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
3eadb8fa
Commit
3eadb8fa
authored
Oct 12, 2014
by
Igor Dejanovic
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
PEG modules refactored to use visitor pattern in semantic analysis
parent
c38397ff
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
54 additions
and
65 deletions
+54
-65
__init__.py
arpeggio/__init__.py
+1
-0
cleanpeg.py
arpeggio/cleanpeg.py
+7
-6
peg.py
arpeggio/peg.py
+46
-59
No files found.
arpeggio/__init__.py
View file @
3eadb8fa
...
...
@@ -974,6 +974,7 @@ def visit_parse_tree(parse_tree, visitor):
if
visitor
.
debug
:
print
(
"ASG: First pass"
)
# Visit tree.
result
=
parse_tree
.
visit
(
visitor
)
...
...
arpeggio/cleanpeg.py
View file @
3eadb8fa
...
...
@@ -13,7 +13,7 @@ from __future__ import print_function, unicode_literals
from
arpeggio
import
*
from
arpeggio
import
RegExMatch
as
_
from
.peg
import
sem_actions
from
.peg
import
PEGVisitor
from
.peg
import
ParserPEG
as
ParserPEGOrig
__all__
=
[
'ParserPEG'
]
...
...
@@ -49,13 +49,14 @@ def comment(): return _("#.*\n")
class
ParserPEG
(
ParserPEGOrig
):
def
_from_peg
(
self
,
language_def
):
parser
=
ParserPython
(
peggrammar
,
comment
,
reduce_tree
=
False
,
debug
=
self
.
debug
)
parser
.
root_rule_name
=
self
.
root_rule_name
parser
.
parse
(
language_def
)
# Initialise cross-ref counter
parser
.
_crossref_cnt
=
0
parse_tree
=
parser
.
parse
(
language_def
)
return
parser
.
getASG
(
sem_actions
=
sem_actions
)
# return parser.getASG(sem_actions=sem_actions)
return
visit_parse_tree
(
parse_tree
,
PEGVisitor
(
self
.
root_rule_name
,
self
.
ignore_case
,
debug
=
self
.
debug
))
arpeggio/peg.py
View file @
3eadb8fa
...
...
@@ -3,7 +3,7 @@
# Name: peg.py
# Purpose: Implementing 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
#######################################################################
...
...
@@ -49,32 +49,30 @@ def rule_crossref(): return rule_name
def
str_match
():
return
_
(
r'(\'(\\\'|[^\'])*\')|("[^"]*")'
)
def
comment
():
return
"//"
,
_
(
".*
\n
"
)
# ------------------------------------------------------------------
# PEG Semantic Actions
class
SemGrammar
(
SemanticAction
):
def
first_pass
(
self
,
parser
,
node
,
children
):
# Find root rule
for
rule
in
children
:
if
rule
.
rule_name
==
parser
.
root_rule_name
:
self
.
resolved
=
set
()
resolved_rule
=
self
.
_resolve
(
parser
,
rule
)
class
PEGVisitor
(
PTNodeVisitor
):
return
resolved_rule
assert
False
,
"Root rule not found!"
def
__init__
(
self
,
root_rule_name
,
ignore_case
,
*
args
,
**
kwargs
):
super
(
PEGVisitor
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
root_rule_name
=
root_rule_name
self
.
ignore_case
=
ignore_case
# Used for linking phase
self
.
peg_rules
=
{
"EOF"
:
EndOfFile
()
}
def
_resolve
(
self
,
parser
,
node
):
def
visit_peggrammar
(
self
,
node
,
children
):
def
_resolve
(
node
):
def
get_rule_by_name
(
rule_name
):
if
rule_name
in
parser
.
peg_rules
:
return
parser
.
peg_rules
[
rule_name
]
if
rule_name
in
self
.
peg_rules
:
return
self
.
peg_rules
[
rule_name
]
else
:
raise
SemanticError
(
"Rule
\"
{}
\"
does not exists."
.
format
(
rule_name
))
def
resolve_rule_by_name
(
rule_name
):
if
parser
.
debug
:
if
self
.
debug
:
print
(
"Resolving crossref {}"
.
format
(
rule_name
))
resolved_rule
=
get_rule_by_name
(
rule_name
)
while
type
(
resolved_rule
)
is
CrossRef
:
...
...
@@ -85,8 +83,8 @@ class SemGrammar(SemanticAction):
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
:
self
.
peg_rules
[
rule_name
]
=
resolved_rule
if
self
.
debug
:
print
(
"Resolving: cloned to {} = > {}"
.
format
(
resolved_rule
.
rule_name
,
resolved_rule
.
name
))
...
...
@@ -97,17 +95,28 @@ class SemGrammar(SemanticAction):
resolved_rule
=
resolve_rule_by_name
(
node
.
target_rule_name
)
if
resolved_rule
not
in
self
.
resolved
:
self
.
resolved
.
add
(
resolved_rule
)
self
.
_resolve
(
parser
,
resolved_rule
)
_resolve
(
resolved_rule
)
return
resolved_rule
else
:
# Resolve children nodes
for
i
,
n
in
enumerate
(
node
.
nodes
):
node
.
nodes
[
i
]
=
self
.
_resolve
(
parser
,
n
)
node
.
nodes
[
i
]
=
_resolve
(
n
)
self
.
resolved
.
add
(
node
)
return
node
# Find root rule
for
rule
in
children
:
print
(
"RULENODE"
,
rule
.
rule_name
,
self
.
root_rule_name
)
if
rule
.
rule_name
==
self
.
root_rule_name
:
print
(
"ROOT"
,
rule
.
rule_name
)
self
.
resolved
=
set
()
resolved_rule
=
_resolve
(
rule
)
return
resolved_rule
assert
False
,
"Root rule not found!"
def
sem_rule
(
parser
,
node
,
children
):
def
visit_rule
(
self
,
node
,
children
):
rule_name
=
children
[
0
]
if
len
(
children
)
>
2
:
retval
=
Sequence
(
nodes
=
children
[
1
:])
...
...
@@ -117,25 +126,19 @@ def sem_rule(parser, node, children):
retval
.
rule_name
=
rule_name
retval
.
root
=
True
if
not
hasattr
(
parser
,
"peg_rules"
):
parser
.
peg_rules
=
{}
# Used for linking phase
parser
.
peg_rules
[
"EOF"
]
=
EndOfFile
()
# Keep a map of parser rules for cross reference
# resolving.
parser
.
peg_rules
[
rule_name
]
=
retval
self
.
peg_rules
[
rule_name
]
=
retval
return
retval
def
sem_sequence
(
parser
,
node
,
children
):
def
visit_sequence
(
self
,
node
,
children
):
if
len
(
children
)
>
1
:
return
Sequence
(
nodes
=
children
[:])
else
:
# If only one child rule exists reduce.
return
children
[
0
]
def
sem_ordered_choice
(
parser
,
node
,
children
):
def
visit_ordered_choice
(
self
,
node
,
children
):
if
len
(
children
)
>
1
:
retval
=
OrderedChoice
(
nodes
=
children
[:])
else
:
...
...
@@ -143,8 +146,7 @@ def sem_ordered_choice(parser, node, children):
retval
=
children
[
0
]
return
retval
def
sem_prefix
(
parser
,
node
,
children
):
def
visit_prefix
(
self
,
node
,
children
):
if
len
(
children
)
==
2
:
if
children
[
0
]
==
NOT
():
retval
=
Not
()
...
...
@@ -160,8 +162,7 @@ def sem_prefix(parser, node, children):
return
retval
def
sem_sufix
(
parser
,
node
,
children
):
def
visit_sufix
(
self
,
node
,
children
):
if
len
(
children
)
==
2
:
if
children
[
1
]
==
STAR
():
retval
=
ZeroOrMore
(
children
[
0
])
...
...
@@ -178,37 +179,20 @@ def sem_sufix(parser, node, children):
return
retval
def
sem_rule_crossref
(
parser
,
node
,
children
):
def
visit_rule_crossref
(
self
,
node
,
children
):
return
CrossRef
(
node
.
value
)
def
sem_regex
(
parser
,
node
,
children
):
def
visit_regex
(
self
,
node
,
children
):
match
=
RegExMatch
(
children
[
0
],
ignore_case
=
parser
.
ignore_case
)
ignore_case
=
self
.
ignore_case
)
match
.
compile
()
return
match
def
sem_strmatch
(
parser
,
node
,
children
):
def
visit_str_match
(
self
,
node
,
children
):
match_str
=
node
.
value
[
1
:
-
1
]
match_str
=
match_str
.
replace
(
"
\\
'"
,
"'"
)
match_str
=
match_str
.
replace
(
"
\\\\
"
,
"
\\
"
)
return
StrMatch
(
match_str
,
ignore_case
=
parser
.
ignore_case
)
sem_actions
=
{
'peggrammar'
:
SemGrammar
(),
'rule'
:
sem_rule
,
'sequence'
:
sem_sequence
,
'ordered_choice'
:
sem_ordered_choice
,
'prefix'
:
sem_prefix
,
'sufix'
:
sem_sufix
,
'rule_crossref'
:
sem_rule_crossref
,
'regex'
:
sem_regex
,
'str_match'
:
sem_strmatch
,
'expression'
:
SemanticActionSingleChild
(),
}
return
StrMatch
(
match_str
,
ignore_case
=
self
.
ignore_case
)
class
ParserPEG
(
Parser
):
...
...
@@ -240,6 +224,9 @@ class ParserPEG(Parser):
parser
=
ParserPython
(
peggrammar
,
comment
,
reduce_tree
=
False
,
debug
=
self
.
debug
)
parser
.
root_rule_name
=
self
.
root_rule_name
parser
.
parse
(
language_def
)
parse
_tree
=
parse
r
.
parse
(
language_def
)
return
parser
.
getASG
(
sem_actions
=
sem_actions
)
# return parser.getASG(sem_actions=sem_actions)
return
visit_parse_tree
(
parse_tree
,
PEGVisitor
(
self
.
root_rule_name
,
self
.
ignore_case
,
debug
=
self
.
debug
))
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