Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/third_party/ply/test/testyacc.py
6162 views
1
# testyacc.py
2
3
import unittest
4
try:
5
import StringIO
6
except ImportError:
7
import io as StringIO
8
9
import sys
10
import os
11
import warnings
12
13
sys.path.insert(0,"..")
14
sys.tracebacklimit = 0
15
16
import ply.yacc
17
import imp
18
19
def make_pymodule_path(filename):
20
path = os.path.dirname(filename)
21
file = os.path.basename(filename)
22
mod, ext = os.path.splitext(file)
23
24
if sys.hexversion >= 0x3020000:
25
modname = mod+"."+imp.get_tag()+ext
26
fullpath = os.path.join(path,'__pycache__',modname)
27
else:
28
fullpath = filename
29
return fullpath
30
31
def pymodule_out_exists(filename):
32
return os.path.exists(make_pymodule_path(filename))
33
34
def pymodule_out_remove(filename):
35
os.remove(make_pymodule_path(filename))
36
37
38
def check_expected(result,expected):
39
resultlines = []
40
for line in result.splitlines():
41
if line.startswith("WARNING: "):
42
line = line[9:]
43
elif line.startswith("ERROR: "):
44
line = line[7:]
45
resultlines.append(line)
46
47
expectedlines = expected.splitlines()
48
if len(resultlines) != len(expectedlines):
49
return False
50
for rline,eline in zip(resultlines,expectedlines):
51
if not rline.endswith(eline):
52
return False
53
return True
54
55
def run_import(module):
56
code = "import "+module
57
exec(code)
58
del sys.modules[module]
59
60
# Tests related to errors and warnings when building parsers
61
class YaccErrorWarningTests(unittest.TestCase):
62
def setUp(self):
63
sys.stderr = StringIO.StringIO()
64
sys.stdout = StringIO.StringIO()
65
try:
66
os.remove("parsetab.py")
67
pymodule_out_remove("parsetab.pyc")
68
except OSError:
69
pass
70
71
if sys.hexversion >= 0x3020000:
72
warnings.filterwarnings('ignore',category=ResourceWarning)
73
74
def tearDown(self):
75
sys.stderr = sys.__stderr__
76
sys.stdout = sys.__stdout__
77
def test_yacc_badargs(self):
78
self.assertRaises(ply.yacc.YaccError,run_import,"yacc_badargs")
79
result = sys.stderr.getvalue()
80
self.assert_(check_expected(result,
81
"yacc_badargs.py:23: Rule 'p_statement_assign' has too many arguments\n"
82
"yacc_badargs.py:27: Rule 'p_statement_expr' requires an argument\n"
83
))
84
def test_yacc_badid(self):
85
self.assertRaises(ply.yacc.YaccError,run_import,"yacc_badid")
86
result = sys.stderr.getvalue()
87
self.assert_(check_expected(result,
88
"yacc_badid.py:32: Illegal name 'bad&rule' in rule 'statement'\n"
89
"yacc_badid.py:36: Illegal rule name 'bad&rule'\n"
90
))
91
92
def test_yacc_badprec(self):
93
try:
94
run_import("yacc_badprec")
95
except ply.yacc.YaccError:
96
result = sys.stderr.getvalue()
97
self.assert_(check_expected(result,
98
"precedence must be a list or tuple\n"
99
))
100
def test_yacc_badprec2(self):
101
self.assertRaises(ply.yacc.YaccError,run_import,"yacc_badprec2")
102
result = sys.stderr.getvalue()
103
self.assert_(check_expected(result,
104
"Bad precedence table\n"
105
))
106
107
def test_yacc_badprec3(self):
108
run_import("yacc_badprec3")
109
result = sys.stderr.getvalue()
110
self.assert_(check_expected(result,
111
"Precedence already specified for terminal 'MINUS'\n"
112
"Generating LALR tables\n"
113
114
))
115
116
def test_yacc_badrule(self):
117
self.assertRaises(ply.yacc.YaccError,run_import,"yacc_badrule")
118
result = sys.stderr.getvalue()
119
self.assert_(check_expected(result,
120
"yacc_badrule.py:24: Syntax error. Expected ':'\n"
121
"yacc_badrule.py:28: Syntax error in rule 'statement'\n"
122
"yacc_badrule.py:33: Syntax error. Expected ':'\n"
123
"yacc_badrule.py:42: Syntax error. Expected ':'\n"
124
))
125
126
def test_yacc_badtok(self):
127
try:
128
run_import("yacc_badtok")
129
except ply.yacc.YaccError:
130
result = sys.stderr.getvalue()
131
self.assert_(check_expected(result,
132
"tokens must be a list or tuple\n"))
133
134
def test_yacc_dup(self):
135
run_import("yacc_dup")
136
result = sys.stderr.getvalue()
137
self.assert_(check_expected(result,
138
"yacc_dup.py:27: Function p_statement redefined. Previously defined on line 23\n"
139
"Token 'EQUALS' defined, but not used\n"
140
"There is 1 unused token\n"
141
"Generating LALR tables\n"
142
143
))
144
def test_yacc_error1(self):
145
try:
146
run_import("yacc_error1")
147
except ply.yacc.YaccError:
148
result = sys.stderr.getvalue()
149
self.assert_(check_expected(result,
150
"yacc_error1.py:61: p_error() requires 1 argument\n"))
151
152
def test_yacc_error2(self):
153
try:
154
run_import("yacc_error2")
155
except ply.yacc.YaccError:
156
result = sys.stderr.getvalue()
157
self.assert_(check_expected(result,
158
"yacc_error2.py:61: p_error() requires 1 argument\n"))
159
160
def test_yacc_error3(self):
161
try:
162
run_import("yacc_error3")
163
except ply.yacc.YaccError:
164
e = sys.exc_info()[1]
165
result = sys.stderr.getvalue()
166
self.assert_(check_expected(result,
167
"'p_error' defined, but is not a function or method\n"))
168
169
def test_yacc_error4(self):
170
self.assertRaises(ply.yacc.YaccError,run_import,"yacc_error4")
171
result = sys.stderr.getvalue()
172
self.assert_(check_expected(result,
173
"yacc_error4.py:62: Illegal rule name 'error'. Already defined as a token\n"
174
))
175
176
def test_yacc_inf(self):
177
self.assertRaises(ply.yacc.YaccError,run_import,"yacc_inf")
178
result = sys.stderr.getvalue()
179
self.assert_(check_expected(result,
180
"Token 'NUMBER' defined, but not used\n"
181
"There is 1 unused token\n"
182
"Infinite recursion detected for symbol 'statement'\n"
183
"Infinite recursion detected for symbol 'expression'\n"
184
))
185
def test_yacc_literal(self):
186
self.assertRaises(ply.yacc.YaccError,run_import,"yacc_literal")
187
result = sys.stderr.getvalue()
188
self.assert_(check_expected(result,
189
"yacc_literal.py:36: Literal token '**' in rule 'expression' may only be a single character\n"
190
))
191
def test_yacc_misplaced(self):
192
self.assertRaises(ply.yacc.YaccError,run_import,"yacc_misplaced")
193
result = sys.stderr.getvalue()
194
self.assert_(check_expected(result,
195
"yacc_misplaced.py:32: Misplaced '|'\n"
196
))
197
198
def test_yacc_missing1(self):
199
self.assertRaises(ply.yacc.YaccError,run_import,"yacc_missing1")
200
result = sys.stderr.getvalue()
201
self.assert_(check_expected(result,
202
"yacc_missing1.py:24: Symbol 'location' used, but not defined as a token or a rule\n"
203
))
204
205
def test_yacc_nested(self):
206
run_import("yacc_nested")
207
result = sys.stdout.getvalue()
208
self.assert_(check_expected(result,
209
"A\n"
210
"A\n"
211
"A\n",
212
))
213
214
def test_yacc_nodoc(self):
215
run_import("yacc_nodoc")
216
result = sys.stderr.getvalue()
217
self.assert_(check_expected(result,
218
"yacc_nodoc.py:27: No documentation string specified in function 'p_statement_expr' (ignored)\n"
219
"Generating LALR tables\n"
220
))
221
222
def test_yacc_noerror(self):
223
run_import("yacc_noerror")
224
result = sys.stderr.getvalue()
225
self.assert_(check_expected(result,
226
"no p_error() function is defined\n"
227
"Generating LALR tables\n"
228
))
229
230
def test_yacc_nop(self):
231
run_import("yacc_nop")
232
result = sys.stderr.getvalue()
233
self.assert_(check_expected(result,
234
"yacc_nop.py:27: Possible grammar rule 'statement_expr' defined without p_ prefix\n"
235
"Generating LALR tables\n"
236
))
237
238
def test_yacc_notfunc(self):
239
run_import("yacc_notfunc")
240
result = sys.stderr.getvalue()
241
self.assert_(check_expected(result,
242
"'p_statement_assign' not defined as a function\n"
243
"Token 'EQUALS' defined, but not used\n"
244
"There is 1 unused token\n"
245
"Generating LALR tables\n"
246
))
247
def test_yacc_notok(self):
248
try:
249
run_import("yacc_notok")
250
except ply.yacc.YaccError:
251
result = sys.stderr.getvalue()
252
self.assert_(check_expected(result,
253
"No token list is defined\n"))
254
255
def test_yacc_rr(self):
256
run_import("yacc_rr")
257
result = sys.stderr.getvalue()
258
self.assert_(check_expected(result,
259
"Generating LALR tables\n"
260
"1 reduce/reduce conflict\n"
261
"reduce/reduce conflict in state 15 resolved using rule (statement -> NAME EQUALS NUMBER)\n"
262
"rejected rule (expression -> NUMBER) in state 15\n"
263
264
))
265
266
def test_yacc_rr_unused(self):
267
run_import("yacc_rr_unused")
268
result = sys.stderr.getvalue()
269
self.assert_(check_expected(result,
270
"no p_error() function is defined\n"
271
"Generating LALR tables\n"
272
"3 reduce/reduce conflicts\n"
273
"reduce/reduce conflict in state 1 resolved using rule (rule3 -> A)\n"
274
"rejected rule (rule4 -> A) in state 1\n"
275
"reduce/reduce conflict in state 1 resolved using rule (rule3 -> A)\n"
276
"rejected rule (rule5 -> A) in state 1\n"
277
"reduce/reduce conflict in state 1 resolved using rule (rule4 -> A)\n"
278
"rejected rule (rule5 -> A) in state 1\n"
279
"Rule (rule5 -> A) is never reduced\n"
280
))
281
282
def test_yacc_simple(self):
283
run_import("yacc_simple")
284
result = sys.stderr.getvalue()
285
self.assert_(check_expected(result,
286
"Generating LALR tables\n"
287
))
288
def test_yacc_sr(self):
289
run_import("yacc_sr")
290
result = sys.stderr.getvalue()
291
self.assert_(check_expected(result,
292
"Generating LALR tables\n"
293
"20 shift/reduce conflicts\n"
294
))
295
296
def test_yacc_term1(self):
297
self.assertRaises(ply.yacc.YaccError,run_import,"yacc_term1")
298
result = sys.stderr.getvalue()
299
self.assert_(check_expected(result,
300
"yacc_term1.py:24: Illegal rule name 'NUMBER'. Already defined as a token\n"
301
))
302
303
def test_yacc_unused(self):
304
self.assertRaises(ply.yacc.YaccError,run_import,"yacc_unused")
305
result = sys.stderr.getvalue()
306
self.assert_(check_expected(result,
307
"yacc_unused.py:62: Symbol 'COMMA' used, but not defined as a token or a rule\n"
308
"Symbol 'COMMA' is unreachable\n"
309
"Symbol 'exprlist' is unreachable\n"
310
))
311
def test_yacc_unused_rule(self):
312
run_import("yacc_unused_rule")
313
result = sys.stderr.getvalue()
314
self.assert_(check_expected(result,
315
"yacc_unused_rule.py:62: Rule 'integer' defined, but not used\n"
316
"There is 1 unused rule\n"
317
"Symbol 'integer' is unreachable\n"
318
"Generating LALR tables\n"
319
))
320
321
def test_yacc_uprec(self):
322
self.assertRaises(ply.yacc.YaccError,run_import,"yacc_uprec")
323
result = sys.stderr.getvalue()
324
self.assert_(check_expected(result,
325
"yacc_uprec.py:37: Nothing known about the precedence of 'UMINUS'\n"
326
))
327
328
def test_yacc_uprec2(self):
329
self.assertRaises(ply.yacc.YaccError,run_import,"yacc_uprec2")
330
result = sys.stderr.getvalue()
331
self.assert_(check_expected(result,
332
"yacc_uprec2.py:37: Syntax error. Nothing follows %prec\n"
333
))
334
335
def test_yacc_prec1(self):
336
self.assertRaises(ply.yacc.YaccError,run_import,"yacc_prec1")
337
result = sys.stderr.getvalue()
338
self.assert_(check_expected(result,
339
"Precedence rule 'left' defined for unknown symbol '+'\n"
340
"Precedence rule 'left' defined for unknown symbol '*'\n"
341
"Precedence rule 'left' defined for unknown symbol '-'\n"
342
"Precedence rule 'left' defined for unknown symbol '/'\n"
343
))
344
345
346
347
unittest.main()
348
349