1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#######################################################################
# 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-2014 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 __future__ import absolute_import
from arpeggio.peg import ParserPEG
from arpeggio.export import PMDOTExporter, PTDOTExporter
# Semantic actions
from calc import ToFloat, Factor, Term, Expr
# 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+ EOF;
"""
# Rules are mapped to semantic actions
sem_actions = {
"number" : ToFloat(),
"factor" : Factor(),
"term" : Term(),
"expression" : Expr(),
}
def main(debug=False):
# 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", debug=debug)
if debug:
# Then we export it to a dot file.
PMDOTExporter().exportFile(parser.parser_model, "calc_peg_parser_model.dot")
# An expression we want to evaluate
input_expr = "-(4-1)*5+(2+4.67)+5.89/(.2+7)"
# Then parse tree is created out of the input_expr expression.
parse_tree = parser.parse(input_expr)
if debug:
# We save it to dot file in order to visualise it.
PTDOTExporter().exportFile(parse_tree, "calc_peg_parse_tree.dot")
result = parser.getASG(sem_actions)
if debug:
# getASG will start semantic analysis.
# In this case semantic analysis will evaluate expression and
# returned value will be evaluated result of the input_expr expression.
# Semantic actions are supplied to the getASG function.
print("{} = {}".format(input_expr, result))
if __name__ == "__main__":
main(debug=True)