Commit ff9ad67a authored by Igor Dejanovic's avatar Igor Dejanovic

Semantic actions may now be Python callables.

parent ddfb9d40
...@@ -951,6 +951,9 @@ class Parser(object): ...@@ -951,6 +951,9 @@ class Parser(object):
if node.rule in sem_actions: if node.rule in sem_actions:
sem_action = sem_actions[node.rule] sem_action = sem_actions[node.rule]
if type(sem_action) is types.FunctionType:
retval = sem_action(self, node, children)
else:
retval = sem_action.first_pass(self, node, children) retval = sem_action.first_pass(self, node, children)
if hasattr(sem_action, "second_pass"): if hasattr(sem_action, "second_pass"):
......
...@@ -23,38 +23,30 @@ def calc(): return OneOrMore(expression), EOF ...@@ -23,38 +23,30 @@ def calc(): return OneOrMore(expression), EOF
# Semantic actions # Semantic actions
class ToFloat(SemanticAction): def to_floatSA(parser, node, children):
""" """
Converts node value to float. Converts node value to float.
""" """
def first_pass(self, parser, node, children):
if parser.debug: if parser.debug:
print("Converting {}.".format(node.value)) print("Converting {}.".format(node.value))
return float(node.value) return float(node.value)
def factorSA(parser, node, children):
class Factor(SemanticAction):
""" """
Removes parenthesis if exists and returns what was contained inside. Removes parenthesis if exists and returns what was contained inside.
""" """
def first_pass(self, parser, node, children):
if parser.debug: if parser.debug:
print("Factor {}".format(children)) print("Factor {}".format(children))
if len(children) == 1: if len(children) == 1:
return children[0] return children[0]
sign = -1 if children[0] == '-' else 1 sign = -1 if children[0] == '-' else 1
next_chd = 0 return sign * children[-1]
if children[0] in ['+', '-']:
next_chd = 1
return sign * children[next_chd]
class Term(SemanticAction): def termSA(parser, node, children):
""" """
Divides or multiplies factors. Divides or multiplies factors.
Factor nodes will be already evaluated. Factor nodes will be already evaluated.
""" """
def first_pass(self, parser, node, children):
if parser.debug: if parser.debug:
print("Term {}".format(children)) print("Term {}".format(children))
term = children[0] term = children[0]
...@@ -68,12 +60,11 @@ class Term(SemanticAction): ...@@ -68,12 +60,11 @@ class Term(SemanticAction):
return term return term
class Expr(SemanticAction): def exprSA(parser, node, children):
""" """
Adds or substracts terms. Adds or substracts terms.
Term nodes will be already evaluated. Term nodes will be already evaluated.
""" """
def first_pass(self, parser, node, children):
if parser.debug: if parser.debug:
print("Expression {}".format(children)) print("Expression {}".format(children))
expr = 0 expr = 0
...@@ -95,10 +86,10 @@ class Expr(SemanticAction): ...@@ -95,10 +86,10 @@ class Expr(SemanticAction):
# Connecting rules with semantic actions # Connecting rules with semantic actions
number.sem = ToFloat() number.sem = to_floatSA
factor.sem = Factor() factor.sem = factorSA
term.sem = Term() term.sem = termSA
expression.sem = Expr() expression.sem = exprSA
def main(debug=False): def main(debug=False):
# First we will make a parser - an instance of the calc parser model. # First we will make a parser - an instance of the calc parser model.
......
...@@ -17,7 +17,7 @@ from __future__ import absolute_import ...@@ -17,7 +17,7 @@ from __future__ import absolute_import
from arpeggio.peg import ParserPEG from arpeggio.peg import ParserPEG
# Semantic actions # Semantic actions
from calc import ToFloat, Factor, Term, Expr from calc import to_floatSA, factorSA, termSA, exprSA
# Grammar is defined using textual specification based on PEG language. # Grammar is defined using textual specification based on PEG language.
calc_grammar = """ calc_grammar = """
...@@ -31,10 +31,10 @@ calc_grammar = """ ...@@ -31,10 +31,10 @@ calc_grammar = """
# Rules are mapped to semantic actions # Rules are mapped to semantic actions
sem_actions = { sem_actions = {
"number" : ToFloat(), "number" : to_floatSA,
"factor" : Factor(), "factor" : factorSA,
"term" : Term(), "term" : termSA,
"expression" : Expr(), "expression" : exprSA,
} }
def main(debug=False): def main(debug=False):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment