diff --git a/src/op.cc b/src/op.cc index c8e099e7..56d3710e 100644 --- a/src/op.cc +++ b/src/op.cc @@ -262,13 +262,18 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) case O_CALL: { ptr_op_t func = left(); - const string& name(func->as_ident()); + string name; - func = func->left(); - if (! func) - func = scope.lookup(symbol_t::FUNCTION, name); - if (! func) - throw_(calc_error, _("Calling unknown function '%1'") << name); + if (func->is_ident()) { + name = func->as_ident(); + func = func->left(); + if (! func) + func = scope.lookup(symbol_t::FUNCTION, name); + if (! func) + throw_(calc_error, _("Calling unknown function '%1'") << name); + } else { + name = ""; + } call_scope_t call_args(scope, locus, depth + 1); if (has_right()) 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,11 +71,40 @@ expr_t::parser_t::parse_value_term(std::istream& in, return node; } + +expr_t::ptr_op_t +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)); + + 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_value_term(in, tflags)); + ptr_op_t node(parse_call_expr(in, tflags)); if (node && ! tflags.has_flags(PARSE_SINGLE)) { while (true) { @@ -98,7 +113,7 @@ expr_t::parser_t::parse_dot_expr(std::istream& in, 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); diff --git a/src/parser.h b/src/parser.h index 75fd9a41..db16a919 100644 --- a/src/parser.h +++ b/src/parser.h @@ -81,6 +81,8 @@ class expr_t::parser_t : public noncopyable ptr_op_t parse_value_term(std::istream& in, const parse_flags_t& flags) const; + ptr_op_t parse_call_expr(std::istream& in, + const parse_flags_t& flags) const; ptr_op_t parse_dot_expr(std::istream& in, const parse_flags_t& flags) const; ptr_op_t parse_unary_expr(std::istream& in,