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
2d460242
Commit
2d460242
authored
Aug 11, 2014
by
Igor Dejanovic
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixing peg language
parent
8609d13a
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
137 additions
and
157 deletions
+137
-157
peg.py
arpeggio/peg.py
+137
-157
No files found.
arpeggio/peg.py
View file @
2d460242
...
@@ -16,6 +16,17 @@ from arpeggio.export import PMDOTExporter, PTDOTExporter
...
@@ -16,6 +16,17 @@ from arpeggio.export import PMDOTExporter, PTDOTExporter
__all__
=
[
'ParserPEG'
]
__all__
=
[
'ParserPEG'
]
# PEG syntax rules
def
peggrammar
():
return
OneOrMore
(
rule
),
EOF
def
rule
():
return
rule_name
,
LEFT_ARROW
,
ordered_choice
,
";"
def
ordered_choice
():
return
sequence
,
ZeroOrMore
(
SLASH
,
sequence
)
def
sequence
():
return
OneOrMore
(
prefix
)
def
prefix
():
return
Optional
([
AND
,
NOT
]),
sufix
def
sufix
():
return
expression
,
Optional
([
QUESTION
,
STAR
,
PLUS
])
def
expression
():
return
[
regex
,
rule_crossref
,
(
OPEN
,
ordered_choice
,
CLOSE
),
str_match
]
# PEG Lexical rules
# PEG Lexical rules
def
LEFT_ARROW
():
return
"<-"
def
LEFT_ARROW
():
return
"<-"
def
SLASH
():
return
"/"
def
SLASH
():
return
"/"
...
@@ -33,38 +44,49 @@ def rule_crossref(): return rule_name
...
@@ -33,38 +44,49 @@ def rule_crossref(): return rule_name
def
str_match
():
return
_
(
r'(\'(\\\'|[^\'])*\')|("[^"]*")'
)
def
str_match
():
return
_
(
r'(\'(\\\'|[^\'])*\')|("[^"]*")'
)
def
comment
():
return
"//"
,
_
(
".*
\n
"
)
def
comment
():
return
"//"
,
_
(
".*
\n
"
)
# PEG syntax rules
def
peggrammar
():
return
OneOrMore
(
rule
),
EOF
def
rule
():
return
rule_name
,
LEFT_ARROW
,
ordered_choice
,
";"
def
ordered_choice
():
return
sequence
,
ZeroOrMore
(
SLASH
,
sequence
)
def
sequence
():
return
OneOrMore
(
prefix
)
def
prefix
():
return
Optional
([
AND
,
NOT
]),
sufix
def
sufix
():
return
expression
,
Optional
([
QUESTION
,
STAR
,
PLUS
])
def
expression
():
return
[
regex
,
rule_crossref
,
(
OPEN
,
ordered_choice
,
CLOSE
),
str_match
]
# ------------------------------------------------------------------
# ------------------------------------------------------------------
# PEG Semantic Actions
# PEG Semantic Actions
class
PEGSemanticAction
(
SemanticAction
):
class
SemGrammar
(
SemanticAction
):
def
_resolve
(
self
,
parser
,
rule_name
):
def
first_pass
(
self
,
parser
,
node
,
children
):
return
parser
.
peg_rules
[
parser
.
root_rule_name
]
if
rule_name
in
parser
.
peg_rules
:
def
_resolve
(
self
,
parser
,
node
):
resolved_rule
=
parser
.
peg_rules
[
rule_name
]
if
type
(
resolved_rule
)
is
CrossRef
:
resolved_rule
=
self
.
_resolve
(
parser
,
resolved_rule
.
rule_name
)
if
parser
.
debug
:
def
get_rule_by_name
(
rule_name
):
print
(
"Resolving: CrossRef {} => {}"
.
format
(
rule_name
,
if
rule_name
in
parser
.
peg_rules
:
resolved_rule
.
name
))
return
parser
.
peg_rules
[
rule_name
]
else
:
raise
SemanticError
(
"Rule
\"
{}
\"
does not exists."
.
format
(
n
.
rule_name
))
for
i
,
n
in
enumerate
(
node
.
nodes
):
if
isinstance
(
n
,
CrossRef
):
rule_name
=
n
.
rule_name
if
parser
.
debug
:
print
(
"Resolving crossref {}"
.
format
(
rule_name
))
resolved_rule
=
get_rule_by_name
(
rule_name
)
while
type
(
resolved_rule
)
is
CrossRef
:
target_rule
=
resolved_rule
.
rule_name
resolved_rule
=
get_rule_by_name
(
target_rule
)
# If resolved rule hasn't got the same name it
# should be cloned and preserved in the peg_rules cache
if
resolved_rule
.
rule_name
!=
rule_name
:
resolved_rule
=
copy
.
copy
(
resolved_rule
)
resolved_rule
.
rule_name
=
rule_name
parser
.
peg_rules
[
rule_name
]
=
resolved_rule
if
parser
.
debug
:
print
(
"Resolving: cloned to {} = > {}"
\
.
format
(
resolved_rule
.
rule_name
,
resolved_rule
.
name
))
node
.
nodes
[
i
]
=
resolved_rule
else
:
resolved_rule
=
n
return
resolved_rule
if
not
resolved_rule
in
self
.
resolved
:
else
:
self
.
resolved
.
add
(
resolved_rule
)
raise
SemanticError
(
"Rule
\"
{}
\"
does not exists."
self
.
_resolve
(
parser
,
resolved_rule
)
.
format
(
rule_name
))
def
second_pass
(
self
,
parser
,
node
):
def
second_pass
(
self
,
parser
,
node
):
'''
'''
...
@@ -73,148 +95,106 @@ class PEGSemanticAction(SemanticAction):
...
@@ -73,148 +95,106 @@ class PEGSemanticAction(SemanticAction):
if
parser
.
debug
:
if
parser
.
debug
:
print
(
"Second pass:"
,
type
(
node
),
str
(
node
))
print
(
"Second pass:"
,
type
(
node
),
str
(
node
))
if
isinstance
(
node
,
ParsingExpression
):
self
.
resolved
=
set
()
self
.
_resolve
(
parser
,
node
)
for
i
,
n
in
enumerate
(
node
.
nodes
):
return
node
if
isinstance
(
n
,
CrossRef
):
peggrammar
.
sem
=
SemGrammar
()
resolved_rule
=
self
.
_resolve
(
parser
,
n
.
rule_name
)
# If resolved rule hasn't got the same name it
# should be cloned and preserved in the peg_rules cache
if
resolved_rule
.
rule_name
!=
n
.
rule_name
:
resolved_rule
=
copy
.
copy
(
resolved_rule
)
resolved_rule
.
rule_name
=
n
.
rule_name
parser
.
peg_rules
[
resolved_rule
.
rule_name
]
=
resolved_rule
if
parser
.
debug
:
print
(
"Resolving: cloned to {} = > {}"
\
.
format
(
resolved_rule
.
rule_name
,
resolved_rule
.
name
))
node
.
nodes
[
i
]
=
resolved_rule
return
node
elif
not
isinstance
(
node
,
CrossRef
):
raise
SemanticError
(
"Invalid type '{}'({}) after first pass."
.
format
(
type
(
node
),
str
(
node
)))
class
SemGrammar
(
SemanticAction
):
def
first_pass
(
self
,
parser
,
node
,
children
):
return
parser
.
peg_rules
[
parser
.
root_rule_name
]
def
sem_rule
(
parser
,
node
,
children
):
rule_name
=
children
[
0
]
if
len
(
children
)
>
2
:
retval
=
Sequence
(
nodes
=
children
[
1
:])
else
:
retval
=
children
[
1
]
class
SemRule
(
PEGSemanticAction
):
# CrossRef already has rule_name set
def
first_pass
(
self
,
parser
,
node
,
children
):
# that attrib is a target rule name
rule_name
=
children
[
0
]
if
type
(
retval
)
is
not
CrossRef
:
if
len
(
children
)
>
2
:
retval
=
Sequence
(
nodes
=
children
[
1
:])
else
:
retval
=
children
[
1
]
retval
.
rule_name
=
rule_name
retval
.
rule_name
=
rule_name
retval
.
root
=
True
retval
.
root
=
True
if
not
hasattr
(
parser
,
"peg_rules"
):
if
not
hasattr
(
parser
,
"peg_rules"
):
parser
.
peg_rules
=
{}
# Used for linking phase
parser
.
peg_rules
=
{}
# Used for linking phase
parser
.
peg_rules
[
"EOF"
]
=
EndOfFile
()
parser
.
peg_rules
[
"EOF"
]
=
EndOfFile
()
# Keep a map of parser rules for cross reference
# Keep a map of parser rules for cross reference
# resolving.
# resolving.
parser
.
peg_rules
[
rule_name
]
=
retval
parser
.
peg_rules
[
rule_name
]
=
retval
return
retval
return
retval
rule
.
sem
=
sem_rule
class
SemSequence
(
PEGSemanticAction
):
def
sem_sequence
(
parser
,
node
,
children
):
def
first_pass
(
self
,
parser
,
node
,
children
):
if
len
(
children
)
>
1
:
if
len
(
children
)
>
1
:
return
Sequence
(
nodes
=
children
[:])
return
Sequence
(
nodes
=
children
[:])
else
:
# If only one child rule exists reduce.
return
children
[
0
]
sequence
.
sem
=
sem_sequence
def
sem_ordered_choice
(
parser
,
node
,
children
):
if
len
(
children
)
>
1
:
retval
=
OrderedChoice
(
nodes
=
children
[:])
else
:
# If only one child rule exists reduce.
retval
=
children
[
0
]
return
retval
ordered_choice
.
sem
=
sem_ordered_choice
def
sem_prefix
(
parser
,
node
,
children
):
if
len
(
children
)
==
2
:
if
children
[
0
]
==
NOT
():
retval
=
Not
()
else
:
else
:
# If only one child rule exists reduce.
retval
=
And
()
return
children
[
0
]
if
type
(
children
[
1
])
is
list
:
retval
.
nodes
=
children
[
1
]
class
SemOrderedChoice
(
PEGSemanticAction
):
def
first_pass
(
self
,
parser
,
node
,
children
):
if
len
(
children
)
>
1
:
retval
=
OrderedChoice
(
nodes
=
children
[:])
else
:
else
:
# If only one child rule exists reduce.
retval
.
nodes
=
[
children
[
1
]]
retval
=
children
[
0
]
else
:
return
retval
# If there is no optional prefix reduce.
retval
=
children
[
0
]
class
SemPrefix
(
PEGSemanticAction
):
return
retval
def
first_pass
(
self
,
parser
,
node
,
children
):
prefix
.
sem
=
sem_prefix
if
len
(
children
)
==
2
:
if
children
[
0
]
==
NOT
():
def
sem_sufix
(
parser
,
node
,
children
):
retval
=
Not
()
if
len
(
children
)
==
2
:
else
:
if
children
[
1
]
==
STAR
():
retval
=
And
()
retval
=
ZeroOrMore
(
children
[
0
])
if
type
(
children
[
1
])
is
list
:
elif
children
[
1
]
==
QUESTION
():
retval
.
nodes
=
children
[
1
]
retval
=
Optional
(
children
[
0
])
else
:
retval
.
nodes
=
[
children
[
1
]]
else
:
else
:
# If there is no optional prefix reduce.
retval
=
OneOrMore
(
children
[
0
])
retval
=
children
[
0
]
if
type
(
children
[
0
])
is
list
:
retval
.
nodes
=
children
[
0
]
return
retval
class
SemSufix
(
PEGSemanticAction
):
def
first_pass
(
self
,
parser
,
node
,
children
):
if
len
(
children
)
==
2
:
if
children
[
1
]
==
STAR
():
retval
=
ZeroOrMore
(
children
[
0
])
elif
children
[
1
]
==
QUESTION
():
retval
=
Optional
(
children
[
0
])
else
:
retval
=
OneOrMore
(
children
[
0
])
if
type
(
children
[
0
])
is
list
:
retval
.
nodes
=
children
[
0
]
else
:
retval
.
nodes
=
[
children
[
0
]]
else
:
else
:
retval
=
children
[
0
]
retval
.
nodes
=
[
children
[
0
]]
else
:
return
retval
retval
=
children
[
0
]
return
retval
class
SemExpression
(
PEGSemanticAction
):
sufix
.
sem
=
sem_sufix
def
first_pass
(
self
,
parser
,
node
,
children
):
return
children
[
0
]
def
sem_rule_crossref
(
parser
,
node
,
children
):
return
CrossRef
(
node
.
value
)
rule_crossref
.
sem
=
sem_rule_crossref
class
SemRuleCrossRef
(
SemanticAction
):
def
first_pass
(
self
,
parser
,
node
,
children
):
def
sem_regex
(
parser
,
node
,
children
):
return
CrossRef
(
node
.
value
)
match
=
RegExMatch
(
children
[
0
],
ignore_case
=
parser
.
ignore_case
)
match
.
compile
()
class
SemRegEx
(
SemanticAction
):
return
match
def
first_pass
(
self
,
parser
,
node
,
children
):
regex
.
sem
=
sem_regex
match
=
RegExMatch
(
children
[
0
],
ignore_case
=
parser
.
ignore_case
)
def
sem_strmatch
(
parser
,
node
,
children
):
match
.
compile
()
match_str
=
node
.
value
[
1
:
-
1
]
return
match
match_str
=
match_str
.
replace
(
"
\\
'"
,
"'"
)
match_str
=
match_str
.
replace
(
"
\\\\
"
,
"
\\
"
)
class
SemStrMatch
(
SemanticAction
):
return
StrMatch
(
match_str
,
ignore_case
=
parser
.
ignore_case
)
def
first_pass
(
self
,
parser
,
node
,
children
):
str_match
.
sem
=
sem_strmatch
match_str
=
node
.
value
[
1
:
-
1
]
match_str
=
match_str
.
replace
(
"
\\
'"
,
"'"
)
expression
.
sem
=
SemanticActionSingleChild
()
match_str
=
match_str
.
replace
(
"
\\\\
"
,
"
\\
"
)
return
StrMatch
(
match_str
,
ignore_case
=
parser
.
ignore_case
)
peggrammar
.
sem
=
SemGrammar
()
rule
.
sem
=
SemRule
()
ordered_choice
.
sem
=
SemOrderedChoice
()
sequence
.
sem
=
SemSequence
()
prefix
.
sem
=
SemPrefix
()
sufix
.
sem
=
SemSufix
()
expression
.
sem
=
SemExpression
()
rule_crossref
.
sem
=
SemRuleCrossRef
()
regex
.
sem
=
SemRegEx
()
str_match
.
sem
=
SemStrMatch
()
class
ParserPEG
(
Parser
):
class
ParserPEG
(
Parser
):
...
...
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