diff options
Diffstat (limited to 'src/parser.cc')
-rw-r--r-- | src/parser.cc | 102 |
1 files changed, 88 insertions, 14 deletions
diff --git a/src/parser.cc b/src/parser.cc index a5b1e6e3..e9205d16 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -232,15 +232,12 @@ expr_t::parser_t::parse_logic_expr(std::istream& in, if (node && ! tflags.has_flags(PARSE_SINGLE)) { while (true) { - op_t::kind_t kind = op_t::LAST; + op_t::kind_t kind = op_t::LAST; parse_flags_t _flags = tflags; - token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT)); - bool negate = false; + token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT)); + bool negate = false; switch (tok.kind) { - case token_t::DEFINE: - kind = op_t::O_DEFINE; - break; case token_t::EQUAL: if (tflags.has_flags(PARSE_NO_ASSIGN)) tok.rewind(in); @@ -422,22 +419,42 @@ expr_t::parser_t::parse_querycolon_expr(std::istream& in, } expr_t::ptr_op_t -expr_t::parser_t::parse_value_expr(std::istream& in, - const parse_flags_t& tflags) const +expr_t::parser_t::parse_lambda_expr(std::istream& in, + const parse_flags_t& tflags) const { ptr_op_t node(parse_querycolon_expr(in, tflags)); if (node && ! tflags.has_flags(PARSE_SINGLE)) { + token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT)); + + if (tok.kind == token_t::ARROW) { + ptr_op_t prev(node); + node = new op_t(op_t::O_LAMBDA); + node->set_left(prev); + node->set_right(parse_querycolon_expr(in, tflags)); + } else { + push_token(tok); + } + } + + return node; +} + +expr_t::ptr_op_t +expr_t::parser_t::parse_comma_expr(std::istream& in, + const parse_flags_t& tflags) const +{ + ptr_op_t node(parse_lambda_expr(in, tflags)); + + if (node && ! tflags.has_flags(PARSE_SINGLE)) { ptr_op_t next; while (true) { token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT)); - if (tok.kind == token_t::COMMA || tok.kind == token_t::SEMI) { - bool comma_op = tok.kind == token_t::COMMA; - + if (tok.kind == token_t::COMMA) { if (! next) { ptr_op_t prev(node); - node = new op_t(comma_op ? op_t::O_CONS : op_t::O_SEQ); + node = new op_t(op_t::O_CONS); node->set_left(prev); next = node; @@ -448,8 +465,65 @@ expr_t::parser_t::parse_value_expr(std::istream& in, if (ntok.kind == token_t::RPAREN) break; - ptr_op_t chain(new op_t(comma_op ? op_t::O_CONS : op_t::O_SEQ)); - chain->set_left(parse_querycolon_expr(in, tflags)); + ptr_op_t chain(new op_t(op_t::O_CONS)); + chain->set_left(parse_lambda_expr(in, tflags)); + + next->set_right(chain); + next = chain; + } else { + push_token(tok); + break; + } + } + } + + return node; +} + +expr_t::ptr_op_t +expr_t::parser_t::parse_assign_expr(std::istream& in, + const parse_flags_t& tflags) const +{ + ptr_op_t node(parse_comma_expr(in, tflags)); + + if (node && ! tflags.has_flags(PARSE_SINGLE)) { + token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT)); + + if (tok.kind == token_t::ASSIGN) { + ptr_op_t prev(node); + node = new op_t(op_t::O_DEFINE); + node->set_left(prev); + node->set_right(parse_comma_expr(in, tflags)); + } else { + push_token(tok); + } + } + + return node; +} + +expr_t::ptr_op_t +expr_t::parser_t::parse_value_expr(std::istream& in, + const parse_flags_t& tflags) const +{ + ptr_op_t node(parse_assign_expr(in, tflags)); + + if (node && ! tflags.has_flags(PARSE_SINGLE)) { + ptr_op_t next; + while (true) { + token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT)); + + if (tok.kind == token_t::SEMI) { + if (! next) { + ptr_op_t prev(node); + node = new op_t(op_t::O_SEQ); + node->set_left(prev); + + next = node; + } + + ptr_op_t chain(new op_t(op_t::O_SEQ)); + chain->set_left(parse_assign_expr(in, tflags)); next->set_right(chain); next = chain; |