summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--parser.cc42
-rw-r--r--token.cc22
-rw-r--r--token.h5
3 files changed, 59 insertions, 10 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);
diff --git a/token.cc b/token.cc
index adc7069f..27180e99 100644
--- a/token.cc
+++ b/token.cc
@@ -164,7 +164,7 @@ void expr_t::token_t::next(std::istream& in, const unsigned int pflags)
char buf[256];
READ_INTO_(in, buf, 255, c, length, c != ']');
if (c != ']')
- unexpected(c, ']');
+ expected(']', c);
in.get(c);
length++;
@@ -182,7 +182,7 @@ void expr_t::token_t::next(std::istream& in, const unsigned int pflags)
char buf[4096];
READ_INTO_(in, buf, 4095, c, length, c != delim);
if (c != delim)
- unexpected(c, delim);
+ expected(delim, c);
in.get(c);
length++;
kind = VALUE;
@@ -196,7 +196,7 @@ void expr_t::token_t::next(std::istream& in, const unsigned int pflags)
temp.parse(in, AMOUNT_PARSE_NO_MIGRATE);
in.get(c);
if (c != '}')
- unexpected(c, '}');
+ expected('}', c);
length++;
kind = VALUE;
value = temp;
@@ -231,6 +231,16 @@ void expr_t::token_t::next(std::istream& in, const unsigned int pflags)
kind = STAR;
break;
+ case '?':
+ in.get(c);
+ kind = QUERY;
+ break;
+
+ case ':':
+ in.get(c);
+ kind = COLON;
+ break;
+
case 'c':
case 'C':
case 'p':
@@ -266,7 +276,7 @@ void expr_t::token_t::next(std::istream& in, const unsigned int pflags)
char buf[256];
READ_INTO_(in, buf, 255, c, length, c != '/');
if (c != '/')
- unexpected(c, '/');
+ expected('/', c);
in.get(c);
length++;
@@ -379,9 +389,9 @@ void expr_t::token_t::unexpected()
}
}
-void expr_t::token_t::unexpected(char c, char wanted)
+void expr_t::token_t::expected(char wanted, char c)
{
- if (static_cast<unsigned char>(c) == 0xff) {
+ if (c == '\0') {
if (wanted)
throw_(parse_error, "Missing '" << wanted << "'");
else
diff --git a/token.h b/token.h
index df08b6bc..cc3ec988 100644
--- a/token.h
+++ b/token.h
@@ -71,6 +71,9 @@ struct expr_t::token_t : public noncopyable, public supports_flags<>
KW_OR, // |
KW_MOD, // %
+ QUERY, // ?
+ COLON, // :
+
COMMA, // ,
TOK_EOF,
@@ -111,7 +114,7 @@ struct expr_t::token_t : public noncopyable, public supports_flags<>
void rewind(std::istream& in);
void unexpected();
- static void unexpected(char c, char wanted = '\0');
+ static void expected(char wanted, char c = '\0');
};
} // namespace ledger