diff options
-rw-r--r-- | parser.cc | 42 | ||||
-rw-r--r-- | token.cc | 22 | ||||
-rw-r--r-- | token.h | 5 |
3 files changed, 59 insertions, 10 deletions
@@ -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); @@ -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 @@ -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 |