# -*- coding: utf-8 -*- ####################################################################### # Name: test_python_parser # Purpose: Test for parser constructed using Python-based grammars. # Author: Igor R. Dejanović <igor DOT dejanovic AT gmail DOT com> # Copyright: (c) 2014 Igor R. Dejanović <igor DOT dejanovic AT gmail DOT com> # License: MIT License ####################################################################### from unittest import TestCase # Grammar from arpeggio import Optional, ZeroOrMore, OneOrMore, EndOfFile, ParserPython, Sequence, NonTerminal from arpeggio import RegExMatch as _ def number(): return _(r'\d*\.\d*|\d+') def factor(): return Optional(["+","-"]), [number, ("(", expression, ")")] def term(): return factor, ZeroOrMore(["*","/"], factor) def expression(): return term, ZeroOrMore(["+", "-"], term) def calc(): return OneOrMore(expression), EndOfFile class TestPythonParser(TestCase): def test_pp_construction(self): ''' Tests parser construction from python internal DSL description. ''' parser = ParserPython(calc) self.assertEqual(parser.parser_model.rule ,'calc') self.assertTrue(isinstance(parser.parser_model, Sequence)) self.assertEqual(parser.parser_model.nodes[0].desc ,'OneOrMore') def test_parse_input(self): parser = ParserPython(calc) input = "4+5*7/3.45*-45*(2.56+32)/-56*(2-1.34)" result = parser.parse(input) self.assertTrue(isinstance(result, NonTerminal)) self.assertEqual(str(result), "4+5*7/3.45*-45*(2.56+32)/-56*(2-1.34)") self.assertEqual(repr(result), "[ [ [ [ number '4' [0] ] ], '+' [1], [ [ number '5' [2] ], '*' [3], [ number '7' [4] ], '/' [5], [ number '3.45' [6] ], '*' [10], [ '-' [11], number '45' [12] ], '*' [14], [ '(' [15], [ [ [ number '2.56' [16] ] ], '+' [20], [ [ number '32' [21] ] ] ], ')' [23] ], '/' [24], [ '-' [25], number '56' [26] ], '*' [28], [ '(' [29], [ [ [ number '2' [30] ] ], '-' [31], [ [ number '1.34' [32] ] ] ], ')' [36] ] ] ], EOF [37] ]") def test_reduce_tree(self): parser = ParserPython(calc, reduce_tree=True) input = "4+5*7/3.45*-45*(2.56+32)/-56*(2-1.34)" result = parser.parse(input) self.assertTrue(isinstance(result, NonTerminal)) self.assertEqual(str(result),"4+5*7/3.45*-45*(2.56+32)/-56*(2-1.34)") self.assertEqual(repr(result), "[ [ number '4' [0], '+' [1], [ number '5' [2], '*' [3], number '7' [4], '/' [5], number '3.45' [6], '*' [10], [ '-' [11], number '45' [12] ], '*' [14], [ '(' [15], [ number '2.56' [16], '+' [20], number '32' [21] ], ')' [23] ], '/' [24], [ '-' [25], number '56' [26] ], '*' [28], [ '(' [29], [ number '2' [30], '-' [31], number '1.34' [32] ], ')' [36] ] ] ], EOF [37] ]")