Generalized function call parsing
Directly calling a lambda now works: (x -> x + 10)(10) => 20
This commit is contained in:
parent
59a16e59ee
commit
acb5e1beea
3 changed files with 44 additions and 22 deletions
17
src/op.cc
17
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: {
|
case O_CALL: {
|
||||||
ptr_op_t func = left();
|
ptr_op_t func = left();
|
||||||
const string& name(func->as_ident());
|
string name;
|
||||||
|
|
||||||
func = func->left();
|
if (func->is_ident()) {
|
||||||
if (! func)
|
name = func->as_ident();
|
||||||
func = scope.lookup(symbol_t::FUNCTION, name);
|
func = func->left();
|
||||||
if (! func)
|
if (! func)
|
||||||
throw_(calc_error, _("Calling unknown function '%1'") << name);
|
func = scope.lookup(symbol_t::FUNCTION, name);
|
||||||
|
if (! func)
|
||||||
|
throw_(calc_error, _("Calling unknown function '%1'") << name);
|
||||||
|
} else {
|
||||||
|
name = "<lambda>";
|
||||||
|
}
|
||||||
|
|
||||||
call_scope_t call_args(scope, locus, depth + 1);
|
call_scope_t call_args(scope, locus, depth + 1);
|
||||||
if (has_right())
|
if (has_right())
|
||||||
|
|
|
||||||
|
|
@ -54,20 +54,6 @@ expr_t::parser_t::parse_value_term(std::istream& in,
|
||||||
|
|
||||||
node = new op_t(op_t::IDENT);
|
node = new op_t(op_t::IDENT);
|
||||||
node->set_ident(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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,11 +71,40 @@ expr_t::parser_t::parse_value_term(std::istream& in,
|
||||||
return node;
|
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::ptr_op_t
|
||||||
expr_t::parser_t::parse_dot_expr(std::istream& in,
|
expr_t::parser_t::parse_dot_expr(std::istream& in,
|
||||||
const parse_flags_t& tflags) const
|
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)) {
|
if (node && ! tflags.has_flags(PARSE_SINGLE)) {
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
@ -98,7 +113,7 @@ expr_t::parser_t::parse_dot_expr(std::istream& in,
|
||||||
ptr_op_t prev(node);
|
ptr_op_t prev(node);
|
||||||
node = new op_t(op_t::O_LOOKUP);
|
node = new op_t(op_t::O_LOOKUP);
|
||||||
node->set_left(prev);
|
node->set_left(prev);
|
||||||
node->set_right(parse_value_term(in, tflags));
|
node->set_right(parse_call_expr(in, tflags));
|
||||||
if (! node->right())
|
if (! node->right())
|
||||||
throw_(parse_error,
|
throw_(parse_error,
|
||||||
_("%1 operator not followed by argument") << tok.symbol);
|
_("%1 operator not followed by argument") << tok.symbol);
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,8 @@ class expr_t::parser_t : public noncopyable
|
||||||
|
|
||||||
ptr_op_t parse_value_term(std::istream& in,
|
ptr_op_t parse_value_term(std::istream& in,
|
||||||
const parse_flags_t& flags) const;
|
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,
|
ptr_op_t parse_dot_expr(std::istream& in,
|
||||||
const parse_flags_t& flags) const;
|
const parse_flags_t& flags) const;
|
||||||
ptr_op_t parse_unary_expr(std::istream& in,
|
ptr_op_t parse_unary_expr(std::istream& in,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue