[bugfix]: parser::parse_unary_expr() parses '-a-b' correctly now.
authorAlexei Sheplyakov <varg@theor.jinr.ru>
Sat, 13 Sep 2008 23:19:05 +0000 (03:19 +0400)
committerAlexei Sheplyakov <varg@theor.jinr.ru>
Fri, 19 Sep 2008 09:15:49 +0000 (13:15 +0400)
Also added regression test.

check/Makefile.am
check/parser_bugs.cpp [new file with mode: 0644]
ginac/parser/parser.cpp
ginac/parser/parser.hpp

index de86f5c..87b489d 100644 (file)
@@ -8,6 +8,7 @@ CHECKS = check_numeric \
 EXAMS = exam_paranoia \
        exam_heur_gcd \
        match_bug \
+       parser_bugs \
        exam_numeric_archive \
        exam_numeric \
        exam_powerlaws  \
@@ -78,6 +79,9 @@ exam_heur_gcd_LDADD = ../ginac/libginac.la
 match_bug_SOURCES = match_bug.cpp error_report.hpp
 match_bug_LDADD = ../ginac/libginac.la
 
+parser_bugs_SOURCES = parser_bugs.cpp
+parser_bugs_LDADD = ../ginac/libginac.la
+
 exam_numeric_archive_SOURCES = numeric_archive.cpp
 exam_numeric_archive_LDADD = ../ginac/libginac.la
 
diff --git a/check/parser_bugs.cpp b/check/parser_bugs.cpp
new file mode 100644 (file)
index 0000000..340fe20
--- /dev/null
@@ -0,0 +1,59 @@
+/// @file parser_a_b.cpp Check for some silly bugs in the parser.
+#include "ginac.h"
+#include <string>
+#include <iostream>
+#include <stdexcept>
+#include <sstream>
+using namespace GiNaC;
+
+// - a - b was misparsed as -a + b due to a bug in parser::parse_unary_expr()
+static int check1(std::ostream& err_str)
+{
+       const std::string srep("-a-b");
+       parser reader;
+       ex e = reader(srep);
+       ex a = reader.get_syms()["a"];
+       ex b = reader.get_syms()["b"];
+       ex g = - a - b;
+       ex d = (e - g).expand();
+       if (!d.is_zero()) {
+               err_str << "\"" << srep << "\" was misparsed as \""
+                       << e << "\"" << std::endl;
+               return 1;
+       }
+       return 0;
+}
+
+/// Parser was rejecting the valid expression '5 - (3*x)/10'.
+static int check2(std::ostream& err_str)
+{
+       const std::string srep("5-(3*x)/10");
+       parser reader;
+       ex e = reader(srep);
+       ex x = reader.get_syms()["x"];
+       ex g = 5 - (3*x)/10;
+       ex d = (e - g).expand();
+       if (!d.is_zero()) {
+               err_str << "\"" << srep << "\" was misparsed as \""
+                       << e << "\"" << std::endl;
+               return 1;
+       }
+       return 0;
+}
+
+int main(int argc, char** argv)
+{
+       std::cout << "checking for parser bugs. " << std::flush;
+       std::ostringstream err_str;
+       int errors = 0;
+       errors += check1(err_str);
+       errors += check2(err_str);
+       if (errors) {
+               std::cout << "Yes, unfortunately:" << std::endl;
+               std::cout << err_str.str();
+       } else {
+               std::cout << "Not found. ";
+       }
+       return errors;
+}
+
index 0ee682a..f48d37f 100644 (file)
@@ -60,21 +60,25 @@ ex parser::parse_paren_expr()
 }
 
 extern numeric* _num_1_p;
+extern ex _ex0;
 
 /// unary_expr: [+-] expression
-ex parser::parse_unary_expr(const int s)
+ex parser::parse_unary_expr()
 {
-       // consume '-' (or '+')
-       get_next_tok();
-       ex v = parse_expression();
-       switch (s) {
-               case '-':
-                       return (new mul(v, *_num_1_p))->setflag(status_flags::dynallocated);
-               case '+':
-                       return v;
-               default:
-                       Parse_error_("invalid unary operator \"" << char(s) << "\"");
-       }
+       // Unlike most other parse_* method this one does NOT consume
+       // current token so parse_binop_rhs() knows what kind of operator
+       // is being parsed.
+       
+       // There are different kinds of expressions which need to be handled:
+       // -a+b 
+       // -(a) 
+       // +a
+       // +(a)
+       // Delegete the work to parse_binop_rhs(), otherwise we end up
+       // duplicating it here. 
+       ex lhs = _ex0; // silly trick
+       ex e = parse_binop_rhs(0, lhs);
+       return e;
 }
 
 /// primary: identifier_expr | number_expr | paren_expr | unary_expr 
@@ -88,9 +92,8 @@ ex parser::parse_primary()
                case '(': 
                         return parse_paren_expr();
                case '-':
-                        return parse_unary_expr('-');
                case '+':
-                        return parse_unary_expr('+');
+                        return parse_unary_expr();
                case lexer::token_type::literal:
                         return parse_literal_expr();
                case lexer::token_type::eof:
index eb50adc..b46ec65 100644 (file)
@@ -49,7 +49,7 @@ class parser
        ex parse_number_expr();
 
        /// unary_expr: [+-] expression
-       ex parse_unary_expr(const int c);
+       ex parse_unary_expr();
 
        /// literal_expr: 'I' | 'Pi' | 'Euler' | 'Catalan'
        ex parse_literal_expr();