Mercurial > lcfOS
view python/testpyy.py @ 185:51a6440d6398
Fixed LR(1) parser
author | Windel Bouwman |
---|---|
date | Fri, 24 May 2013 20:45:03 +0200 |
parents | fe2b72381a83 |
children | 6b2bec5653f1 |
line wrap: on
line source
import unittest, pprint from pyyacc import Grammar, Item, EOF class testLR(unittest.TestCase): def setUp(self): pass def testSimpleGrammar(self): # 1. define a simple grammar: g = Grammar(['EOF', 'identifier', '(', ')', '+', '*']) g.add_production('input', ['expression']) g.add_production('expression', ['term']) g.add_production('expression', ['expression', '+', 'term']) g.add_production('term', ['factor']) g.add_production('term', ['term', '*', 'factor']) g.add_production('factor', ['(', 'expression', ')']) g.add_production('factor', ['identifier']) g.start_symbol = 'input' # 2. define input: tokens = ['identifier', '+', 'identifier', '+', 'identifier', 'EOF'] # 3. build parser: p = g.genParser() # 4. feed input: p.parse(tokens) class testExpressionGrammar(unittest.TestCase): def setUp(self): g = Grammar(['EOF', 'identifier', '(', ')', '+', '*', 'num']) g.add_production('input', ['expression']) g.add_production('expression', ['term']) g.add_production('expression', ['expression', '+', 'term']) g.add_production('term', ['factor']) g.add_production('term', ['term', '*', 'factor']) g.add_production('factor', ['(', 'expression', ')']) g.add_production('factor', ['identifier']) g.add_production('factor', ['num']) g.start_symbol = 'input' self.g = g def testFirstSimpleGrammar(self): # 1. define a simple grammar: first = self.g.calcFirstSets() self.assertEqual(first['input'], {'identifier', '(', 'num'}) self.assertEqual(first['term'], {'identifier', '(', 'num'}) def testCanonical(self): s0 = self.g.initialItemSet() s, gt = self.g.genCanonicalSet(s0) # Must result in 12 sets: self.assertEqual(len(s), 24) class testPG(unittest.TestCase): """ Tests several parts of the parser generator """ def setUp(self): g = Grammar(['(', ')']) g.add_production('goal', ['list']) g.add_production('list', ['list', 'pair']) g.add_production('list', ['pair']) g.add_production('pair', ['(', 'pair', ')']) g.add_production('pair', ['(', ')']) g.start_symbol = 'goal' self.g = g def testFirstSet(self): for a in ['(', ')', EOF, 'EPS']: self.assertEqual(self.g.first[a], {a}) for nt in ['list', 'pair', 'goal']: self.assertEqual(self.g.first[nt], {'('}) def testInitItemSet(self): p0, p1, p2, p3, p4 = self.g.productions s0 = self.g.initialItemSet() self.assertEqual(len(s0), 9) # 9 with the goal rule included! self.assertIn(Item(p0, 0, EOF), s0) self.assertIn(Item(p1, 0, EOF), s0) self.assertIn(Item(p1, 0, '('), s0) self.assertIn(Item(p2, 0, EOF), s0) self.assertIn(Item(p2, 0, '('), s0) self.assertIn(Item(p3, 0, EOF), s0) self.assertIn(Item(p3, 0, '('), s0) self.assertIn(Item(p4, 0, EOF), s0) self.assertIn(Item(p4, 0, '('), s0) def testCanonical(self): s0 = self.g.initialItemSet() s, gt = self.g.genCanonicalSet(s0) # Must result in 12 sets: self.assertEqual(len(s), 12) def testClosure(self): p0, p1, p2, p3, p4 = self.g.productions s0 = set() s0.add(Item(p0, 0, EOF)) self.assertEqual(len(s0), 1) # 1 rule self.assertIn(Item(p0, 0, EOF), s0) # Invoke closure on set: s0 = self.g.closure(s0) self.assertIn(Item(p0, 0, EOF), s0) self.assertIn(Item(p1, 0, EOF), s0) self.assertIn(Item(p1, 0, '('), s0) self.assertIn(Item(p2, 0, EOF), s0) self.assertIn(Item(p2, 0, '('), s0) self.assertIn(Item(p3, 0, EOF), s0) self.assertIn(Item(p3, 0, '('), s0) self.assertIn(Item(p4, 0, EOF), s0) self.assertIn(Item(p4, 0, '('), s0) def testParser(self): tokens = ['(', '(', ')', ')', '(', ')', EOF] # 3. build parser: p = self.g.genParser() self.assertEqual(len(p.goto_table), 5) self.assertEqual(len(p.action_table), 19) # 4. feed input: p.parse(tokens) if __name__ == '__main__': unittest.main()