diff options
author | John Wiegley <johnw@newartisans.com> | 2010-09-06 00:33:03 -0400 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2010-09-06 00:56:00 -0400 |
commit | 84780270f9bc427f6edcd295b68ffcf6b911baf6 (patch) | |
tree | 7b151bbc02ab30bad5c3636cfefd4d5cd4a419da /src | |
parent | e162455ebb545ea33580e58f52ebe424ef9e68fa (diff) | |
download | fork-ledger-84780270f9bc427f6edcd295b68ffcf6b911baf6.tar.gz fork-ledger-84780270f9bc427f6edcd295b68ffcf6b911baf6.tar.bz2 fork-ledger-84780270f9bc427f6edcd295b68ffcf6b911baf6.zip |
Added initial support for lambda functions
Diffstat (limited to 'src')
-rw-r--r-- | src/op.cc | 32 | ||||
-rw-r--r-- | src/op.h | 1 | ||||
-rw-r--r-- | src/parser.cc | 102 | ||||
-rw-r--r-- | src/parser.h | 6 | ||||
-rw-r--r-- | src/token.cc | 11 | ||||
-rw-r--r-- | src/token.h | 4 |
6 files changed, 129 insertions, 27 deletions
@@ -108,10 +108,15 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth) scope.define(symbol_t::FUNCTION, left()->as_ident(), right()); break; case O_CALL: - if (left()->left()->is_ident()) - scope.define(symbol_t::FUNCTION, left()->left()->as_ident(), this); - else + if (left()->left()->is_ident()) { + ptr_op_t node(new op_t(op_t::O_LAMBDA)); + node->set_left(left()->right()); + node->set_right(right()); + + scope.define(symbol_t::FUNCTION, left()->left()->as_ident(), node); + } else { throw_(compile_error, _("Invalid function definition")); + } break; default: throw_(compile_error, _("Invalid function definition")); @@ -183,16 +188,12 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) break; } - case O_DEFINE: { + case O_LAMBDA: { call_scope_t& call_args(downcast<call_scope_t>(scope)); - std::size_t args_count = call_args.size(); - std::size_t args_index = 0; - - assert(left()->kind == O_CALL); - - ptr_op_t sym = left()->right(); - + std::size_t args_count(call_args.size()); + std::size_t args_index(0); symbol_scope_t call_scope(call_args); + ptr_op_t sym(left()); for (; sym; sym = sym->has_right() ? sym->right() : NULL) { ptr_op_t varname = sym; @@ -618,6 +619,14 @@ bool expr_t::op_t::print(std::ostream& out, const context_t& context) const found = true; break; + case O_LAMBDA: + if (left() && left()->print(out, context)) + found = true; + out << " -> "; + if (has_right() && right()->print(out, context)) + found = true; + break; + case O_CALL: if (left() && left()->print(out, context)) found = true; @@ -692,6 +701,7 @@ void expr_t::op_t::dump(std::ostream& out, const int depth) const case O_DEFINE: out << "O_DEFINE"; break; case O_LOOKUP: out << "O_LOOKUP"; break; + case O_LAMBDA: out << "O_LAMBDA"; break; case O_CALL: out << "O_CALL"; break; case O_MATCH: out << "O_MATCH"; break; @@ -104,6 +104,7 @@ public: O_DEFINE, O_LOOKUP, + O_LAMBDA, O_CALL, O_MATCH, 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; diff --git a/src/parser.h b/src/parser.h index 93ea994f..9a65765d 100644 --- a/src/parser.h +++ b/src/parser.h @@ -93,6 +93,12 @@ class expr_t::parser_t : public noncopyable const parse_flags_t& flags) const; ptr_op_t parse_querycolon_expr(std::istream& in, const parse_flags_t& flags) const; + ptr_op_t parse_comma_expr(std::istream& in, + const parse_flags_t& flags) const; + ptr_op_t parse_lambda_expr(std::istream& in, + const parse_flags_t& flags) const; + ptr_op_t parse_assign_expr(std::istream& in, + const parse_flags_t& flags) const; ptr_op_t parse_value_expr(std::istream& in, const parse_flags_t& flags) const; diff --git a/src/token.cc b/src/token.cc index be39205c..199c3b3c 100644 --- a/src/token.cc +++ b/src/token.cc @@ -269,6 +269,15 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags, case '-': in.get(c); + c = static_cast<char>(in.peek()); + if (c == '>') { + in.get(c); + symbol[1] = c; + symbol[2] = '\0'; + kind = ARROW; + length = 2; + break; + } kind = MINUS; break; case '+': @@ -329,7 +338,7 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags, length = 2; break; } - kind = DEFINE; + kind = ASSIGN; break; case '<': diff --git a/src/token.h b/src/token.h index 28e29752..13a799cb 100644 --- a/src/token.h +++ b/src/token.h @@ -56,6 +56,8 @@ struct expr_t::token_t : public noncopyable LPAREN, // ( RPAREN, // ) + LBRACE, // { + RBRACE, // } EQUAL, // == NEQUAL, // != @@ -64,7 +66,6 @@ struct expr_t::token_t : public noncopyable GREATER, // > GREATEREQ, // >= - DEFINE, // := ASSIGN, // = MATCH, // =~ NMATCH, // !~ @@ -72,6 +73,7 @@ struct expr_t::token_t : public noncopyable PLUS, // + STAR, // * SLASH, // / + ARROW, // -> KW_DIV, // div EXCLAM, // !, not |