summaryrefslogtreecommitdiff
path: root/src/parser.cc
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2010-09-06 00:33:03 -0400
committerJohn Wiegley <johnw@newartisans.com>2010-09-06 00:56:00 -0400
commit84780270f9bc427f6edcd295b68ffcf6b911baf6 (patch)
tree7b151bbc02ab30bad5c3636cfefd4d5cd4a419da /src/parser.cc
parente162455ebb545ea33580e58f52ebe424ef9e68fa (diff)
downloadfork-ledger-84780270f9bc427f6edcd295b68ffcf6b911baf6.tar.gz
fork-ledger-84780270f9bc427f6edcd295b68ffcf6b911baf6.tar.bz2
fork-ledger-84780270f9bc427f6edcd295b68ffcf6b911baf6.zip
Added initial support for lambda functions
Diffstat (limited to 'src/parser.cc')
-rw-r--r--src/parser.cc102
1 files changed, 88 insertions, 14 deletions
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;