####################################################################### # Name: calc_peg.py # Purpose: Simple expression evaluator example using PEG language # Author: Igor R. Dejanovic <igor DOT dejanovic AT gmail DOT com> # Copyright: (c) 2009 Igor R. Dejanovic <igor DOT dejanovic AT gmail DOT com> # License: MIT License # # This example is functionally equivalent to calc.py. The difference is that # in this example grammar is specified using PEG language instead of python constructs. # Semantic actions are used to calculate expression during semantic # analysis. # Parser model as well as parse tree exported to dot files should be # the same as parser model and parse tree generated in calc.py example. ####################################################################### from arpeggio import * from arpeggio.peg import ParserPEG from arpeggio.export import PMDOTExport, PTDOTExport import logging # Semantic actions from calc import ToFloat, Factor, Term, Expr, Calc # Grammar is defined using textual specification based on PEG language. calc_grammar = """ number <- r'\d*\.\d*|\d+'; factor <- number / "(" expression ")"; term <- factor (( "*" / "/") factor)*; expression <- ("+" / "-")? term (("+" / "-") term)*; calc <- expression EndOfFile; """ # Rules are mapped to semantic actions sem_actions = { "number" : ToFloat(), "factor" : Factor(), "term" : Term(), "expression" : Expr(), "calc" : Calc() } try: logging.basicConfig(level=logging.DEBUG) # First we will make a parser - an instance of the calc parser model. # Parser model is given in the form of PEG notation therefore we # are using ParserPEG class. Root rule name (parsing expression) is "calc". parser = ParserPEG(calc_grammar, "calc") # Then we export it to a dot file. PMDOTExport().exportFile(parser.parser_model, "calc_peg_parser_model.dot") # An expression we want to evaluate input = "-(4-1)*5+(2+4.67)+5.89/(.2+7)" # Then parse tree is created out of the input expression. parse_tree = parser.parse(input) # We save it to dot file in order to visualise it. PTDOTExport().exportFile(parse_tree, "calc_peg_parse_tree.dot") # getASG will start semantic analysis. # In this case semantic analysis will evaluate expression and # returned value will be evaluated result of the input expression. # Semantic actions are supplied to the getASG function. print "%s = %f" % (input, parser.getASG(sem_actions)) except NoMatch, e: print "Expected %s at position %s." % (e.value, str(e.parser.pos_to_linecol(e.position)))