diff options
Diffstat (limited to 'src/parser.cc')
-rw-r--r-- | src/parser.cc | 135 |
1 files changed, 102 insertions, 33 deletions
diff --git a/src/parser.cc b/src/parser.cc index 9a1ebf6f..f0085295 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -65,9 +65,6 @@ expr_t::parser_t::parse_value_term(std::istream& in, push_token(tok); // let the parser see it again node->set_right(parse_value_expr(in, tflags.plus_flags(PARSE_SINGLE))); - - if (node->has_right() && node->right()->kind == op_t::O_CONS) - node->set_right(node->right()->left()); } else { push_token(tok); } @@ -78,12 +75,6 @@ expr_t::parser_t::parse_value_term(std::istream& in, node = parse_value_expr(in, tflags.plus_flags(PARSE_PARTIAL) .minus_flags(PARSE_SINGLE)); tok = next_token(in, tflags, ')'); - - if (node && node->kind == op_t::O_CONS) { - ptr_op_t prev(node); - node = new op_t(op_t::O_SEQ); - node->set_left(prev); - } break; default: @@ -241,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); @@ -431,39 +419,120 @@ 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, +expr_t::parser_t::parse_comma_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)); + 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(op_t::O_CONS); + node->set_left(prev); + + next = node; + } + + token_t& ntok = next_token(in, tflags); + push_token(ntok); + if (ntok.kind == token_t::RPAREN) + break; + + ptr_op_t chain(new op_t(op_t::O_CONS)); + chain->set_left(parse_querycolon_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_lambda_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::ARROW) { 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_LAMBDA); node->set_left(prev); - node->set_right(parse_value_expr(in, tflags)); - if (! node->right()) - throw_(parse_error, - _("%1 operator not followed by argument") << tok.symbol); + node->set_right(parse_querycolon_expr(in, tflags)); + } else { + push_token(tok); + } + } - tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT)); + 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_lambda_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_lambda_expr(in, tflags)); + } else { + push_token(tok); } + } + + return node; +} - if (tok.kind != token_t::TOK_EOF) { - if (tflags.has_flags(PARSE_PARTIAL)) +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; + } else { push_token(tok); - else - tok.unexpected(); + break; + } } } - else if (! tflags.has_flags(PARSE_PARTIAL) && - ! tflags.has_flags(PARSE_SINGLE)) { - throw_(parse_error, _("Failed to parse value expression")); - } return node; } |