summaryrefslogtreecommitdiff
path: root/parser.cc
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2008-08-01 01:56:13 -0400
committerJohn Wiegley <johnw@newartisans.com>2008-08-01 01:56:13 -0400
commitc98be731733176c9e9afb690619d806630ec9090 (patch)
treeaedd210699a652a2b77b2a1985c14a1bdd9c227a /parser.cc
parent567902b1731db6f1ace85a7bc384b55ffd0948ab (diff)
downloadledger-c98be731733176c9e9afb690619d806630ec9090.tar.gz
ledger-c98be731733176c9e9afb690619d806630ec9090.tar.bz2
ledger-c98be731733176c9e9afb690619d806630ec9090.zip
Re-implemented ?: parsing in value expressions. "a ? b : c" is implemented by
translating it into the equivalent syntax tree "(a & b) | c", since this expression evaluates to the value of b if a is true, otherwise c.
Diffstat (limited to 'parser.cc')
-rw-r--r--parser.cc42
1 files changed, 39 insertions, 3 deletions
diff --git a/parser.cc b/parser.cc
index 85d92901..6eae2f1c 100644
--- a/parser.cc
+++ b/parser.cc
@@ -134,7 +134,7 @@ expr_t::parser_t::parse_value_term(std::istream& in,
tok = next_token(in, tflags);
if (tok.kind != token_t::RPAREN)
- tok.unexpected(0xff, ')');
+ tok.expected(')');
node = call_node;
} else {
@@ -158,7 +158,7 @@ expr_t::parser_t::parse_value_term(std::istream& in,
tok = next_token(in, tflags);
if (tok.kind != token_t::RPAREN)
- tok.unexpected(0xff, ')');
+ tok.expected(')');
break;
default:
@@ -383,10 +383,46 @@ expr_t::parser_t::parse_or_expr(std::istream& in,
}
expr_t::ptr_op_t
+expr_t::parser_t::parse_querycolon_expr(std::istream& in,
+ const flags_t tflags) const
+{
+ ptr_op_t node(parse_or_expr(in, tflags));
+
+ if (node) {
+ token_t& tok = next_token(in, tflags);
+
+ if (tok.kind == token_t::QUERY) {
+ ptr_op_t prev(node);
+ node = new op_t(op_t::O_AND);
+ node->set_left(prev);
+ node->set_right(parse_or_expr(in, tflags));
+ if (! node->right())
+ throw_(parse_error,
+ tok.symbol << " operator not followed by argument");
+
+ token_t& next_tok = next_token(in, tflags);
+ if (next_tok.kind != token_t::COLON)
+ next_tok.expected(':');
+
+ prev = node;
+ node = new op_t(op_t::O_OR);
+ node->set_left(prev);
+ node->set_right(parse_or_expr(in, tflags));
+ if (! node->right())
+ throw_(parse_error,
+ tok.symbol << " operator not followed by argument");
+ } else {
+ push_token(tok);
+ }
+ }
+ return node;
+}
+
+expr_t::ptr_op_t
expr_t::parser_t::parse_value_expr(std::istream& in,
const flags_t tflags) const
{
- ptr_op_t node(parse_or_expr(in, tflags));
+ ptr_op_t node(parse_querycolon_expr(in, tflags));
if (node) {
token_t& tok = next_token(in, tflags);