Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
A
arpeggio-gm
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
backend
arpeggio-gm
Commits
ac2d22b1
Commit
ac2d22b1
authored
Apr 01, 2014
by
Igor Dejanovic
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix #7 Support for Python 3.
Arpeggio now supports both python 2 and 3.
parent
2d654c9a
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
80 additions
and
69 deletions
+80
-69
__init__.py
arpeggio/__init__.py
+20
-18
export.py
arpeggio/export.py
+2
-2
peg.py
arpeggio/peg.py
+11
-9
bibtex.py
examples/bibtex.py
+6
-5
calc.py
examples/calc.py
+18
-18
calc_peg.py
examples/calc_peg.py
+7
-7
robot.py
examples/robot.py
+14
-9
robot_peg.py
examples/robot_peg.py
+2
-1
No files found.
arpeggio/__init__.py
View file @
ac2d22b1
...
...
@@ -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
):
...
...
@@ -507,6 +506,9 @@ 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
...
...
arpeggio/export.py
View file @
ac2d22b1
...
...
@@ -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
()
...
...
arpeggio/peg.py
View file @
ac2d22b1
...
...
@@ -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
)
...
...
@@ -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
=
parse
r
.
parse
(
language_def
)
parser
.
parse
(
language_def
)
return
parser
.
getASG
()
examples/bibtex.py
View file @
ac2d22b1
...
...
@@ -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"
)
examples/calc.py
View file @
ac2d22b1
...
...
@@ -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
()
))
examples/calc_peg.py
View file @
ac2d22b1
...
...
@@ -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
)
))
examples/robot.py
View file @
ac2d22b1
...
...
@@ -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
()
)
examples/robot_peg.py
View file @
ac2d22b1
...
...
@@ -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
)
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment