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
30b13fc0
Commit
30b13fc0
authored
Jun 11, 2014
by
Igor Dejanovic
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'release/v0.6.x'
parents
d2dfccad
6c12636c
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
84 additions
and
41 deletions
+84
-41
__init__.py
arpeggio/__init__.py
+84
-41
No files found.
arpeggio/__init__.py
View file @
30b13fc0
...
...
@@ -152,38 +152,47 @@ class ParsingExpression(object):
def
_parse_intro
(
self
,
parser
):
if
parser
.
debug
:
print
(
"
Parsing
{}"
.
format
(
self
.
name
))
print
(
"
>> Entering rule
{}"
.
format
(
self
.
name
))
# Skip whitespaces if we are not in the lexical rule
if
not
parser
.
_in_lex_rule
:
parser
.
_skip_ws
()
# Set the begi
ning position in the input stream of
# this parsing expression
self
.
c_pos
=
parser
.
position
# # Set the begin
ning position in the input stream of
#
# this parsing expression
#
self.c_pos = parser.position
def
parse
(
self
,
parser
):
self
.
_parse_intro
(
parser
)
# Current position could change in recursive calls
# so save it.
c_pos
=
self
.
c_pos
c_pos
=
parser
.
position
# Memoization.
# If this position is already parsed by this parser expression use
# the result
if
c_pos
in
self
.
result_cache
:
if
parser
.
debug
:
print
(
"Result for [{}, {}] founded in result_cache."
.
format
(
self
,
self
.
c_pos
))
result
,
new_pos
=
self
.
result_cache
[
c_pos
]
parser
.
position
=
new_pos
if
parser
.
debug
:
print
(
"** Cache hit for [{}, {}] = '{}'"
.
format
(
self
.
name
,
c_pos
,
unicode
(
result
)))
if
parser
.
debug
:
print
(
"<< Leaving rule {}"
.
format
(
self
.
name
))
return
result
# We are descending down
if
parser
.
nm
:
parser
.
nm
.
_up
=
False
result
=
self
.
_parse
(
parser
)
try
:
result
=
self
.
_parse
(
parser
)
except
NoMatch
:
parser
.
position
=
c_pos
# Backtracking
raise
finally
:
if
parser
.
debug
:
print
(
"<< Leaving rule {}"
.
format
(
self
.
name
))
# Create terminal or non-terminal if result is not
# already a Terminal.
...
...
@@ -212,7 +221,7 @@ class ParsingExpression(object):
Used to report most generic language element expected at the
place of the NoMatch exception.
"""
if
self
.
root
and
self
.
c_pos
==
nm
.
position
and
nm
.
_up
:
if
self
.
root
and
parser
.
position
==
nm
.
position
and
nm
.
_up
:
nm
.
rule
=
self
.
rule
...
...
@@ -228,6 +237,7 @@ class Sequence(ParsingExpression):
if
result
:
results
.
append
(
result
)
except
NoMatch
as
m
:
# parser.position = self.c_pos # Backtracking
self
.
_nm_change_rule
(
m
,
parser
)
raise
...
...
@@ -242,12 +252,13 @@ class OrderedChoice(Sequence):
def
_parse
(
self
,
parser
):
result
=
None
match
=
False
c_pos
=
parser
.
position
for
e
in
self
.
nodes
:
try
:
result
=
e
.
parse
(
parser
)
match
=
True
except
NoMatch
as
m
:
parser
.
position
=
self
.
c_pos
# Backtracking
parser
.
position
=
c_pos
# Backtracking
self
.
_nm_change_rule
(
m
,
parser
)
else
:
break
...
...
@@ -271,10 +282,11 @@ class Optional(Repetition):
"""
def
_parse
(
self
,
parser
):
result
=
None
c_pos
=
parser
.
position
try
:
result
=
self
.
nodes
[
0
]
.
parse
(
parser
)
except
NoMatch
:
parser
.
position
=
self
.
c_pos
# Backtracking
parser
.
position
=
c_pos
# Backtracking
return
result
...
...
@@ -288,10 +300,10 @@ class ZeroOrMore(Repetition):
results
=
[]
while
True
:
try
:
self
.
c_pos
=
parser
.
position
c_pos
=
parser
.
position
results
.
append
(
self
.
nodes
[
0
]
.
parse
(
parser
))
except
NoMatch
:
parser
.
position
=
self
.
c_pos
# Backtracking
parser
.
position
=
c_pos
# Backtracking
break
return
results
...
...
@@ -306,11 +318,11 @@ class OneOrMore(Repetition):
first
=
False
while
True
:
try
:
self
.
c_pos
=
parser
.
position
c_pos
=
parser
.
position
results
.
append
(
self
.
nodes
[
0
]
.
parse
(
parser
))
first
=
True
except
NoMatch
:
parser
.
position
=
self
.
c_pos
# Backtracking
parser
.
position
=
c_pos
# Backtracking
if
not
first
:
raise
break
...
...
@@ -325,19 +337,21 @@ class SyntaxPredicate(ParsingExpression):
consume any input.
"""
class
And
(
SyntaxPredicate
):
"""
This predicate will succeed if the specified expression matches current
input.
"""
def
_parse
(
self
,
parser
):
c_pos
=
parser
.
position
for
e
in
self
.
nodes
:
try
:
e
.
parse
(
parser
)
except
NoMatch
:
parser
.
position
=
self
.
c_pos
parser
.
position
=
c_pos
raise
parser
.
position
=
self
.
c_pos
parser
.
position
=
c_pos
class
Not
(
SyntaxPredicate
):
...
...
@@ -346,14 +360,15 @@ class Not(SyntaxPredicate):
current input.
"""
def
_parse
(
self
,
parser
):
c_pos
=
parser
.
position
for
e
in
self
.
nodes
:
try
:
e
.
parse
(
parser
)
except
NoMatch
:
parser
.
position
=
self
.
c_pos
parser
.
position
=
c_pos
return
parser
.
position
=
self
.
c_pos
parser
.
_nm_raise
(
self
.
name
,
self
.
c_pos
,
parser
)
parser
.
position
=
c_pos
parser
.
_nm_raise
(
self
.
name
,
c_pos
,
parser
)
class
Empty
(
SyntaxPredicate
):
...
...
@@ -384,7 +399,7 @@ class Combine(Decorator):
old_in_lex_rule
=
parser
.
_in_lex_rule
parser
.
_in_lex_rule
=
True
self
.
c_pos
=
parser
.
position
c_pos
=
parser
.
position
try
:
for
parser_model_node
in
self
.
nodes
:
results
.
append
(
parser_model_node
.
parse
(
parser
))
...
...
@@ -392,10 +407,10 @@ class Combine(Decorator):
results
=
flatten
(
results
)
# Create terminal from result
return
Terminal
(
self
.
rule
if
self
.
root
else
''
,
self
.
c_pos
,
\
return
Terminal
(
self
.
rule
if
self
.
root
else
''
,
c_pos
,
\
""
.
join
([
str
(
result
)
for
result
in
results
]))
except
NoMatch
:
parser
.
position
=
self
.
c_pos
# Backtracking
parser
.
position
=
c_pos
# Backtracking
raise
finally
:
parser
.
_in_lex_rule
=
old_in_lex_rule
...
...
@@ -413,11 +428,13 @@ class Match(ParsingExpression):
@property
def
name
(
self
):
return
"
%
s(
%
s)"
%
(
self
.
__class__
.
__name__
,
self
.
to_match
)
def
parse
(
self
,
parser
):
self
.
_parse_intro
(
parser
)
if
parser
.
_in_parse_comment
:
return
self
.
_parse
(
parser
)
c_pos
=
parser
.
position
comments
=
[]
try
:
...
...
@@ -436,7 +453,7 @@ class Match(ParsingExpression):
# If comment match successfully try terminal match again
if
comments
:
match
=
self
.
_parse
(
parser
)
match
.
comments
=
NonTerminal
(
'comment'
,
self
.
c_pos
,
match
.
comments
=
NonTerminal
(
'comment'
,
c_pos
,
comments
)
else
:
parser
.
_nm_raise
(
nm
)
...
...
@@ -466,17 +483,19 @@ class RegExMatch(Match):
self
.
regex
=
re
.
compile
(
to_match
)
def
_parse
(
self
,
parser
):
m
=
self
.
regex
.
match
(
parser
.
input
[
parser
.
position
:])
c_pos
=
parser
.
position
m
=
self
.
regex
.
match
(
parser
.
input
[
c_pos
:])
if
m
:
parser
.
position
+=
len
(
m
.
group
())
if
parser
.
debug
:
print
(
"Match {} at {}"
.
format
(
m
.
group
(),
self
.
c_pos
))
return
Terminal
(
self
.
rule
if
self
.
root
else
''
,
self
.
c_pos
,
print
(
"++ Match '
%
s' at
%
d => '
%
s'"
%
(
m
.
group
(),
\
c_pos
,
parser
.
context
(
len
(
m
.
group
()))))
parser
.
position
+=
len
(
m
.
group
())
return
Terminal
(
self
.
rule
if
self
.
root
else
''
,
c_pos
,
m
.
group
())
else
:
if
parser
.
debug
:
print
(
"
NoMatch at {}"
.
format
(
self
.
c_pos
))
parser
.
_nm_raise
(
self
.
name
,
self
.
c_pos
,
parser
)
print
(
"
-- NoMatch at {}"
.
format
(
c_pos
))
parser
.
_nm_raise
(
self
.
name
,
c_pos
,
parser
)
class
StrMatch
(
Match
):
...
...
@@ -491,16 +510,18 @@ class StrMatch(Match):
self
.
to_match
=
to_match
def
_parse
(
self
,
parser
):
if
parser
.
input
[
parser
.
position
:]
.
startswith
(
self
.
to_match
):
parser
.
position
+=
len
(
self
.
to_match
)
c_pos
=
parser
.
position
if
parser
.
input
[
c_pos
:]
.
startswith
(
self
.
to_match
):
if
parser
.
debug
:
print
(
"Match {} at {}"
.
format
(
self
.
to_match
,
self
.
c_pos
))
return
Terminal
(
self
.
rule
if
self
.
root
else
''
,
self
.
c_pos
,
print
(
"++ Match '{}' at {} => '{}'"
.
format
(
self
.
to_match
,
\
c_pos
,
parser
.
context
(
len
(
self
.
to_match
))))
parser
.
position
+=
len
(
self
.
to_match
)
return
Terminal
(
self
.
rule
if
self
.
root
else
''
,
c_pos
,
self
.
to_match
)
else
:
if
parser
.
debug
:
print
(
"
NoMatch at {}"
.
format
(
self
.
c_pos
))
parser
.
_nm_raise
(
self
.
to_match
,
self
.
c_pos
,
parser
)
print
(
"
-- NoMatch at {}"
.
format
(
c_pos
))
parser
.
_nm_raise
(
self
.
to_match
,
c_pos
,
parser
)
def
__str__
(
self
):
return
self
.
to_match
...
...
@@ -537,12 +558,13 @@ class EndOfFile(Match):
return
"EOF"
def
_parse
(
self
,
parser
):
if
len
(
parser
.
input
)
==
parser
.
position
:
return
Terminal
(
'EOF'
,
self
.
c_pos
,
''
)
c_pos
=
parser
.
position
if
len
(
parser
.
input
)
==
c_pos
:
return
Terminal
(
'** EOF'
,
c_pos
,
''
)
else
:
if
parser
.
debug
:
print
(
"EOF not matched."
)
parser
.
_nm_raise
(
self
.
name
,
self
.
c_pos
,
parser
)
print
(
"
!!
EOF not matched."
)
parser
.
_nm_raise
(
self
.
name
,
c_pos
,
parser
)
def
EOF
():
return
EndOfFile
()
...
...
@@ -798,6 +820,27 @@ class Parser(object):
if
self
.
input
[
self
.
line_ends
[
line
-
1
]]
in
'
\n\r
'
:
col
-=
1
return
line
+
1
,
col
+
1
def
context
(
self
,
length
=
None
,
position
=
None
):
"""
Returns current context substring, i.e. the substring around current
position.
Args:
length(int): If given used to mark with asterisk a length chars from
current position.
position(int): The position in the input stream.
"""
if
not
position
:
position
=
self
.
position
if
length
:
return
"{}*{}*{}"
.
format
(
str
(
self
.
input
[
max
(
position
-
10
,
0
):
position
]),
str
(
self
.
input
[
position
:
position
+
length
]),
str
(
self
.
input
[
position
+
length
:
position
+
10
]))
else
:
return
"{}*{}"
.
format
(
str
(
self
.
input
[
max
(
position
-
10
,
0
):
position
]),
str
(
self
.
input
[
position
:
position
+
10
]))
def
_skip_ws
(
self
):
"""
...
...
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