parser: improve error reporting a little bit.
authorAlexei Sheplyakov <varg@theor.jinr.ru>
Mon, 25 Aug 2008 15:08:36 +0000 (19:08 +0400)
committerAlexei Sheplyakov <varg@theor.jinr.ru>
Tue, 9 Sep 2008 08:33:06 +0000 (12:33 +0400)
Introduce class 'parse_error' (which contain some info about location of
the error) and throw it on parse errors.

N.B.: the actual info is a bit inaccurate because lexer doesn't track
the location properly yet.

ginac/parser/debug.hpp
ginac/parser/lexer.cpp
ginac/parser/lexer.hpp
ginac/parser/parser.cpp
ginac/parser/parser.hpp

index a43cc7a..5221580 100644 (file)
@@ -20,6 +20,19 @@ do { \
        throw exception(err.str()); \
 } while (0)
 
+#define Parse_error_(message) \
+do { \
+       std::ostringstream err; \
+       err << "GiNaC: parse error at line " << scanner->line_num << \
+               ", column " << scanner->column << ": "; \
+       err << message << std::endl; \
+       err << '[' << __PRETTY_FUNCTION__ << "(" << __FILE__ << ':' << __LINE__ << ")]" << std::endl; \
+       throw parse_error(err.str(), scanner->line_num, scanner->column); \
+} while (0)
+
+#define Parse_error(message) \
+       Parse_error_(message << ", got: " << scanner->tok2str(token))
+
 #define bug(message) bail_out(std::logic_error, message)
 
 #define dout(condition, message) \
index 894a2ad..d8c49b8 100644 (file)
@@ -129,5 +129,19 @@ void lexer::switch_input(std::istream* in)
        c = ' ';
 }
 
+/// Symbolic name of current token (for error reporting)
+std::string lexer::tok2str(const int tok) const
+{
+       switch (tok) {
+               case lexer::token_type::identifier:
+               case lexer::token_type::number:
+                       return std::string("\"") + str + "\"";
+               case lexer::token_type::eof:
+                       return std::string("EOF");
+               default:
+                       return std::string("\"") + char(tok) + "\"";
+       }
+}
+
 } // namespace GiNaC
 
index b53d08f..0a00ed3 100644 (file)
@@ -37,6 +37,9 @@ public:
 
                };
        };
+       
+       /// Symbolic name of the token (for error reporting)
+       std::string tok2str(const int tok) const;
 };
 
 } // namespace GiNaC
index b33261c..1e905cf 100644 (file)
@@ -30,7 +30,7 @@ ex parser::parse_identifier_expr()
                                break;
 
                        if (token != ',')
-                               throw std::invalid_argument("Expected ')' or ',' in argument list");
+                               Parse_error("expected ')' or ',' in argument list");
 
                        get_next_tok();
                }
@@ -40,9 +40,8 @@ ex parser::parse_identifier_expr()
        prototype the_prototype = make_pair(name, args.size());
        prototype_table::const_iterator reader = funcs.find(the_prototype);
        if (reader == funcs.end()) {
-               bail_out(std::invalid_argument,
-                       "no function \"" << name << "\" with " << args.size()
-                       << " arguments");
+               Parse_error_("no function \"" << name << "\" with " <<
+                            args.size() << " arguments");
        }
        ex ret = reader->second(args);
        return ret;
@@ -55,7 +54,7 @@ ex parser::parse_paren_expr()
        ex e = parse_expression();
 
        if (token != ')')
-               throw std::invalid_argument("parser::parse_paren_expr: expected ')'");
+               Parse_error("expected ')'");
        get_next_tok();  // eat ).
        return e;
 }
@@ -74,10 +73,7 @@ ex parser::parse_unary_expr(const int s)
                case '+':
                        return v;
                default:
-                       throw std::invalid_argument(
-                                       std::string(__func__)
-                                       + ": invalid unary operator \""
-                                       + char(s) + "\"");
+                       Parse_error_("invalid unary operator \"" << char(s) << "\"");
        }
 }
 
@@ -98,12 +94,8 @@ ex parser::parse_primary()
                case lexer::token_type::literal:
                         return parse_literal_expr();
                case lexer::token_type::eof:
-                        bail_out(std::invalid_argument, "got EOF while parsing the expression");
                default:
-                        bail_out(std::invalid_argument, "unknown token " <<
-                               token << " (\"" << 
-                               (token ? std::string("") + char(token) : "NULL")
-                               << "\")");
+                        Parse_error("unexpected token");
        }
 }
 
index 81b7847..3e10b8f 100644 (file)
@@ -9,6 +9,18 @@ namespace GiNaC
 
 class lexer;
 
+class parse_error : public std::invalid_argument
+{
+public:
+       const std::size_t line;
+       const std::size_t column;
+       parse_error(const std::string& what_,
+                   const std::size_t line_ = 0,
+                   const std::size_t column_ = 0) throw () :
+               std::invalid_argument(what_), line(line_), column(column_)
+       { }
+};
+
 /**
  * Recursive descent parser for GiNaC expressions.
  */