diff options
author | John Wiegley <johnw@newartisans.com> | 2010-05-22 18:45:42 -0400 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2010-05-22 21:35:03 -0400 |
commit | a3482606dc33b88d2ae661e49c6b15b902497421 (patch) | |
tree | 19d3946e11d0fd8fe0d72859d5bfb3f0e66e7c07 | |
parent | 3e1ec40551184010d6ff3272d68b3ff17ff1ad26 (diff) | |
download | fork-ledger-a3482606dc33b88d2ae661e49c6b15b902497421.tar.gz fork-ledger-a3482606dc33b88d2ae661e49c6b15b902497421.tar.bz2 fork-ledger-a3482606dc33b88d2ae661e49c6b15b902497421.zip |
Improved error reporting in the expression parser
Fixes 15A80F68-F233-49D9-AF0C-9908BB6903BA
-rw-r--r-- | src/parser.cc | 9 | ||||
-rw-r--r-- | src/parser.h | 5 | ||||
-rw-r--r-- | src/token.cc | 47 | ||||
-rw-r--r-- | src/token.h | 7 |
4 files changed, 45 insertions, 23 deletions
diff --git a/src/parser.cc b/src/parser.cc index e8e987cb..f52949ce 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -79,9 +79,7 @@ expr_t::parser_t::parse_value_term(std::istream& in, case token_t::LPAREN: node = parse_value_expr(in, tflags.plus_flags(PARSE_PARTIAL) .minus_flags(PARSE_SINGLE)); - tok = next_token(in, tflags); - if (tok.kind != token_t::RPAREN) - tok.expected(')'); + tok = next_token(in, tflags, ')'); if (node->kind == op_t::O_CONS) { ptr_op_t prev(node); @@ -383,10 +381,7 @@ expr_t::parser_t::parse_querycolon_expr(std::istream& in, throw_(parse_error, _("%1 operator not followed by argument") << tok.symbol); - token_t& next_tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT)); - if (next_tok.kind != token_t::COLON) - next_tok.expected(':'); - + next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT), ':'); prev = node->right(); ptr_op_t subnode = new op_t(op_t::O_COLON); subnode->set_left(prev); diff --git a/src/parser.h b/src/parser.h index 5eba4ffd..aab48830 100644 --- a/src/parser.h +++ b/src/parser.h @@ -52,11 +52,12 @@ class expr_t::parser_t : public noncopyable mutable token_t lookahead; mutable bool use_lookahead; - token_t& next_token(std::istream& in, const parse_flags_t& tflags) const { + token_t& next_token(std::istream& in, const parse_flags_t& tflags, + const char expecting = '\0') const { if (use_lookahead) use_lookahead = false; else - lookahead.next(in, tflags); + lookahead.next(in, tflags, expecting); return lookahead; } diff --git a/src/token.cc b/src/token.cc index a34cdcd0..add97b8b 100644 --- a/src/token.cc +++ b/src/token.cc @@ -138,7 +138,8 @@ void expr_t::token_t::parse_ident(std::istream& in) value.set_string(buf); } -void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags) +void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags, + const char expecting) { if (in.eof()) { kind = TOK_EOF; @@ -423,6 +424,13 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags) expected('\0', c); parse_ident(in); + + if (value.as_string().length() == 0) { + kind = ERROR; + symbol[0] = c; + symbol[1] = '\0'; + unexpected(expecting); + } } else { kind = VALUE; value = temp; @@ -447,21 +455,38 @@ void expr_t::token_t::rewind(std::istream& in) } -void expr_t::token_t::unexpected() +void expr_t::token_t::unexpected(const char wanted) { kind_t prev_kind = kind; kind = ERROR; - switch (prev_kind) { - case TOK_EOF: - throw_(parse_error, _("Unexpected end of expression")); - case IDENT: - throw_(parse_error, _("Unexpected symbol '%1'") << value); - case VALUE: - throw_(parse_error, _("Unexpected value '%1'") << value); - default: - throw_(parse_error, _("Unexpected token '%1'") << symbol); + if (wanted == '\0') { + switch (prev_kind) { + case TOK_EOF: + throw_(parse_error, _("Unexpected end of expression")); + case IDENT: + throw_(parse_error, _("Unexpected symbol '%1'") << value); + case VALUE: + throw_(parse_error, _("Unexpected value '%1'") << value); + default: + throw_(parse_error, _("Unexpected expression token '%1'") << symbol); + } + } else { + switch (prev_kind) { + case TOK_EOF: + throw_(parse_error, + _("Unexpected end of expression (wanted '%1')" << wanted)); + case IDENT: + throw_(parse_error, + _("Unexpected symbol '%1' (wanted '%2')") << value << wanted); + case VALUE: + throw_(parse_error, + _("Unexpected value '%1' (wanted '%2')") << value << wanted); + default: + throw_(parse_error, _("Unexpected expression token '%1' (wanted '%2')") + << symbol << wanted); + } } } diff --git a/src/token.h b/src/token.h index 8d70996b..582373cb 100644 --- a/src/token.h +++ b/src/token.h @@ -124,10 +124,11 @@ struct expr_t::token_t : public noncopyable int parse_reserved_word(std::istream& in); void parse_ident(std::istream& in); - void next(std::istream& in, const parse_flags_t& flags); + void next(std::istream& in, const parse_flags_t& flags, + const char expecting = '\0'); void rewind(std::istream& in); - void unexpected(); - void expected(char wanted, char c = '\0'); + void unexpected(const char wanted = '\0'); + void expected(const char wanted, char c = '\0'); }; } // namespace ledger |