Commit ac2d22b1 authored by Igor Dejanovic's avatar Igor Dejanovic

fix #7 Support for Python 3.

Arpeggio now supports both python 2 and 3.
parent 2d654c9a
......@@ -11,6 +11,7 @@
# notation.
################################################################################
from __future__ import print_function
import re
import bisect
......@@ -150,7 +151,7 @@ class ParsingExpression(object):
def _parse_intro(self, parser):
if parser.debug:
print "Parsing %s" % self.name
print("Parsing {}".format(self.name))
# Skip whitespaces if we are not in the lexical rule
if not parser._in_lex_rule:
......@@ -172,8 +173,7 @@ class ParsingExpression(object):
# the result
if c_pos in self.result_cache:
if parser.debug:
print "Result for [%s, %s] founded in result_cache." % \
(self, self.c_pos)
print("Result for [{}, {}] founded in result_cache.".format(self, self.c_pos))
result, new_pos = self.result_cache[c_pos]
parser.position = new_pos
return result
......@@ -226,7 +226,7 @@ class Sequence(ParsingExpression):
result = e.parse(parser)
if result:
results.append(result)
except NoMatch, m:
except NoMatch as m:
self._nm_change_rule(m, parser)
raise
......@@ -245,7 +245,7 @@ class OrderedChoice(Sequence):
try:
result = e.parse(parser)
match = True
except NoMatch, m:
except NoMatch as m:
parser.position = self.c_pos # Backtracking
self._nm_change_rule(m, parser)
else:
......@@ -273,7 +273,6 @@ class Optional(Repetition):
result = self.nodes[0].parse(parser)
except NoMatch:
parser.position = self.c_pos # Backtracking
pass
return result
......@@ -421,7 +420,7 @@ class Match(ParsingExpression):
comments = []
try:
match = self._parse(parser)
except NoMatch, nm:
except NoMatch as nm:
# If not matched and not in lexical rule try to match comment
#TODO: Comment handling refactoring. Should think of better way to
# handle comments.
......@@ -469,12 +468,12 @@ class RegExMatch(Match):
if m:
parser.position += len(m.group())
if parser.debug:
print "Match %s at %d" % (m.group(), self.c_pos)
print("Match {} at {}".format(m.group(), self.c_pos))
return Terminal(self.rule if self.root else '', self.c_pos,
m.group())
else:
if parser.debug:
print "NoMatch at %d" % self.c_pos
print("NoMatch at {}".format(self.c_pos))
parser._nm_raise(self.name, self.c_pos, parser)
......@@ -493,12 +492,12 @@ class StrMatch(Match):
if parser.input[parser.position:].startswith(self.to_match):
parser.position += len(self.to_match)
if parser.debug:
print "Match %s at %d" % (self.to_match, self.c_pos)
print("Match {} at {}".format(self.to_match, self.c_pos))
return Terminal(self.rule if self.root else '', self.c_pos,
self.to_match)
else:
if parser.debug:
print "NoMatch at %d" % self.c_pos
print("NoMatch at {}".format(self.c_pos))
parser._nm_raise(self.to_match, self.c_pos, parser)
def __str__(self):
......@@ -506,7 +505,10 @@ class StrMatch(Match):
def __eq__(self, other):
return self.to_match == str(other)
def __hash__(self):
return hash(self.to_match)
# HACK: Kwd class is a bit hackish. Need to find a better way to
# introduce different classes of string tokens.
......@@ -537,7 +539,7 @@ class EndOfFile(Match):
return Terminal('EOF', self.c_pos, '')
else:
if parser.debug:
print "EOF not matched."
print("EOF not matched.")
parser._nm_raise(self.name, self.c_pos, parser)
......@@ -759,12 +761,12 @@ class Parser(object):
return retval
if self.debug:
print "ASG: First pass"
print("ASG: First pass")
asg = tree_walk(self.parse_tree)
# Second pass
if self.debug:
print "ASG: Second pass"
print("ASG: Second pass")
for sa_name, asg_node in for_second_pass:
sem_actions[sa_name].second_pass(self, asg_node)
......@@ -872,11 +874,11 @@ class ParserPython(Parser):
if rule in __rule_cache:
c_rule = __rule_cache.get(rule)
if self.debug:
print "Rule %s founded in cache." % rule
print("Rule {} founded in cache.".format(rule))
if isinstance(c_rule, CrossRef):
self.__cross_refs += 1
if self.debug:
print "CrossRef usage: %s" % c_rule.rule_name
print("CrossRef usage: {}".format(c_rule.rule_name))
return c_rule
# Semantic action for the rule
......@@ -893,8 +895,8 @@ class ParserPython(Parser):
# Update cache
__rule_cache[rule] = retval
if self.debug:
print "New rule: %s -> %s" % \
(rule, retval.__class__.__name__)
print("New rule: {} -> {}".format(rule,
retval.__class__.__name__))
elif isinstance(expression, Match):
retval = expression
......
......@@ -7,7 +7,7 @@
# License: MIT License
#######################################################################
import StringIO
import io
from arpeggio import Terminal
......@@ -32,7 +32,7 @@ class Exporter(object):
"""
Export of an obj to a string.
"""
self._outf = StringIO()
self._outf = io.StringIO()
self._export(obj)
return self._outf.getvalue()
......
......@@ -7,6 +7,8 @@
# License: MIT License
#######################################################################
from __future__ import print_function
__all__ = ['ParserPEG']
from arpeggio import *
......@@ -49,7 +51,7 @@ class PEGSemanticAction(SemanticAction):
return
for i,n in enumerate(node.nodes):
if isinstance(n, Terminal):
if parser.peg_rules.has_key(n.value):
if n.value in parser.peg_rules:
node.nodes[i] = parser.peg_rules[n.value]
else:
raise SemanticError("Rule \"%s\" does not exists." % n)
......@@ -80,7 +82,7 @@ class SemSequence(PEGSemanticAction):
if len(children)>1:
return Sequence(nodes=children)
else:
return children[0]
return children[0]
class SemOrderedChoice(PEGSemanticAction):
def first_pass(self, parser, node, children):
......@@ -93,7 +95,7 @@ class SemOrderedChoice(PEGSemanticAction):
class SemPrefix(PEGSemanticAction):
def first_pass(self, parser, node, children):
if parser.debug:
print "Prefix: %s " % str(children)
print("Prefix: {} ".format(str(children)))
if len(children)==2:
if children[0] == NOT():
retval = Not()
......@@ -111,10 +113,10 @@ class SemPrefix(PEGSemanticAction):
class SemSufix(PEGSemanticAction):
def first_pass(self, parser, node, children):
if parser.debug:
print "Sufix : %s" % str(children)
print("Sufix : {}".format(str(children)))
if len(children) == 2:
if parser.debug:
print "Sufix : %s" % str(children[1])
print("Sufix : {}".format(str(children[1])))
if children[1] == STAR():
retval = ZeroOrMore(children[0])
elif children[1] == QUESTION():
......@@ -133,7 +135,7 @@ class SemSufix(PEGSemanticAction):
class SemExpression(PEGSemanticAction):
def first_pass(self, parser, node, children):
if parser.debug:
print "Expression : %s" % str(children)
print("Expression : {}".format(str(children)))
if len(children)==1:
return children[0]
else:
......@@ -142,19 +144,19 @@ class SemExpression(PEGSemanticAction):
class SemIdentifier(SemanticAction):
def first_pass(self, parser, node, children):
if parser.debug:
print "Identifier %s." % node.value
print("Identifier {}.".format(node.value))
return node
class SemRegEx(SemanticAction):
def first_pass(self, parser, node, children):
if parser.debug:
print "RegEx %s." % children[1].value
print("RegEx {}.".format(children[1].value))
return RegExMatch(children[1].value)
class SemLiteral(SemanticAction):
def first_pass(self, parser, node, children):
if parser.debug:
print "Literal: %s" % node.value
print("Literal: {}".format(node.value))
match_str = node.value[1:-1]
match_str = match_str.replace("\\'", "'")
match_str = match_str.replace("\\\\", "\\")
......@@ -198,6 +200,6 @@ class ParserPEG(Parser):
def _from_peg(self, language_def):
parser = ParserPython(grammar, comment)
parser.root_rule_name = self.root_rule_name
parse_tree = parser.parse(language_def)
parser.parse(language_def)
return parser.getASG()
......@@ -8,8 +8,9 @@
#
# This example demonstrates grammar and parser for bibtex files.
#######################################################################
import pprint
from __future__ import print_function
import pprint
import sys
from arpeggio import *
from arpeggio.export import PMDOTExporter, PTDOTExporter
......@@ -44,7 +45,7 @@ class BibFileSem(SemanticAction):
"""
def first_pass(self, parser, node, children):
if parser.debug:
print "Processing Bibfile"
print("Processing Bibfile")
# Return only dict nodes
return [x for x in children if type(x) is dict]
......@@ -57,7 +58,7 @@ class BibEntrySem(SemanticAction):
"""
def first_pass(self, parser, node, children):
if parser.debug:
print " Processing bibentry %s" % children[2]
print(" Processing bibentry %s" % children[2])
bib_entry_map = {
'bibtype': children[0].value,
'bibkey': children[2].value
......@@ -74,7 +75,7 @@ class FieldSem(SemanticAction):
"""
def first_pass(self, parser, node, children):
if parser.debug:
print " Processing field %s" % children[0]
print(" Processing field %s" % children[0])
field = (children[0].value, children[2])
return field
......@@ -136,5 +137,5 @@ if __name__ == "__main__":
pp.pprint(ast)
else:
print "Usage: python bibtex.py file_to_parse"
print("Usage: python bibtex.py file_to_parse")
......@@ -2,7 +2,7 @@
# Name: calc.py
# Purpose: Simple expression evaluator example
# Author: Igor R. Dejanovic <igor DOT dejanovic AT gmail DOT com>
# Copyright: (c) 2009 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 demonstrates grammar definition using python constructs as
......@@ -10,7 +10,7 @@
# notation.
#######################################################################
from arpeggio import *
from arpeggio import Optional, ZeroOrMore, OneOrMore, EndOfFile, SemanticAction, ParserPython
from arpeggio.export import PMDOTExporter, PTDOTExporter
from arpeggio import RegExMatch as _
......@@ -28,7 +28,7 @@ class ToFloat(SemanticAction):
Converts node value to float.
"""
def first_pass(self, parser, node, children):
print "Converting %s." % node.value
print("Converting {}.".format(node.value))
return float(node.value)
class Factor(SemanticAction):
......@@ -36,17 +36,17 @@ class Factor(SemanticAction):
Removes parenthesis if exists and returns what was contained inside.
"""
def first_pass(self, parser, node, children):
print "Factor %s" % children
print("Factor {}".format(children))
if len(children) == 1:
return children[0]
sign = -1 if children[0] == '-' else 1
next = 0
next_chd = 0
if children[0] in ['+', '-']:
next = 1
if children[next] == '(':
return sign * children[next+1]
next_chd = 1
if children[next_chd] == '(':
return sign * children[next_chd+1]
else:
return sign * children[next]
return sign * children[next_chd]
class Term(SemanticAction):
"""
......@@ -54,14 +54,14 @@ class Term(SemanticAction):
Factor nodes will be already evaluated.
"""
def first_pass(self, parser, node, children):
print "Term %s" % children
print("Term {}".format(children))
term = children[0]
for i in range(2, len(children), 2):
if children[i-1]=="*":
term *= children[i]
else:
term /= children[i]
print "Term = %f" % term
print("Term = {}".format(term))
return term
class Expr(SemanticAction):
......@@ -70,7 +70,7 @@ class Expr(SemanticAction):
Term nodes will be already evaluated.
"""
def first_pass(self, parser, node, children):
print "Expression %s" % children
print("Expression {}".format(children))
expr = 0
start = 0
# Check for unary + or - operator
......@@ -83,7 +83,7 @@ class Expr(SemanticAction):
else:
expr += children[i]
print "Expression = %f" % expr
print("Expression = {}".format(expr))
return expr
class Calc(SemanticAction):
......@@ -111,10 +111,10 @@ if __name__ == "__main__":
PMDOTExporter().exportFile(parser.parser_model, "calc_parse_tree_model.dot")
# An expression we want to evaluate
input = "-(4-1)*5+(2+4.67)+5.89/(.2+7)"
input_expr = "-(4-1)*5+(2+4.67)+5.89/(.2+7)"
# We create a parse tree out of textual input
parse_tree = parser.parse(input)
# We create a parse tree out of textual input_expr
parse_tree = parser.parse(input_expr)
# Then we export it to a dot file in order to visualise it.
# This is also optional.
......@@ -122,6 +122,6 @@ if __name__ == "__main__":
# getASG will start semantic analysis.
# In this case semantic analysis will evaluate expression and
# returned value will be the result of the input expression.
print "%s = %f" % (input, parser.getASG())
# returned value will be the result of the input_expr expression.
print("{} = {}".format(input_expr, parser.getASG()))
......@@ -2,7 +2,7 @@
# 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>
# 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
......@@ -12,8 +12,8 @@
# 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 import *
from arpeggio.peg import ParserPEG
from arpeggio.export import PMDOTExporter, PTDOTExporter
......@@ -50,17 +50,17 @@ parser = ParserPEG(calc_grammar, "calc", debug=True)
PMDOTExporter().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)"
input_expr = "-(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)
# Then parse tree is created out of the input_expr expression.
parse_tree = parser.parse(input_expr)
# We save it to dot file in order to visualise it.
PTDOTExporter().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.
# returned value will be evaluated result of the input_expr expression.
# Semantic actions are supplied to the getASG function.
print "%s = %f" % (input, parser.getASG(sem_actions))
print("{} = {}".format(input_expr, parser.getASG(sem_actions)))
......@@ -18,6 +18,7 @@
# right
# end
#######################################################################
from __future__ import print_function
from arpeggio import *
from arpeggio.export import PMDOTExporter, PTDOTExporter
......@@ -34,34 +35,38 @@ def right(): return 'right'
# Semantic actions
class Up(SemanticAction):
def first_pass(self, parser, node, children):
print "Going up"
print("Going up")
return (0, 1)
class Down(SemanticAction):
def first_pass(self, parser, node, children):
print "Going down"
print("Going down")
return (0, -1)
class Left(SemanticAction):
def first_pass(self, parser, node, children):
print "Going left"
print("Going left")
return (-1, 0)
class Right(SemanticAction):
def first_pass(self, parser, node, children):
print "Going right"
print("Going right")
return (1, 0)
class Command(SemanticAction):
def first_pass(self, parser, node, children):
print "Command"
return nodes[0]
print("Command")
return children[0]
class Program(SemanticAction):
def first_pass(self, parser, node, children):
print "Evaluating position"
return reduce(lambda x, y: (x[0]+y[0], x[1]+y[1]), children[1:-2])
print("Evaluating position")
position = [0, 0]
for move in children[1:-2]:
position[0] += move[0]
position[1] += move[1]
return position
# Connecting rules with semantic actions
program.sem = Program()
......@@ -108,5 +113,5 @@ if __name__ == "__main__":
# getASG will start semantic analysis.
# In this case semantic analysis will evaluate expression and
# returned value will be the final position of the robot.
print "position = ", parser.getASG()
print("position = ", parser.getASG())
......@@ -18,6 +18,7 @@
# right
# end
#######################################################################
from __future__ import print_function
from arpeggio import *
from arpeggio.export import PMDOTExporter, PTDOTExporter
......@@ -82,5 +83,5 @@ if __name__ == "__main__":
# getASG will start semantic analysis.
# In this case semantic analysis will evaluate expression and
# returned value will be the final position of the robot.
print "position = ", parser.getASG(sem_actions=semantic_actions)
print("position = ", parser.getASG(sem_actions=semantic_actions))
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