diff options
author | John Wiegley <johnw@newartisans.com> | 2012-03-05 22:01:41 -0600 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2012-03-05 22:01:41 -0600 |
commit | acb5e1beea4176ab51ca2c9d32b006e7c0a7bef0 (patch) | |
tree | e4f890c10c081a88b7e63401b47e4d9781ba90e6 /src/parser.cc | |
parent | 59a16e59ee2e684f1d5292fe78ef94464a935d73 (diff) | |
download | fork-ledger-acb5e1beea4176ab51ca2c9d32b006e7c0a7bef0.tar.gz fork-ledger-acb5e1beea4176ab51ca2c9d32b006e7c0a7bef0.tar.bz2 fork-ledger-acb5e1beea4176ab51ca2c9d32b006e7c0a7bef0.zip |
Generalized function call parsing
Directly calling a lambda now works:
(x -> x + 10)(10) => 20
Diffstat (limited to 'src/parser.cc')
-rw-r--r-- | src/parser.cc | 47 |
1 files changed, 31 insertions, 16 deletions
diff --git a/src/parser.cc b/src/parser.cc index 2c9069d7..b3f50e41 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -54,20 +54,6 @@ expr_t::parser_t::parse_value_term(std::istream& in, node = new op_t(op_t::IDENT); node->set_ident(ident); - - // An identifier followed by ( represents a function call - tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT)); - if (tok.kind == token_t::LPAREN) { - op_t::kind_t kind = op_t::O_CALL; - ptr_op_t call_node(new op_t(kind)); - call_node->set_left(node); - node = call_node; - - push_token(tok); // let the parser see it again - node->set_right(parse_value_expr(in, tflags.plus_flags(PARSE_SINGLE))); - } else { - push_token(tok); - } break; } @@ -85,8 +71,9 @@ expr_t::parser_t::parse_value_term(std::istream& in, return node; } + expr_t::ptr_op_t -expr_t::parser_t::parse_dot_expr(std::istream& in, +expr_t::parser_t::parse_call_expr(std::istream& in, const parse_flags_t& tflags) const { ptr_op_t node(parse_value_term(in, tflags)); @@ -94,11 +81,39 @@ expr_t::parser_t::parse_dot_expr(std::istream& in, if (node && ! tflags.has_flags(PARSE_SINGLE)) { while (true) { token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT)); + if (tok.kind == token_t::LPAREN) { + ptr_op_t prev(node); + node = new op_t(op_t::O_CALL); + node->set_left(prev); + push_token(tok); // let the parser see the '(' again + node->set_right(parse_value_expr(in, tflags.plus_flags(PARSE_SINGLE))); + if (! node->right()) + throw_(parse_error, + _("%1 operator not followed by argument") << tok.symbol); + } else { + push_token(tok); + break; + } + } + } + + return node; +} + +expr_t::ptr_op_t +expr_t::parser_t::parse_dot_expr(std::istream& in, + const parse_flags_t& tflags) const +{ + ptr_op_t node(parse_call_expr(in, tflags)); + + if (node && ! tflags.has_flags(PARSE_SINGLE)) { + while (true) { + token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT)); if (tok.kind == token_t::DOT) { ptr_op_t prev(node); node = new op_t(op_t::O_LOOKUP); node->set_left(prev); - node->set_right(parse_value_term(in, tflags)); + node->set_right(parse_call_expr(in, tflags)); if (! node->right()) throw_(parse_error, _("%1 operator not followed by argument") << tok.symbol); |