summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2010-05-22 18:45:42 -0400
committerJohn Wiegley <johnw@newartisans.com>2010-05-22 21:35:03 -0400
commita3482606dc33b88d2ae661e49c6b15b902497421 (patch)
tree19d3946e11d0fd8fe0d72859d5bfb3f0e66e7c07
parent3e1ec40551184010d6ff3272d68b3ff17ff1ad26 (diff)
downloadfork-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.cc9
-rw-r--r--src/parser.h5
-rw-r--r--src/token.cc47
-rw-r--r--src/token.h7
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