12632Sstever@eecs.umich.edu# testyacc.py 22632Sstever@eecs.umich.edu 36498Snate@binkert.orgimport unittest 46498Snate@binkert.orgtry: 56498Snate@binkert.org import StringIO 66498Snate@binkert.orgexcept ImportError: 76498Snate@binkert.org import io as StringIO 82632Sstever@eecs.umich.edu 96498Snate@binkert.orgimport sys 106498Snate@binkert.orgimport os 112632Sstever@eecs.umich.edu 126498Snate@binkert.orgsys.path.insert(0,"..") 136498Snate@binkert.orgsys.tracebacklimit = 0 142632Sstever@eecs.umich.edu 156498Snate@binkert.orgimport ply.yacc 162632Sstever@eecs.umich.edu 176498Snate@binkert.orgdef check_expected(result,expected): 186498Snate@binkert.org resultlines = [] 196498Snate@binkert.org for line in result.splitlines(): 206498Snate@binkert.org if line.startswith("WARNING: "): 216498Snate@binkert.org line = line[9:] 226498Snate@binkert.org elif line.startswith("ERROR: "): 236498Snate@binkert.org line = line[7:] 246498Snate@binkert.org resultlines.append(line) 252632Sstever@eecs.umich.edu 266498Snate@binkert.org expectedlines = expected.splitlines() 276498Snate@binkert.org if len(resultlines) != len(expectedlines): 286498Snate@binkert.org return False 296498Snate@binkert.org for rline,eline in zip(resultlines,expectedlines): 306498Snate@binkert.org if not rline.endswith(eline): 316498Snate@binkert.org return False 326498Snate@binkert.org return True 332632Sstever@eecs.umich.edu 346498Snate@binkert.orgdef run_import(module): 356498Snate@binkert.org code = "import "+module 366498Snate@binkert.org exec(code) 376498Snate@binkert.org del sys.modules[module] 386498Snate@binkert.org 396498Snate@binkert.org# Tests related to errors and warnings when building parsers 406498Snate@binkert.orgclass YaccErrorWarningTests(unittest.TestCase): 416498Snate@binkert.org def setUp(self): 426498Snate@binkert.org sys.stderr = StringIO.StringIO() 436498Snate@binkert.org sys.stdout = StringIO.StringIO() 446498Snate@binkert.org try: 456498Snate@binkert.org os.remove("parsetab.py") 466498Snate@binkert.org os.remove("parsetab.pyc") 476498Snate@binkert.org except OSError: 486498Snate@binkert.org pass 496498Snate@binkert.org 506498Snate@binkert.org def tearDown(self): 516498Snate@binkert.org sys.stderr = sys.__stderr__ 526498Snate@binkert.org sys.stdout = sys.__stdout__ 536498Snate@binkert.org def test_yacc_badargs(self): 546498Snate@binkert.org self.assertRaises(ply.yacc.YaccError,run_import,"yacc_badargs") 556498Snate@binkert.org result = sys.stderr.getvalue() 566498Snate@binkert.org self.assert_(check_expected(result, 576498Snate@binkert.org "yacc_badargs.py:23: Rule 'p_statement_assign' has too many arguments\n" 586498Snate@binkert.org "yacc_badargs.py:27: Rule 'p_statement_expr' requires an argument\n" 596498Snate@binkert.org )) 606498Snate@binkert.org def test_yacc_badid(self): 616498Snate@binkert.org self.assertRaises(ply.yacc.YaccError,run_import,"yacc_badid") 626498Snate@binkert.org result = sys.stderr.getvalue() 636498Snate@binkert.org self.assert_(check_expected(result, 646498Snate@binkert.org "yacc_badid.py:32: Illegal name 'bad&rule' in rule 'statement'\n" 656498Snate@binkert.org "yacc_badid.py:36: Illegal rule name 'bad&rule'\n" 666498Snate@binkert.org )) 672632Sstever@eecs.umich.edu 686498Snate@binkert.org def test_yacc_badprec(self): 696498Snate@binkert.org try: 706498Snate@binkert.org run_import("yacc_badprec") 716498Snate@binkert.org except ply.yacc.YaccError: 726498Snate@binkert.org result = sys.stderr.getvalue() 736498Snate@binkert.org self.assert_(check_expected(result, 746498Snate@binkert.org "precedence must be a list or tuple\n" 756498Snate@binkert.org )) 766498Snate@binkert.org def test_yacc_badprec2(self): 776498Snate@binkert.org self.assertRaises(ply.yacc.YaccError,run_import,"yacc_badprec2") 786498Snate@binkert.org result = sys.stderr.getvalue() 796498Snate@binkert.org self.assert_(check_expected(result, 806498Snate@binkert.org "Bad precedence table\n" 816498Snate@binkert.org )) 822632Sstever@eecs.umich.edu 836498Snate@binkert.org def test_yacc_badprec3(self): 846498Snate@binkert.org run_import("yacc_badprec3") 856498Snate@binkert.org result = sys.stderr.getvalue() 866498Snate@binkert.org self.assert_(check_expected(result, 876498Snate@binkert.org "Precedence already specified for terminal 'MINUS'\n" 886498Snate@binkert.org "Generating LALR tables\n" 892632Sstever@eecs.umich.edu 906498Snate@binkert.org )) 916498Snate@binkert.org 926498Snate@binkert.org def test_yacc_badrule(self): 936498Snate@binkert.org self.assertRaises(ply.yacc.YaccError,run_import,"yacc_badrule") 946498Snate@binkert.org result = sys.stderr.getvalue() 956498Snate@binkert.org self.assert_(check_expected(result, 966498Snate@binkert.org "yacc_badrule.py:24: Syntax error. Expected ':'\n" 976498Snate@binkert.org "yacc_badrule.py:28: Syntax error in rule 'statement'\n" 986498Snate@binkert.org "yacc_badrule.py:33: Syntax error. Expected ':'\n" 996498Snate@binkert.org "yacc_badrule.py:42: Syntax error. Expected ':'\n" 1006498Snate@binkert.org )) 1012632Sstever@eecs.umich.edu 1026498Snate@binkert.org def test_yacc_badtok(self): 1036498Snate@binkert.org try: 1046498Snate@binkert.org run_import("yacc_badtok") 1056498Snate@binkert.org except ply.yacc.YaccError: 1066498Snate@binkert.org result = sys.stderr.getvalue() 1076498Snate@binkert.org self.assert_(check_expected(result, 1086498Snate@binkert.org "tokens must be a list or tuple\n")) 1092632Sstever@eecs.umich.edu 1106498Snate@binkert.org def test_yacc_dup(self): 1116498Snate@binkert.org run_import("yacc_dup") 1126498Snate@binkert.org result = sys.stderr.getvalue() 1136498Snate@binkert.org self.assert_(check_expected(result, 1146498Snate@binkert.org "yacc_dup.py:27: Function p_statement redefined. Previously defined on line 23\n" 1156498Snate@binkert.org "Token 'EQUALS' defined, but not used\n" 1166498Snate@binkert.org "There is 1 unused token\n" 1176498Snate@binkert.org "Generating LALR tables\n" 1182632Sstever@eecs.umich.edu 1196498Snate@binkert.org )) 1206498Snate@binkert.org def test_yacc_error1(self): 1216498Snate@binkert.org try: 1226498Snate@binkert.org run_import("yacc_error1") 1236498Snate@binkert.org except ply.yacc.YaccError: 1246498Snate@binkert.org result = sys.stderr.getvalue() 1256498Snate@binkert.org self.assert_(check_expected(result, 1266498Snate@binkert.org "yacc_error1.py:61: p_error() requires 1 argument\n")) 1272632Sstever@eecs.umich.edu 1286498Snate@binkert.org def test_yacc_error2(self): 1296498Snate@binkert.org try: 1306498Snate@binkert.org run_import("yacc_error2") 1316498Snate@binkert.org except ply.yacc.YaccError: 1326498Snate@binkert.org result = sys.stderr.getvalue() 1336498Snate@binkert.org self.assert_(check_expected(result, 1346498Snate@binkert.org "yacc_error2.py:61: p_error() requires 1 argument\n")) 1352632Sstever@eecs.umich.edu 1366498Snate@binkert.org def test_yacc_error3(self): 1376498Snate@binkert.org try: 1386498Snate@binkert.org run_import("yacc_error3") 1396498Snate@binkert.org except ply.yacc.YaccError: 1406498Snate@binkert.org e = sys.exc_info()[1] 1416498Snate@binkert.org result = sys.stderr.getvalue() 1426498Snate@binkert.org self.assert_(check_expected(result, 1436498Snate@binkert.org "'p_error' defined, but is not a function or method\n")) 1446498Snate@binkert.org 1456498Snate@binkert.org def test_yacc_error4(self): 1466498Snate@binkert.org self.assertRaises(ply.yacc.YaccError,run_import,"yacc_error4") 1476498Snate@binkert.org result = sys.stderr.getvalue() 1486498Snate@binkert.org self.assert_(check_expected(result, 1496498Snate@binkert.org "yacc_error4.py:62: Illegal rule name 'error'. Already defined as a token\n" 1506498Snate@binkert.org )) 1516498Snate@binkert.org 1526498Snate@binkert.org def test_yacc_inf(self): 1536498Snate@binkert.org self.assertRaises(ply.yacc.YaccError,run_import,"yacc_inf") 1546498Snate@binkert.org result = sys.stderr.getvalue() 1556498Snate@binkert.org self.assert_(check_expected(result, 1566498Snate@binkert.org "Token 'NUMBER' defined, but not used\n" 1576498Snate@binkert.org "There is 1 unused token\n" 1586498Snate@binkert.org "Infinite recursion detected for symbol 'statement'\n" 1596498Snate@binkert.org "Infinite recursion detected for symbol 'expression'\n" 1606498Snate@binkert.org )) 1616498Snate@binkert.org def test_yacc_literal(self): 1626498Snate@binkert.org self.assertRaises(ply.yacc.YaccError,run_import,"yacc_literal") 1636498Snate@binkert.org result = sys.stderr.getvalue() 1646498Snate@binkert.org self.assert_(check_expected(result, 1656498Snate@binkert.org "yacc_literal.py:36: Literal token '**' in rule 'expression' may only be a single character\n" 1666498Snate@binkert.org )) 1676498Snate@binkert.org def test_yacc_misplaced(self): 1686498Snate@binkert.org self.assertRaises(ply.yacc.YaccError,run_import,"yacc_misplaced") 1696498Snate@binkert.org result = sys.stderr.getvalue() 1706498Snate@binkert.org self.assert_(check_expected(result, 1716498Snate@binkert.org "yacc_misplaced.py:32: Misplaced '|'\n" 1726498Snate@binkert.org )) 1732632Sstever@eecs.umich.edu 1746498Snate@binkert.org def test_yacc_missing1(self): 1756498Snate@binkert.org self.assertRaises(ply.yacc.YaccError,run_import,"yacc_missing1") 1766498Snate@binkert.org result = sys.stderr.getvalue() 1776498Snate@binkert.org self.assert_(check_expected(result, 1786498Snate@binkert.org "yacc_missing1.py:24: Symbol 'location' used, but not defined as a token or a rule\n" 1796498Snate@binkert.org )) 1806498Snate@binkert.org 1816498Snate@binkert.org def test_yacc_nested(self): 1826498Snate@binkert.org run_import("yacc_nested") 1836498Snate@binkert.org result = sys.stdout.getvalue() 1846498Snate@binkert.org self.assert_(check_expected(result, 1856498Snate@binkert.org "A\n" 1866498Snate@binkert.org "A\n" 1876498Snate@binkert.org "A\n", 1886498Snate@binkert.org )) 1896498Snate@binkert.org 1906498Snate@binkert.org def test_yacc_nodoc(self): 1916498Snate@binkert.org run_import("yacc_nodoc") 1926498Snate@binkert.org result = sys.stderr.getvalue() 1936498Snate@binkert.org self.assert_(check_expected(result, 1946498Snate@binkert.org "yacc_nodoc.py:27: No documentation string specified in function 'p_statement_expr' (ignored)\n" 1956498Snate@binkert.org "Generating LALR tables\n" 1966498Snate@binkert.org )) 1976498Snate@binkert.org 1986498Snate@binkert.org def test_yacc_noerror(self): 1996498Snate@binkert.org run_import("yacc_noerror") 2006498Snate@binkert.org result = sys.stderr.getvalue() 2016498Snate@binkert.org self.assert_(check_expected(result, 2026498Snate@binkert.org "no p_error() function is defined\n" 2036498Snate@binkert.org "Generating LALR tables\n" 2046498Snate@binkert.org )) 2056498Snate@binkert.org 2066498Snate@binkert.org def test_yacc_nop(self): 2076498Snate@binkert.org run_import("yacc_nop") 2086498Snate@binkert.org result = sys.stderr.getvalue() 2096498Snate@binkert.org self.assert_(check_expected(result, 2106498Snate@binkert.org "yacc_nop.py:27: Possible grammar rule 'statement_expr' defined without p_ prefix\n" 2116498Snate@binkert.org "Generating LALR tables\n" 2126498Snate@binkert.org )) 2136498Snate@binkert.org 2146498Snate@binkert.org def test_yacc_notfunc(self): 2156498Snate@binkert.org run_import("yacc_notfunc") 2166498Snate@binkert.org result = sys.stderr.getvalue() 2176498Snate@binkert.org self.assert_(check_expected(result, 2186498Snate@binkert.org "'p_statement_assign' not defined as a function\n" 2196498Snate@binkert.org "Token 'EQUALS' defined, but not used\n" 2206498Snate@binkert.org "There is 1 unused token\n" 2216498Snate@binkert.org "Generating LALR tables\n" 2226498Snate@binkert.org )) 2236498Snate@binkert.org def test_yacc_notok(self): 2246498Snate@binkert.org try: 2256498Snate@binkert.org run_import("yacc_notok") 2266498Snate@binkert.org except ply.yacc.YaccError: 2276498Snate@binkert.org result = sys.stderr.getvalue() 2286498Snate@binkert.org self.assert_(check_expected(result, 2296498Snate@binkert.org "No token list is defined\n")) 2306498Snate@binkert.org 2316498Snate@binkert.org def test_yacc_rr(self): 2326498Snate@binkert.org run_import("yacc_rr") 2336498Snate@binkert.org result = sys.stderr.getvalue() 2346498Snate@binkert.org self.assert_(check_expected(result, 2356498Snate@binkert.org "Generating LALR tables\n" 2366498Snate@binkert.org "1 reduce/reduce conflict\n" 2376498Snate@binkert.org "reduce/reduce conflict in state 15 resolved using rule (statement -> NAME EQUALS NUMBER)\n" 2386498Snate@binkert.org "rejected rule (expression -> NUMBER) in state 15\n" 2396498Snate@binkert.org 2406498Snate@binkert.org )) 2416498Snate@binkert.org 2426498Snate@binkert.org def test_yacc_rr_unused(self): 2436498Snate@binkert.org run_import("yacc_rr_unused") 2446498Snate@binkert.org result = sys.stderr.getvalue() 2456498Snate@binkert.org self.assert_(check_expected(result, 2466498Snate@binkert.org "no p_error() function is defined\n" 2476498Snate@binkert.org "Generating LALR tables\n" 2486498Snate@binkert.org "3 reduce/reduce conflicts\n" 2496498Snate@binkert.org "reduce/reduce conflict in state 1 resolved using rule (rule3 -> A)\n" 2506498Snate@binkert.org "rejected rule (rule4 -> A) in state 1\n" 2516498Snate@binkert.org "reduce/reduce conflict in state 1 resolved using rule (rule3 -> A)\n" 2526498Snate@binkert.org "rejected rule (rule5 -> A) in state 1\n" 2536498Snate@binkert.org "reduce/reduce conflict in state 1 resolved using rule (rule4 -> A)\n" 2546498Snate@binkert.org "rejected rule (rule5 -> A) in state 1\n" 2556498Snate@binkert.org "Rule (rule5 -> A) is never reduced\n" 2566498Snate@binkert.org )) 2576498Snate@binkert.org 2586498Snate@binkert.org def test_yacc_simple(self): 2596498Snate@binkert.org run_import("yacc_simple") 2606498Snate@binkert.org result = sys.stderr.getvalue() 2616498Snate@binkert.org self.assert_(check_expected(result, 2626498Snate@binkert.org "Generating LALR tables\n" 2636498Snate@binkert.org )) 2646498Snate@binkert.org def test_yacc_sr(self): 2656498Snate@binkert.org run_import("yacc_sr") 2666498Snate@binkert.org result = sys.stderr.getvalue() 2676498Snate@binkert.org self.assert_(check_expected(result, 2686498Snate@binkert.org "Generating LALR tables\n" 2696498Snate@binkert.org "20 shift/reduce conflicts\n" 2706498Snate@binkert.org )) 2716498Snate@binkert.org 2726498Snate@binkert.org def test_yacc_term1(self): 2736498Snate@binkert.org self.assertRaises(ply.yacc.YaccError,run_import,"yacc_term1") 2746498Snate@binkert.org result = sys.stderr.getvalue() 2756498Snate@binkert.org self.assert_(check_expected(result, 2766498Snate@binkert.org "yacc_term1.py:24: Illegal rule name 'NUMBER'. Already defined as a token\n" 2776498Snate@binkert.org )) 2786498Snate@binkert.org 2796498Snate@binkert.org def test_yacc_unused(self): 2806498Snate@binkert.org self.assertRaises(ply.yacc.YaccError,run_import,"yacc_unused") 2816498Snate@binkert.org result = sys.stderr.getvalue() 2826498Snate@binkert.org self.assert_(check_expected(result, 2836498Snate@binkert.org "yacc_unused.py:62: Symbol 'COMMA' used, but not defined as a token or a rule\n" 2846498Snate@binkert.org "Symbol 'COMMA' is unreachable\n" 2856498Snate@binkert.org "Symbol 'exprlist' is unreachable\n" 2866498Snate@binkert.org )) 2876498Snate@binkert.org def test_yacc_unused_rule(self): 2886498Snate@binkert.org run_import("yacc_unused_rule") 2896498Snate@binkert.org result = sys.stderr.getvalue() 2906498Snate@binkert.org self.assert_(check_expected(result, 2916498Snate@binkert.org "yacc_unused_rule.py:62: Rule 'integer' defined, but not used\n" 2926498Snate@binkert.org "There is 1 unused rule\n" 2936498Snate@binkert.org "Symbol 'integer' is unreachable\n" 2946498Snate@binkert.org "Generating LALR tables\n" 2956498Snate@binkert.org )) 2966498Snate@binkert.org 2976498Snate@binkert.org def test_yacc_uprec(self): 2986498Snate@binkert.org self.assertRaises(ply.yacc.YaccError,run_import,"yacc_uprec") 2996498Snate@binkert.org result = sys.stderr.getvalue() 3006498Snate@binkert.org print repr(result) 3016498Snate@binkert.org self.assert_(check_expected(result, 3026498Snate@binkert.org "yacc_uprec.py:37: Nothing known about the precedence of 'UMINUS'\n" 3036498Snate@binkert.org )) 3046498Snate@binkert.org 3056498Snate@binkert.org def test_yacc_uprec2(self): 3066498Snate@binkert.org self.assertRaises(ply.yacc.YaccError,run_import,"yacc_uprec2") 3076498Snate@binkert.org result = sys.stderr.getvalue() 3086498Snate@binkert.org self.assert_(check_expected(result, 3096498Snate@binkert.org "yacc_uprec2.py:37: Syntax error. Nothing follows %prec\n" 3106498Snate@binkert.org )) 3116498Snate@binkert.org 3126498Snate@binkert.org def test_yacc_prec1(self): 3136498Snate@binkert.org self.assertRaises(ply.yacc.YaccError,run_import,"yacc_prec1") 3146498Snate@binkert.org result = sys.stderr.getvalue() 3156498Snate@binkert.org self.assert_(check_expected(result, 3166498Snate@binkert.org "Precedence rule 'left' defined for unknown symbol '+'\n" 3176498Snate@binkert.org "Precedence rule 'left' defined for unknown symbol '*'\n" 3186498Snate@binkert.org "Precedence rule 'left' defined for unknown symbol '-'\n" 3196498Snate@binkert.org "Precedence rule 'left' defined for unknown symbol '/'\n" 3206498Snate@binkert.org )) 3216498Snate@binkert.org 3226498Snate@binkert.org 3236498Snate@binkert.org 3246498Snate@binkert.orgunittest.main() 325