1 /** @file parser_bugs.cpp
3 * Check for some silly bugs in the parser. */
6 * GiNaC Copyright (C) 1999-2023 Johannes Gutenberg University Mainz, Germany
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 using namespace GiNaC;
33 // - a - b was misparsed as -a + b due to a bug in parser::parse_unary_expr()
34 static int check1(ostream& err_str)
36 const string srep("-a-b");
39 ex a = reader.get_syms()["a"];
40 ex b = reader.get_syms()["b"];
42 ex d = (e - g).expand();
44 err_str << "\"" << srep << "\" was misparsed as \""
51 /// Parser was rejecting the valid expression '5 - (3*x)/10'.
52 static int check2(ostream& err_str)
54 const string srep("5-(3*x)/10");
57 ex x = reader.get_syms()["x"];
59 ex d = (e - g).expand();
61 err_str << "\"" << srep << "\" was misparsed as \""
68 /// parse_literal_expr forget to consume the token, so parser get
70 static int check3(ostream& err_str)
72 const string srep("5-(2*I)/3");
75 ex g = numeric(5) - (numeric(2)*I)/3;
76 ex d = (e - g).expand();
78 err_str << "\"" << srep << "\" was misparsed as \""
85 /// parser happily accepted various junk like 'x^2()+1'
86 static int check4(ostream& err_str)
88 const string junk("x^2()+1");
93 err_str << "parser accepts junk: \"" << junk << "\"" << endl;
95 } catch (parse_error& err) {
96 // Ok, parser rejects the nonsense.
101 // Check that two strings parse to equal expressions.
102 static int check_eq(ostream &err_str, parser &reader, const char *expr1, const char *expr2)
104 const string srep1(expr1);
105 const string srep2(expr2);
107 try{ e1 = reader(srep1); } catch (const exception &e) {
108 err_str << "\"" << srep1 << "\" failed to parse: "
112 try{ e2 = reader(srep2); } catch (const exception &e) {
113 err_str << "\"" << srep2 << "\" failed to parse: "
117 if (!(e1-e2).expand().is_zero()) {
118 err_str << "\"" << srep1 << "\" was misparsed as \""
119 << e1 << "\"" << endl;
125 // Tests for the interaction of the '^' operator with
126 // the unary '+' and the unary '-' operators
127 static int check5(ostream& err_str)
131 +check_eq(err_str, reader, "3^2+1", "10")
132 +check_eq(err_str, reader, "3^+2-1", "8")
133 +check_eq(err_str, reader, "3^-2+1", "10/9")
134 +check_eq(err_str, reader, "3^-2/5", "1/45")
135 +check_eq(err_str, reader, "3^-2*5", "5/9")
136 +check_eq(err_str, reader, "3^-2-5", "-44/9")
137 +check_eq(err_str, reader, "3^(-2)+1", "10/9")
138 +check_eq(err_str, reader, "(3)^(-2)+1", "10/9")
139 +check_eq(err_str, reader, "+3^2+1", "10")
140 +check_eq(err_str, reader, "+3^+2+1", "10")
141 +check_eq(err_str, reader, "+3^-2+1", "10/9")
142 +check_eq(err_str, reader, "+3^-2/5", "1/45")
143 +check_eq(err_str, reader, "+3^-2*5", "5/9")
144 +check_eq(err_str, reader, "+3^-2-5", "-44/9")
145 +check_eq(err_str, reader, "-3^2+1", "-8")
146 +check_eq(err_str, reader, "-3^+2+1", "-8")
147 +check_eq(err_str, reader, "-3^-2+1", "8/9")
148 +check_eq(err_str, reader, "-3^-2/3", "-1/27")
149 +check_eq(err_str, reader, "1+2^3^4", "1+(2^81)")
150 +check_eq(err_str, reader, "2^3^4+1", "1+(2^81)")
151 +check_eq(err_str, reader, "2^+3^4+1", "1+(2^81)")
152 +check_eq(err_str, reader, "2^3^+4+1", "1+(2^81)");
155 // Tests for the interaction of the '*' operator with
156 // the unary '+' and the unary '-' operators
157 static int check6(ostream& err_str)
161 +check_eq(err_str, reader, "3*+2-1", "5")
162 +check_eq(err_str, reader, "3*2+1", "7")
163 +check_eq(err_str, reader, "3*+2+1", "7")
164 +check_eq(err_str, reader, "3*-2+1", "-5")
165 +check_eq(err_str, reader, "3*-2/5", "-6/5")
166 +check_eq(err_str, reader, "3*-2*5", "-30")
167 +check_eq(err_str, reader, "3*-2-5", "-11")
168 +check_eq(err_str, reader, "3*(-2)+1", "-5")
169 +check_eq(err_str, reader, "(3)*(-2)+1", "-5")
170 +check_eq(err_str, reader, "+3*2+1", "7")
171 +check_eq(err_str, reader, "+3*+2+1", "7")
172 +check_eq(err_str, reader, "+3*-2+1", "-5")
173 +check_eq(err_str, reader, "+3*-2/5", "-6/5")
174 +check_eq(err_str, reader, "+3*-2*5", "-30")
175 +check_eq(err_str, reader, "+3*-2-5", "-11")
176 +check_eq(err_str, reader, "-3*2+1", "-5")
177 +check_eq(err_str, reader, "-3*+2+1", "-5")
178 +check_eq(err_str, reader, "-3*-2+1", "7")
179 +check_eq(err_str, reader, "-3*-2/3", "2")
180 +check_eq(err_str, reader, "1+2*3*4", "25")
181 +check_eq(err_str, reader, "2*3*4+1", "25")
182 +check_eq(err_str, reader, "2*+3*4+1", "25")
183 +check_eq(err_str, reader, "2*3*+4+1", "25");
186 // Tests for nested unary + and unary -
187 static int check7(ostream& err_str)
191 +check_eq(err_str, reader, "+1", "1")
192 +check_eq(err_str, reader, "++1", "1")
193 +check_eq(err_str, reader, "+-+1", "-1")
194 +check_eq(err_str, reader, "+-+-1", "1")
195 +check_eq(err_str, reader, "+-+-+1", "1")
196 +check_eq(err_str, reader, "100++--+1+10", "111");
199 int main(int argc, char** argv)
201 cout << "examining old parser bugs" << flush;
202 ostringstream err_str;
204 errors += check1(err_str); cout << '.' << flush;
205 errors += check2(err_str); cout << '.' << flush;
206 errors += check3(err_str); cout << '.' << flush;
207 errors += check4(err_str); cout << '.' << flush;
208 errors += check5(err_str); cout << '.' << flush;
209 errors += check6(err_str); cout << '.' << flush;
210 errors += check7(err_str); cout << '.' << flush;
212 cout << "Yes, unfortunately:" << endl;
213 cout << err_str.str();
215 cout << "Not found. ";