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
2
Merge Requests
2
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
郭家华
arpeggio-gm
Commits
c2bb10f5
Commit
c2bb10f5
authored
Feb 04, 2014
by
Igor Dejanovic
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixing docstrings and comments.
parent
20ad7f7a
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
197 additions
and
158 deletions
+197
-158
__init__.py
arpeggio/__init__.py
+131
-114
export.py
arpeggio/export.py
+39
-29
bibtex.py
examples/bibtex.py
+13
-5
calc.py
examples/calc.py
+10
-6
calc_peg.py
examples/calc_peg.py
+1
-1
json.py
examples/json.py
+1
-1
simple.py
examples/simple.py
+2
-2
No files found.
arpeggio/__init__.py
View file @
c2bb10f5
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
#######################################################################
#######################################################################
#########
# Name: arpeggio.py
# Name: arpeggio.py
# Purpose: PEG parser interpreter
# Purpose: PEG parser interpreter
# Author: Igor R. Dejanović <igor DOT dejanovic AT gmail DOT com>
# Author: Igor R. Dejanović <igor DOT dejanovic AT gmail DOT com>
# Copyright: (c) 2009 Igor R. Dejanović <igor DOT dejanovic AT gmail DOT com>
# Copyright: (c) 2009 Igor R. Dejanović <igor DOT dejanovic AT gmail DOT com>
# License: MIT License
# License: MIT License
#
#
# This is implementation of packrat parser interpreter based on PEG grammars.
# This is an implementation of packrat parser interpreter based on PEG grammars.
# Parsers are defined using python language construction or PEG language.
# Grammars are defined using Python language constructs or the PEG textual
#######################################################################
# notation.
################################################################################
import
re
import
re
import
bisect
import
bisect
...
@@ -17,7 +18,9 @@ DEFAULT_WS = '\t\n\r '
...
@@ -17,7 +18,9 @@ DEFAULT_WS = '\t\n\r '
class
ArpeggioError
(
Exception
):
class
ArpeggioError
(
Exception
):
'''Base class for arpeggio errors.'''
"""
Base class for arpeggio errors.
"""
def
__init__
(
self
,
message
):
def
__init__
(
self
,
message
):
self
.
message
=
message
self
.
message
=
message
...
@@ -26,24 +29,29 @@ class ArpeggioError(Exception):
...
@@ -26,24 +29,29 @@ class ArpeggioError(Exception):
class
GrammarError
(
ArpeggioError
):
class
GrammarError
(
ArpeggioError
):
'''
"""
Error raised during parser building phase used to indicate error in the
Error raised during parser building phase used to indicate error in the
grammar definition.
grammar definition.
'''
"""
class
SemanticError
(
ArpeggioError
):
class
SemanticError
(
ArpeggioError
):
'''
"""
Error raised during the phase of semantic analysis used to indicate
Error raised during the phase of semantic analysis used to indicate
semantic error.
semantic error.
'''
"""
class
NoMatch
(
Exception
):
class
NoMatch
(
Exception
):
'''
"""
Exception raised by the Match classes during parsing to indicate that the
Exception raised by the Match classes during parsing to indicate that the
match is not successful.
match is not successful.
'''
Args:
value (str): A value
position (int):
parser (Parser): An instance of parser
"""
def
__init__
(
self
,
value
,
position
,
parser
):
def
__init__
(
self
,
value
,
position
,
parser
):
self
.
value
=
value
self
.
value
=
value
...
@@ -77,20 +85,18 @@ def flatten(_iterable):
...
@@ -77,20 +85,18 @@ def flatten(_iterable):
class
ParsingExpression
(
object
):
class
ParsingExpression
(
object
):
"""
"""
Represents node of the Parser Model.
Represents
the
node of the Parser Model.
Root parser expression node will create non-terminal parser tree node while
Root parser expression node will create non-terminal parser tree node while
non-root node will create list of terminals and non-terminals.
non-root node will create list of terminals and non-terminals.
Attributes:
rule (str): The name of the parser rule if this is the root rule.
root (bool): Does this parser expression represents the
root of the parser rule? The root parser rule will create
non-terminal node of the parse tree during parsing.
nodes (list of ParsingExpression): A list of child parser expressions.
"""
"""
def
__init__
(
self
,
rule
=
None
,
root
=
False
,
nodes
=
None
):
def
__init__
(
self
,
rule
=
None
,
root
=
False
,
nodes
=
None
):
'''
@param rule - the name of the parser rule if this is the root of the
parser rule.
@param root - Does this parser expression represents the
root of the parser rule?
The root parser rule will create non-terminal node of
the parse tree during parsing.
@param nodes - list of child parser expression nodes.
'''
# Memoization. Every node cache the parsing results for the given input
# Memoization. Every node cache the parsing results for the given input
# positions.
# positions.
self
.
result_cache
=
{}
# position -> parse tree
self
.
result_cache
=
{}
# position -> parse tree
...
@@ -119,12 +125,12 @@ class ParsingExpression(object):
...
@@ -119,12 +125,12 @@ class ParsingExpression(object):
return
id
(
self
)
return
id
(
self
)
def
clear_cache
(
self
,
processed
=
None
):
def
clear_cache
(
self
,
processed
=
None
):
'''
"""
Clears memoization cache. Should be called on input change.
Clears memoization cache. Should be called on input change.
Args:
Args:
processed (set): Set of processed nodes to prevent infinite loops.
processed (set): Set of processed nodes to prevent infinite loops.
'''
"""
self
.
result_cache
=
{}
self
.
result_cache
=
{}
if
not
processed
:
if
not
processed
:
...
@@ -182,26 +188,26 @@ class ParsingExpression(object):
...
@@ -182,26 +188,26 @@ class ParsingExpression(object):
#TODO: _nm_change_rule should be called from every parser expression parse
#TODO: _nm_change_rule should be called from every parser expression parse
# method that can potentialy be the root parser rule.
# method that can potentialy be the root parser rule.
def
_nm_change_rule
(
self
,
nm
,
parser
):
def
_nm_change_rule
(
self
,
nm
,
parser
):
'''
"""
Change rule for the given NoMatch object to a more generic if
Change rule for the given NoMatch object to a more generic if
we did not consume any input and we are moving up the parser model
we did not consume any input and we are moving up the parser model
tree. Used to report most generic language element expected at the
tree. Used to report most generic language element expected at the
place of the NoMatch exception.
place of the NoMatch exception.
'''
"""
if
self
.
root
and
self
.
c_pos
==
nm
.
position
and
nm
.
_up
:
if
self
.
root
and
self
.
c_pos
==
nm
.
position
and
nm
.
_up
:
nm
.
value
=
self
.
rule
nm
.
value
=
self
.
rule
class
Sequence
(
ParsingExpression
):
class
Sequence
(
ParsingExpression
):
'''
"""
Will match sequence of parser expressions in exact order they are defined.
Will match sequence of parser expressions in exact order they are defined.
'''
def
__init__
(
self
,
elements
=
None
,
rule
=
None
,
root
=
False
,
nodes
=
None
):
Attributes:
'''
elements (list): A list used as a staging structure for python based
@param elements - list used as a staging structure for python based
grammar definition. Used in _from_python for building nodes list of
grammar definition. Used in _from_python for building nodes list of
child parser expressions.
child parser expressions.
'''
"""
def
__init__
(
self
,
elements
=
None
,
rule
=
None
,
root
=
False
,
nodes
=
None
):
super
(
Sequence
,
self
)
.
__init__
(
rule
,
root
,
nodes
)
super
(
Sequence
,
self
)
.
__init__
(
rule
,
root
,
nodes
)
self
.
elements
=
elements
self
.
elements
=
elements
...
@@ -220,10 +226,10 @@ class Sequence(ParsingExpression):
...
@@ -220,10 +226,10 @@ class Sequence(ParsingExpression):
class
OrderedChoice
(
Sequence
):
class
OrderedChoice
(
Sequence
):
'''
"""
Will match one of the parser expressions specified. Parser will try to
Will match one of the parser expressions specified. Parser will try to
match expressions in the order they are defined.
match expressions in the order they are defined.
'''
"""
def
_parse
(
self
,
parser
):
def
_parse
(
self
,
parser
):
result
=
None
result
=
None
match
=
False
match
=
False
...
@@ -245,9 +251,9 @@ class OrderedChoice(Sequence):
...
@@ -245,9 +251,9 @@ class OrderedChoice(Sequence):
class
Repetition
(
ParsingExpression
):
class
Repetition
(
ParsingExpression
):
'''
"""
Base class for all repetition-like parser expressions (?,*,+)
Base class for all repetition-like parser expressions (?,*,+)
'''
"""
def
__init__
(
self
,
*
elements
,
**
kwargs
):
def
__init__
(
self
,
*
elements
,
**
kwargs
):
super
(
Repetition
,
self
)
.
__init__
(
None
)
super
(
Repetition
,
self
)
.
__init__
(
None
)
if
len
(
elements
)
==
1
:
if
len
(
elements
)
==
1
:
...
@@ -261,10 +267,10 @@ class Repetition(ParsingExpression):
...
@@ -261,10 +267,10 @@ class Repetition(ParsingExpression):
class
Optional
(
Repetition
):
class
Optional
(
Repetition
):
'''
"""
Optional will try to match parser expression specified buy will not fail in
Optional will try to match parser expression specified buy will not fail in
case match is not successful.
case match is not successful.
'''
"""
def
_parse
(
self
,
parser
):
def
_parse
(
self
,
parser
):
result
=
None
result
=
None
try
:
try
:
...
@@ -277,10 +283,10 @@ class Optional(Repetition):
...
@@ -277,10 +283,10 @@ class Optional(Repetition):
class
ZeroOrMore
(
Repetition
):
class
ZeroOrMore
(
Repetition
):
'''
"""
ZeroOrMore will try to match parser expression specified zero or more
ZeroOrMore will try to match parser expression specified zero or more
times. It will never fail.
times. It will never fail.
'''
"""
def
_parse
(
self
,
parser
):
def
_parse
(
self
,
parser
):
results
=
[]
results
=
[]
while
True
:
while
True
:
...
@@ -295,9 +301,9 @@ class ZeroOrMore(Repetition):
...
@@ -295,9 +301,9 @@ class ZeroOrMore(Repetition):
class
OneOrMore
(
Repetition
):
class
OneOrMore
(
Repetition
):
'''
"""
OneOrMore will try to match parser expression specified one or more times.
OneOrMore will try to match parser expression specified one or more times.
'''
"""
def
_parse
(
self
,
parser
):
def
_parse
(
self
,
parser
):
results
=
[]
results
=
[]
first
=
False
first
=
False
...
@@ -316,11 +322,11 @@ class OneOrMore(Repetition):
...
@@ -316,11 +322,11 @@ class OneOrMore(Repetition):
class
SyntaxPredicate
(
ParsingExpression
):
class
SyntaxPredicate
(
ParsingExpression
):
'''
"""
Base class for all syntax predicates (and, not, empty).
Base class for all syntax predicates (and, not, empty).
Predicates are parser expressions that will do the match but will not
Predicates are parser expressions that will do the match but will not
consume any input.
consume any input.
'''
"""
def
__init__
(
self
,
*
elements
,
**
kwargs
):
def
__init__
(
self
,
*
elements
,
**
kwargs
):
if
len
(
elements
)
==
1
:
if
len
(
elements
)
==
1
:
elements
=
elements
[
0
]
elements
=
elements
[
0
]
...
@@ -335,10 +341,10 @@ class SyntaxPredicate(ParsingExpression):
...
@@ -335,10 +341,10 @@ class SyntaxPredicate(ParsingExpression):
class
And
(
SyntaxPredicate
):
class
And
(
SyntaxPredicate
):
'''
"""
This predicate will succeed if the specified expression matches current
This predicate will succeed if the specified expression matches current
input.
input.
'''
"""
def
_parse
(
self
,
parser
):
def
_parse
(
self
,
parser
):
for
e
in
self
.
nodes
:
for
e
in
self
.
nodes
:
try
:
try
:
...
@@ -350,10 +356,10 @@ class And(SyntaxPredicate):
...
@@ -350,10 +356,10 @@ class And(SyntaxPredicate):
class
Not
(
SyntaxPredicate
):
class
Not
(
SyntaxPredicate
):
'''
"""
This predicate will succeed if the specified expression doesn't match
This predicate will succeed if the specified expression doesn't match
current input.
current input.
'''
"""
def
_parse
(
self
,
parser
):
def
_parse
(
self
,
parser
):
for
e
in
self
.
nodes
:
for
e
in
self
.
nodes
:
try
:
try
:
...
@@ -366,17 +372,17 @@ class Not(SyntaxPredicate):
...
@@ -366,17 +372,17 @@ class Not(SyntaxPredicate):
class
Empty
(
SyntaxPredicate
):
class
Empty
(
SyntaxPredicate
):
'''
"""
This predicate will always succeed without consuming input.
This predicate will always succeed without consuming input.
'''
"""
def
_parse
(
self
,
parser
):
def
_parse
(
self
,
parser
):
pass
pass
class
Match
(
ParsingExpression
):
class
Match
(
ParsingExpression
):
'''
"""
Base class for all classes that will try to match something from the input.
Base class for all classes that will try to match something from the input.
'''
"""
def
__init__
(
self
,
rule
,
root
=
False
):
def
__init__
(
self
,
rule
,
root
=
False
):
super
(
Match
,
self
)
.
__init__
(
rule
,
root
)
super
(
Match
,
self
)
.
__init__
(
rule
,
root
)
...
@@ -421,11 +427,12 @@ class Match(ParsingExpression):
...
@@ -421,11 +427,12 @@ class Match(ParsingExpression):
class
RegExMatch
(
Match
):
class
RegExMatch
(
Match
):
'''
'''
This Match class will perform input matching based on Regular Expressions.
This Match class will perform input matching based on Regular Expressions.
Args:
to_match (regex string): A regular expression string to match. It will be
used to create regular expression using re.compile.
'''
'''
def
__init__
(
self
,
to_match
,
rule
=
None
,
flags
=
None
):
def
__init__
(
self
,
to_match
,
rule
=
None
,
flags
=
None
):
'''
@param to_match - regular expression string to match.
'''
super
(
RegExMatch
,
self
)
.
__init__
(
rule
)
super
(
RegExMatch
,
self
)
.
__init__
(
rule
)
self
.
to_match
=
to_match
self
.
to_match
=
to_match
if
flags
is
not
None
:
if
flags
is
not
None
:
...
@@ -449,13 +456,13 @@ class RegExMatch(Match):
...
@@ -449,13 +456,13 @@ class RegExMatch(Match):
class
StrMatch
(
Match
):
class
StrMatch
(
Match
):
'''
"""
This Match class will perform input matching by a string comparison.
This Match class will perform input matching by a string comparison.
'''
Args:
to_match (str): A string to match.
"""
def
__init__
(
self
,
to_match
,
rule
=
None
,
root
=
False
):
def
__init__
(
self
,
to_match
,
rule
=
None
,
root
=
False
):
'''
@param to_match - string to match.
'''
super
(
StrMatch
,
self
)
.
__init__
(
rule
,
root
)
super
(
StrMatch
,
self
)
.
__init__
(
rule
,
root
)
self
.
to_match
=
to_match
self
.
to_match
=
to_match
...
@@ -481,9 +488,9 @@ class StrMatch(Match):
...
@@ -481,9 +488,9 @@ class StrMatch(Match):
# HACK: Kwd class is a bit hackish. Need to find a better way to
# HACK: Kwd class is a bit hackish. Need to find a better way to
# introduce different classes of string tokens.
# introduce different classes of string tokens.
class
Kwd
(
StrMatch
):
class
Kwd
(
StrMatch
):
'''
"""
S
pecialization of StrMatch to specify keywords of the language.
A s
pecialization of StrMatch to specify keywords of the language.
'''
"""
def
__init__
(
self
,
to_match
):
def
__init__
(
self
,
to_match
):
super
(
Kwd
,
self
)
.
__init__
(
to_match
,
rule
=
None
)
super
(
Kwd
,
self
)
.
__init__
(
to_match
,
rule
=
None
)
self
.
to_match
=
to_match
self
.
to_match
=
to_match
...
@@ -492,9 +499,9 @@ class Kwd(StrMatch):
...
@@ -492,9 +499,9 @@ class Kwd(StrMatch):
class
EndOfFile
(
Match
):
class
EndOfFile
(
Match
):
'''
"""
Match class that will succeed in case end of input is reached.
The
Match class that will succeed in case end of input is reached.
'''
"""
def
__init__
(
self
,
rule
=
None
):
def
__init__
(
self
,
rule
=
None
):
super
(
EndOfFile
,
self
)
.
__init__
(
rule
)
super
(
EndOfFile
,
self
)
.
__init__
(
rule
)
...
@@ -520,19 +527,18 @@ def EOF(): return EndOfFile()
...
@@ -520,19 +527,18 @@ def EOF(): return EndOfFile()
# Parse Tree node classes
# Parse Tree node classes
class
ParseTreeNode
(
object
):
class
ParseTreeNode
(
object
):
'''
"""
Abstract base class representing node of the Parse Tree.
Abstract base class representing node of the Parse Tree.
The node can be terminal(the leaf of the parse tree) or non-terminal.
The node can be terminal(the leaf of the parse tree) or non-terminal.
'''
Attributes:
type (str): The name of the rule that created this node or empty
string in case this node is created by a non-root pexpression.
position (int): A position in the input stream where the match occurred.
error (bool): Is this a false parse tree node created during error recovery.
comments : A parse tree of comment(s) attached to this node.
"""
def
__init__
(
self
,
type
,
position
,
error
):
def
__init__
(
self
,
type
,
position
,
error
):
'''
@param type - the name of the rule that created this node or empty
string in case this node is created by a non-root
parser model node.
@param position - position in the input stream where match occurred.
@param error - is this a false parse tree node created during error
recovery?
'''
self
.
type
=
type
self
.
type
=
type
self
.
position
=
position
self
.
position
=
position
self
.
error
=
error
self
.
error
=
error
...
@@ -544,20 +550,20 @@ class ParseTreeNode(object):
...
@@ -544,20 +550,20 @@ class ParseTreeNode(object):
class
Terminal
(
ParseTreeNode
):
class
Terminal
(
ParseTreeNode
):
'''
"""
Leaf node of the Parse Tree. Represents matched string.
Leaf node of the Parse Tree. Represents matched string.
'''
Attributes:
value (str): Matched string at the given position or missing token
name in the case of an error node.
"""
def
__init__
(
self
,
type
,
position
,
value
,
error
=
False
):
def
__init__
(
self
,
type
,
position
,
value
,
error
=
False
):
'''
@param value - matched string or missing token name in case of an error
node.
'''
super
(
Terminal
,
self
)
.
__init__
(
type
,
position
,
error
)
super
(
Terminal
,
self
)
.
__init__
(
type
,
position
,
error
)
self
.
value
=
value
self
.
value
=
value
@property
@property
def
desc
(
self
):
def
desc
(
self
):
return
"
%
s
\'
%
s
\
'
[
%
s]"
%
(
self
.
type
,
self
.
value
,
self
.
position
)
return
"
%
s
'
%
s
' [
%
s]"
%
(
self
.
type
,
self
.
value
,
self
.
position
)
def
__str__
(
self
):
def
__str__
(
self
):
return
self
.
value
return
self
.
value
...
@@ -567,13 +573,14 @@ class Terminal(ParseTreeNode):
...
@@ -567,13 +573,14 @@ class Terminal(ParseTreeNode):
class
NonTerminal
(
ParseTreeNode
):
class
NonTerminal
(
ParseTreeNode
):
'''
"""
Non-leaf node of the Parse Tree. Represents language syntax construction.
Non-leaf node of the Parse Tree. Represents language syntax construction.
'''
Attributes:
nodes (list of ParseTreeNode): Children parse tree nodes.
"""
def
__init__
(
self
,
type
,
position
,
nodes
,
error
=
False
):
def
__init__
(
self
,
type
,
position
,
nodes
,
error
=
False
):
'''
@param nodes - child ParseTreeNode
'''
super
(
NonTerminal
,
self
)
.
__init__
(
type
,
position
,
error
)
super
(
NonTerminal
,
self
)
.
__init__
(
type
,
position
,
error
)
self
.
nodes
=
flatten
([
nodes
])
self
.
nodes
=
flatten
([
nodes
])
...
@@ -593,7 +600,7 @@ class NonTerminal(ParseTreeNode):
...
@@ -593,7 +600,7 @@ class NonTerminal(ParseTreeNode):
#
#
class
SemanticAction
(
object
):
class
SemanticAction
(
object
):
'''
"""
Semantic actions are executed during semantic analysis. They are in charge
Semantic actions are executed during semantic analysis. They are in charge
of producing Abstract Semantic Graph (ASG) out of the parse tree.
of producing Abstract Semantic Graph (ASG) out of the parse tree.
Every non-terminal and terminal can have semantic action defined which will
Every non-terminal and terminal can have semantic action defined which will
...
@@ -603,11 +610,11 @@ class SemanticAction(object):
...
@@ -603,11 +610,11 @@ class SemanticAction(object):
if exists after the first pass. Second pass can be used for forward
if exists after the first pass. Second pass can be used for forward
referencing, e.g. linking to the declaration registered in the first pass
referencing, e.g. linking to the declaration registered in the first pass
stage.
stage.
'''
"""
def
first_pass
(
self
,
parser
,
node
,
nodes
):
def
first_pass
(
self
,
parser
,
node
,
nodes
):
'''
"""
Called in the first pass of tree walk.
Called in the first pass of tree walk.
'''
"""
raise
NotImplementedError
()
raise
NotImplementedError
()
...
@@ -616,14 +623,18 @@ class SemanticAction(object):
...
@@ -616,14 +623,18 @@ class SemanticAction(object):
class
Parser
(
object
):
class
Parser
(
object
):
"""
Abstract base class for all parsers.
Attributes:
skipws (bool): Should the whitespace skipping be done.
ws (str): A string consisting of whitespace characters.
reduce_tree (bool): If true non-terminals with single child will be
eliminated from the parse tree.
debug (bool): If true debugging messages will be printed.
comments_model (a list of
"""
def
__init__
(
self
,
skipws
=
True
,
ws
=
DEFAULT_WS
,
reduce_tree
=
False
,
debug
=
False
):
def
__init__
(
self
,
skipws
=
True
,
ws
=
DEFAULT_WS
,
reduce_tree
=
False
,
debug
=
False
):
'''
@skipws - if True whitespaces will not be part of parse tree.
@ws - rule for matching ws
@reduce_tree - if true nonterminals with single child will be
eliminated.
@debug - If true debug messages will get printed.
'''
self
.
skipws
=
skipws
self
.
skipws
=
skipws
self
.
ws
=
ws
self
.
ws
=
ws
self
.
reduce_tree
=
reduce_tree
self
.
reduce_tree
=
reduce_tree
...
@@ -645,12 +656,14 @@ class Parser(object):
...
@@ -645,12 +656,14 @@ class Parser(object):
return
self
.
parse_tree
return
self
.
parse_tree
def
getASG
(
self
,
sem_actions
=
None
):
def
getASG
(
self
,
sem_actions
=
None
):
'''
"""
Creates Abstract Semantic Graph (ASG) from the parse tree.
Creates Abstract Semantic Graph (ASG) from the parse tree.
@param sem_actions - semantic actions dictionary to use for semantic
analysis. Rule names are the keys and semantic
Args:
action objects are values.
sem_actions (dict): The semantic actions dictionary to use for semantic
'''
analysis. Rule names are the keys and semantic action objects are
values.
"""
if
not
self
.
parse_tree
:
if
not
self
.
parse_tree
:
raise
Exception
(
"Parse tree is empty. You did call parse(), didn't you?"
)
raise
Exception
(
"Parse tree is empty. You did call parse(), didn't you?"
)
...
@@ -666,11 +679,11 @@ class Parser(object):
...
@@ -666,11 +679,11 @@ class Parser(object):
for_second_pass
=
[]
for_second_pass
=
[]
def
tree_walk
(
node
):
def
tree_walk
(
node
):
'''
"""
Walking the parse tree and calling first_pass for every registered
Walking the parse tree and calling first_pass for every registered
semantic actions and creating list of object that needs to be
semantic actions and creating list of object that needs to be
called in the second pass.
called in the second pass.
'''
"""
nodes
=
[]
nodes
=
[]
if
isinstance
(
node
,
NonTerminal
):
if
isinstance
(
node
,
NonTerminal
):
for
n
in
node
.
nodes
:
for
n
in
node
.
nodes
:
...
@@ -701,9 +714,9 @@ class Parser(object):
...
@@ -701,9 +714,9 @@ class Parser(object):
return
asg
return
asg
def
pos_to_linecol
(
self
,
pos
):
def
pos_to_linecol
(
self
,
pos
):
'''
"""
Calculate (line, column) tuple for the given position in the stream.
Calculate (line, column) tuple for the given position in the stream.
'''
"""
if
not
self
.
line_ends
:
if
not
self
.
line_ends
:
try
:
try
:
#TODO: Check this implementation on Windows.
#TODO: Check this implementation on Windows.
...
@@ -726,9 +739,9 @@ class Parser(object):
...
@@ -726,9 +739,9 @@ class Parser(object):
return
line
+
1
,
col
+
1
return
line
+
1
,
col
+
1
def
_skip_ws
(
self
):
def
_skip_ws
(
self
):
'''
"""
Skiping whitespace characters.
Skiping whitespace characters.
'''
"""
if
self
.
skipws
:
if
self
.
skipws
:
while
self
.
position
<
len
(
self
.
input
)
and
\
while
self
.
position
<
len
(
self
.
input
)
and
\
self
.
input
[
self
.
position
]
in
self
.
ws
:
self
.
input
[
self
.
position
]
in
self
.
ws
:
...
@@ -743,11 +756,13 @@ class Parser(object):
...
@@ -743,11 +756,13 @@ class Parser(object):
return
comments
return
comments
def
_nm_raise
(
self
,
*
args
):
def
_nm_raise
(
self
,
*
args
):
'''
"""
Register new NoMatch object if the input is consumed
Register new NoMatch object if the input is consumed
from the last NoMatch and raise last NoMatch
from the last NoMatch and raise last NoMatch.
@param args - NoMatch instance or value, position, parser
'''
Args:
args: A NoMatch instance or (value, position, parser)
"""
if
not
self
.
_in_parse_comment
:
if
not
self
.
_in_parse_comment
:
if
len
(
args
)
==
1
and
isinstance
(
args
[
0
],
NoMatch
):
if
len
(
args
)
==
1
and
isinstance
(
args
[
0
],
NoMatch
):
if
self
.
nm
is
None
or
args
[
0
]
.
position
>
self
.
nm
.
position
:
if
self
.
nm
is
None
or
args
[
0
]
.
position
>
self
.
nm
.
position
:
...
@@ -781,7 +796,9 @@ class ParserPython(Parser):
...
@@ -781,7 +796,9 @@ class ParserPython(Parser):
Create parser model from the definition given in the form of python
Create parser model from the definition given in the form of python
functions returning lists, tuples, callables, strings and
functions returning lists, tuples, callables, strings and
ParsingExpression objects.
ParsingExpression objects.
@returns - Parser Model (PEG Abstract Semantic Graph)
Returns:
Parser Model (PEG Abstract Semantic Graph)
"""
"""
__rule_cache
=
{
"EndOfFile"
:
EndOfFile
()}
__rule_cache
=
{
"EndOfFile"
:
EndOfFile
()}
__for_resolving
=
[]
# Expressions that needs crossref resolvnih
__for_resolving
=
[]
# Expressions that needs crossref resolvnih
...
...
arpeggio/export.py
View file @
c2bb10f5
...
@@ -12,9 +12,9 @@ from arpeggio import Terminal
...
@@ -12,9 +12,9 @@ from arpeggio import Terminal
class
Export
(
object
):
class
Export
(
object
):
'''
"""
Base class for all Exporters.
Base class for all Exporters.
'''
"""
def
__init__
(
self
):
def
__init__
(
self
):
super
(
Export
,
self
)
.
__init__
()
super
(
Export
,
self
)
.
__init__
()
...
@@ -30,13 +30,17 @@ class Export(object):
...
@@ -30,13 +30,17 @@ class Export(object):
# returned for the same adaptee object
# returned for the same adaptee object
def
export
(
self
,
obj
):
def
export
(
self
,
obj
):
'''Export of obj to a string.'''
"""
Export of an obj to a string.
"""
self
.
_outf
=
StringIO
()
self
.
_outf
=
StringIO
()
self
.
_export
(
obj
)
self
.
_export
(
obj
)
return
self
.
_outf
.
getvalue
()
return
self
.
_outf
.
getvalue
()
def
exportFile
(
self
,
obj
,
file_name
):
def
exportFile
(
self
,
obj
,
file_name
):
'''Export of obj to a file.'''
"""
Export of obj to a file.
"""
self
.
_outf
=
open
(
file_name
,
"w"
)
self
.
_outf
=
open
(
file_name
,
"w"
)
self
.
_export
(
obj
)
self
.
_export
(
obj
)
self
.
_outf
.
close
()
self
.
_outf
.
close
()
...
@@ -47,15 +51,15 @@ class Export(object):
...
@@ -47,15 +51,15 @@ class Export(object):
self
.
_outf
.
write
(
self
.
_end
())
self
.
_outf
.
write
(
self
.
_end
())
def
_start
(
self
):
def
_start
(
self
):
'''
"""
Override this to specify the beginning of the graph representation.
Override this to specify the beginning of the graph representation.
'''
"""
return
""
return
""
def
_end
(
self
):
def
_end
(
self
):
'''
"""
Override this to specify the end of the graph representation.
Override this to specify the end of the graph representation.
'''
"""
return
""
return
""
...
@@ -63,12 +67,12 @@ class ExportAdapter(object):
...
@@ -63,12 +67,12 @@ class ExportAdapter(object):
'''
'''
Base adapter class for the export support.
Base adapter class for the export support.
Adapter should be defined for every graph type.
Adapter should be defined for every graph type.
Attributes:
adaptee: A node to adapt.
export: An export object used as a context of the export.
'''
'''
def
__init__
(
self
,
node
,
export
):
def
__init__
(
self
,
node
,
export
):
'''
@param node - node to adapt
@param export - export object used as a context of the export.
'''
self
.
adaptee
=
node
# adaptee is adapted graph node
self
.
adaptee
=
node
# adaptee is adapted graph node
self
.
export
=
export
self
.
export
=
export
...
@@ -78,29 +82,35 @@ class ExportAdapter(object):
...
@@ -78,29 +82,35 @@ class ExportAdapter(object):
class
DOTExportAdapter
(
ExportAdapter
):
class
DOTExportAdapter
(
ExportAdapter
):
'''
"""
Base adapter class for the DOT export support.
Base adapter class for the DOT export support.
'''
"""
@property
@property
def
id
(
self
):
def
id
(
self
):
'''Graph node unique identification.'''
"""
Graph node unique identification.
"""
raise
NotImplementedError
()
raise
NotImplementedError
()
@property
@property
def
desc
(
self
):
def
desc
(
self
):
'''Graph node textual description.'''
"""
Graph node textual description.
"""
raise
NotImplementedError
()
raise
NotImplementedError
()
@property
@property
def
children
(
self
):
def
children
(
self
):
'''Children of the graph node.'''
"""
Children of the graph node.
"""
raise
NotImplementedError
()
raise
NotImplementedError
()
class
PMDOTExportAdapter
(
DOTExportAdapter
):
class
PMDOTExportAdapter
(
DOTExportAdapter
):
'''
"""
Adapter for ParsingExpression graph types (parser model).
Adapter for ParsingExpression graph types (parser model).
'''
"""
@property
@property
def
id
(
self
):
def
id
(
self
):
return
id
(
self
.
adaptee
)
return
id
(
self
.
adaptee
)
...
@@ -133,9 +143,9 @@ class PMDOTExportAdapter(DOTExportAdapter):
...
@@ -133,9 +143,9 @@ class PMDOTExportAdapter(DOTExportAdapter):
class
PTDOTExportAdapter
(
PMDOTExportAdapter
):
class
PTDOTExportAdapter
(
PMDOTExportAdapter
):
'''
"""
Adapter for ParseTreeNode graph types.
Adapter for ParseTreeNode graph types.
'''
"""
@property
@property
def
children
(
self
):
def
children
(
self
):
if
isinstance
(
self
.
adaptee
,
Terminal
):
if
isinstance
(
self
.
adaptee
,
Terminal
):
...
@@ -150,9 +160,9 @@ class PTDOTExportAdapter(PMDOTExportAdapter):
...
@@ -150,9 +160,9 @@ class PTDOTExportAdapter(PMDOTExportAdapter):
class
DOTExport
(
Export
):
class
DOTExport
(
Export
):
'''
"""
Export to DOT language (part of GraphViz, see http://www.graphviz.org/)
Export to DOT language (part of GraphViz, see http://www.graphviz.org/)
'''
"""
def
_render_node
(
self
,
node
):
def
_render_node
(
self
,
node
):
if
not
node
in
self
.
_render_set
:
if
not
node
in
self
.
_render_set
:
self
.
_render_set
.
add
(
node
)
self
.
_render_set
.
add
(
node
)
...
@@ -183,9 +193,9 @@ class DOTExport(Export):
...
@@ -183,9 +193,9 @@ class DOTExport(Export):
class
PMDOTExport
(
DOTExport
):
class
PMDOTExport
(
DOTExport
):
'''
"""
C
onvenience DOTExport extension that uses ParserExpressionDOTExportAdapter
A c
onvenience DOTExport extension that uses ParserExpressionDOTExportAdapter
'''
"""
def
export
(
self
,
obj
):
def
export
(
self
,
obj
):
return
super
(
PMDOTExport
,
self
)
.
\
return
super
(
PMDOTExport
,
self
)
.
\
export
(
PMDOTExportAdapter
(
obj
,
self
))
export
(
PMDOTExportAdapter
(
obj
,
self
))
...
@@ -196,9 +206,9 @@ class PMDOTExport(DOTExport):
...
@@ -196,9 +206,9 @@ class PMDOTExport(DOTExport):
class
PTDOTExport
(
DOTExport
):
class
PTDOTExport
(
DOTExport
):
'''
"""
C
onvenience DOTExport extension that uses PTDOTExportAdapter
A c
onvenience DOTExport extension that uses PTDOTExportAdapter
'''
"""
def
export
(
self
,
obj
):
def
export
(
self
,
obj
):
return
super
(
PTDOTExport
,
self
)
.
\
return
super
(
PTDOTExport
,
self
)
.
\
export
(
PTDOTExportAdapter
(
obj
,
self
))
export
(
PTDOTExportAdapter
(
obj
,
self
))
...
...
examples/bibtex.py
View file @
c2bb10f5
...
@@ -26,7 +26,9 @@ def comment(): return _(r'[^@]+')
...
@@ -26,7 +26,9 @@ def comment(): return _(r'[^@]+')
# Semantic actions
# Semantic actions
class
BibFileSem
(
SemanticAction
):
class
BibFileSem
(
SemanticAction
):
'''Just returns list of child nodes (bibentries).'''
"""
Just returns list of child nodes (bibentries).
"""
def
first_pass
(
self
,
parser
,
node
,
nodes
):
def
first_pass
(
self
,
parser
,
node
,
nodes
):
if
parser
.
debug
:
if
parser
.
debug
:
print
"Processing Bibfile"
print
"Processing Bibfile"
...
@@ -34,8 +36,10 @@ class BibFileSem(SemanticAction):
...
@@ -34,8 +36,10 @@ class BibFileSem(SemanticAction):
class
BibEntrySem
(
SemanticAction
):
class
BibEntrySem
(
SemanticAction
):
'''Constructs a map where key is bibentry field name.
"""
Key is returned under 'bibkey' key. Type is returned under 'bibtype'.'''
Constructs a map where key is bibentry field name.
Key is returned under 'bibkey' key. Type is returned under 'bibtype'.
"""
def
first_pass
(
self
,
parser
,
node
,
nodes
):
def
first_pass
(
self
,
parser
,
node
,
nodes
):
if
parser
.
debug
:
if
parser
.
debug
:
print
" Processing bibentry
%
s"
%
nodes
[
2
]
print
" Processing bibentry
%
s"
%
nodes
[
2
]
...
@@ -50,7 +54,9 @@ class BibEntrySem(SemanticAction):
...
@@ -50,7 +54,9 @@ class BibEntrySem(SemanticAction):
class
FieldSem
(
SemanticAction
):
class
FieldSem
(
SemanticAction
):
'''Constructs a tuple (fieldname, fieldvalue).'''
"""
Constructs a tuple (fieldname, fieldvalue).
"""
def
first_pass
(
self
,
parser
,
node
,
nodes
):
def
first_pass
(
self
,
parser
,
node
,
nodes
):
if
parser
.
debug
:
if
parser
.
debug
:
print
" Processing field
%
s"
%
nodes
[
0
]
print
" Processing field
%
s"
%
nodes
[
0
]
...
@@ -59,7 +65,9 @@ class FieldSem(SemanticAction):
...
@@ -59,7 +65,9 @@ class FieldSem(SemanticAction):
class
FieldValueSem
(
SemanticAction
):
class
FieldValueSem
(
SemanticAction
):
'''Serbian Serbian letters form latex encoding to Unicode.'''
"""
Serbian Serbian letters form latex encoding to Unicode.
"""
def
first_pass
(
self
,
parser
,
node
,
nodes
):
def
first_pass
(
self
,
parser
,
node
,
nodes
):
return
node
.
value
.
replace
(
r"\'{c}"
,
u"ć"
)
\
return
node
.
value
.
replace
(
r"\'{c}"
,
u"ć"
)
\
.
replace
(
r"\'{C}"
,
u"Ć"
)
\
.
replace
(
r"\'{C}"
,
u"Ć"
)
\
...
...
examples/calc.py
View file @
c2bb10f5
...
@@ -24,13 +24,17 @@ def calc(): return OneOrMore(expression), EndOfFile
...
@@ -24,13 +24,17 @@ def calc(): return OneOrMore(expression), EndOfFile
# Semantic actions
# Semantic actions
class
ToFloat
(
SemanticAction
):
class
ToFloat
(
SemanticAction
):
'''Converts node value to float.'''
"""
Converts node value to float.
"""
def
first_pass
(
self
,
parser
,
node
,
nodes
):
def
first_pass
(
self
,
parser
,
node
,
nodes
):
print
"Converting
%
s."
%
node
.
value
print
"Converting
%
s."
%
node
.
value
return
float
(
node
.
value
)
return
float
(
node
.
value
)
class
Factor
(
SemanticAction
):
class
Factor
(
SemanticAction
):
'''Removes parenthesis if exists and returns what was contained inside.'''
"""
Removes parenthesis if exists and returns what was contained inside.
"""
def
first_pass
(
self
,
parser
,
node
,
nodes
):
def
first_pass
(
self
,
parser
,
node
,
nodes
):
print
"Factor
%
s"
%
nodes
print
"Factor
%
s"
%
nodes
if
len
(
nodes
)
==
1
:
if
len
(
nodes
)
==
1
:
...
@@ -45,10 +49,10 @@ class Factor(SemanticAction):
...
@@ -45,10 +49,10 @@ class Factor(SemanticAction):
return
sign
*
nodes
[
next
]
return
sign
*
nodes
[
next
]
class
Term
(
SemanticAction
):
class
Term
(
SemanticAction
):
'''
"""
Divides or multiplies factors.
Divides or multiplies factors.
Factor nodes will be already evaluated.
Factor nodes will be already evaluated.
'''
"""
def
first_pass
(
self
,
parser
,
node
,
nodes
):
def
first_pass
(
self
,
parser
,
node
,
nodes
):
print
"Term
%
s"
%
nodes
print
"Term
%
s"
%
nodes
term
=
nodes
[
0
]
term
=
nodes
[
0
]
...
@@ -61,10 +65,10 @@ class Term(SemanticAction):
...
@@ -61,10 +65,10 @@ class Term(SemanticAction):
return
term
return
term
class
Expr
(
SemanticAction
):
class
Expr
(
SemanticAction
):
'''
"""
Adds or substracts terms.
Adds or substracts terms.
Term nodes will be already evaluated.
Term nodes will be already evaluated.
'''
"""
def
first_pass
(
self
,
parser
,
node
,
nodes
):
def
first_pass
(
self
,
parser
,
node
,
nodes
):
print
"Expression
%
s"
%
nodes
print
"Expression
%
s"
%
nodes
expr
=
0
expr
=
0
...
...
examples/calc_peg.py
View file @
c2bb10f5
...
@@ -27,7 +27,7 @@ calc_grammar = """
...
@@ -27,7 +27,7 @@ calc_grammar = """
(number / "(" expression ")");
(number / "(" expression ")");
term <- factor (( "*" / "/") factor)*;
term <- factor (( "*" / "/") factor)*;
expression <- term (("+" / "-") term)*;
expression <- term (("+" / "-") term)*;
calc <- expression EndOfFile;
calc <- expression
+
EndOfFile;
"""
"""
# Rules are mapped to semantic actions
# Rules are mapped to semantic actions
...
...
examples/json.py
View file @
c2bb10f5
...
@@ -5,7 +5,7 @@
...
@@ -5,7 +5,7 @@
# Copyright: (c) 2009 Igor R. Dejanovic <igor DOT dejanovic AT gmail DOT com>
# Copyright: (c) 2009 Igor R. Dejanovic <igor DOT dejanovic AT gmail DOT com>
# License: MIT License
# License: MIT License
#
#
# This example is based on jsonParser.py from pyparsing project
# This example is based on jsonParser.py from
the
pyparsing project
# (see http://pyparsing.wikispaces.com/).
# (see http://pyparsing.wikispaces.com/).
##############################################################################
##############################################################################
...
...
examples/simple.py
View file @
c2bb10f5
...
@@ -31,8 +31,8 @@ def simpleLanguage(): return function
...
@@ -31,8 +31,8 @@ def simpleLanguage(): return function
try
:
try
:
# Parser instantiation. simpleLanguage is
root definition and comment is
# Parser instantiation. simpleLanguage is
the definition of the root rule
# grammar rule for comments.
#
and comment is a
grammar rule for comments.
parser
=
ParserPython
(
simpleLanguage
,
comment
,
debug
=
True
)
parser
=
ParserPython
(
simpleLanguage
,
comment
,
debug
=
True
)
# We save parser model to dot file in order to visualise it.
# We save parser model to dot file in order to visualise it.
...
...
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