Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
badw-it
DHParser
Commits
6ef3b9fe
Commit
6ef3b9fe
authored
Feb 24, 2019
by
Eckhart Arnold
Browse files
- transform.py: left_associative() and swing_left() added for rearranging trees (see docstrings.)
parent
d34bec8e
Changes
6
Hide whitespace changes
Inline
Side-by-side
DHParser/transform.py
View file @
6ef3b9fe
...
...
@@ -511,6 +511,10 @@ def has_parent(context: List[Node], tag_name_set: AbstractSet[str]) -> bool:
def
update_attr
(
node
:
Node
,
child
:
Node
):
"""
Adds all attributes from `child` to `node`.This is needed, in order
to keep the attributes if the child node is going to be eliminated.
"""
if
hasattr
(
child
,
'_xml_attr'
):
for
k
,
v
in
child
.
attr
:
if
k
in
node
.
attr
and
v
!=
node
.
attr
[
k
]:
...
...
@@ -520,7 +524,29 @@ def update_attr(node: Node, child: Node):
node
.
attr
[
k
]
=
v
def
swap_attributes
(
node
:
Node
,
other
:
Node
):
"""
Exchanges the attributes between node and other. This might be
needed when rearanging trees.
"""
NA
=
node
.
attr_active
()
OA
=
other
.
attr_active
()
if
NA
or
OA
:
save
=
node
.
_xml_attr
if
NA
else
None
if
OA
:
node
.
_xml_attr
=
other
.
_xml_attr
elif
NA
:
node
.
_xml_attr
=
None
if
NA
:
other
.
_xml_attr
=
node
.
_xml_attr
elif
OA
:
other
.
_xml_attr
=
None
def
_replace_by
(
node
:
Node
,
child
:
Node
):
"""
Replaces node's contents by child's content including the tag name.
"""
if
node
.
is_anonymous
()
or
not
child
.
is_anonymous
():
node
.
tag_name
=
child
.
tag_name
# name, ptype = (node.tag_name.split(':') + [''])[:2]
...
...
@@ -531,6 +557,9 @@ def _replace_by(node: Node, child: Node):
def
_reduce_child
(
node
:
Node
,
child
:
Node
):
"""
Sets node's results to the child's result, keeping node's tag_name.
"""
node
.
result
=
child
.
result
update_attr
(
node
,
child
)
...
...
@@ -846,9 +875,68 @@ def move_adjacent(context: List[Node], condition: Callable = is_insignificant_wh
def
left_associative
(
context
:
List
[
Node
]):
"""
Rearranges a flat node into a left associative tree.
Rearranges a flat node
with infix operators
into a left associative tree.
"""
node
=
context
[
-
1
]
assert
len
(
node
.
children
)
>=
3
assert
(
len
(
node
.
children
)
+
1
)
%
2
==
0
rest
=
list
(
node
.
result
)
left
,
rest
=
rest
[
0
],
rest
[
1
:]
while
rest
:
infix
,
right
,
rest
=
rest
[:
2
],
rest
[
2
:]
assert
not
infix
.
children
assert
infix
.
tag_name
[
0
:
1
]
!=
":"
left
=
Node
(
infix
.
tag_name
,
(
left
,
right
))
node
.
result
=
left
@
transformation_factory
(
collections
.
abc
.
Set
)
def
left_swing
(
context
:
List
[
Node
],
operators
:
AbstractSet
[
str
]):
"""
Rearranges a node that contains a sub-node on the right
with a left-associative operator so that the tree structure
reflects its left-associative character.
"""
node
=
context
[
-
1
]
assert
node
.
children
and
len
(
node
.
children
)
==
2
assert
node
.
tag_name
in
operators
right
=
node
.
children
[
1
]
if
right
.
tag_name
in
operators
:
assert
right
.
children
and
len
(
right
.
children
)
==
2
a
,
b
,
c
=
node
.
children
[
0
],
right
.
children
[
0
],
right
.
children
[
1
]
op1
=
node
.
tag_name
op2
=
right
.
tag_name
right
.
result
=
(
a
,
b
)
right
.
tag_name
=
op1
node
.
result
=
(
right
,
c
)
node
.
tag_name
=
op2
swap_attributes
(
node
,
right
)
# @transformation_factory(collections.abc.Set)
# def left_associative_tree(context: List[Node], operators: AbstracSet[str]):
# """
# Rearranges a right associative tree into a left associative tree.
# ``operators`` is a list of tag names of nodes that shall be rearranged.
# Other nodes will be lelft untouched.
# """
# node = context[-1]
# assert node.tag_name in operators
# right = node.children[1]
# while right.tag_name in operators:
# node.result = (node.children[0], right.children[0])
# right.result = (node, right.children[1])
# node = right
# right = node.children[1]
# parent = context[-2]
# result = list(parent.result)
# for i in range(len(result)):
# if result[i] == contexnt[-1]:
# result[i] = node
# parent.result = tuple(result)
# break
# else:
# assert False, "???"
#######################################################################
...
...
examples/ArithmeticExperimental/ArithmeticExperimental.ebnf
View file @
6ef3b9fe
...
...
@@ -19,10 +19,9 @@
#
#######################################################################
expression = ((addition | subtraction | term) !/[+-]/)
| ((subtraction | addition | term) !/[-+]/)
addition = (subtraction | addition | term) "+" term
subtraction = (addition | subtraction | term) "-" term
expression = add | sub | term
add = term "+" expression
sub = term "-" expression
#######################################################################
...
...
@@ -31,9 +30,9 @@ subtraction = (addition | subtraction | term) "-" term
#
#######################################################################
term
= mul
tiplication
| div
ision
| factor
mul
tiplication
= factor ["*"] term
div
ision
=
term "/" (multiplication | factor)
term = mul | div | factor
mul
= factor ["*"] term
div
=
factor "/" term
#######################################################################
...
...
@@ -42,9 +41,9 @@ division = term "/" (multiplication | factor)
#
#######################################################################
factor
= [sign] ( NUMBER | VARIABLE | group )
sign
= PLUS | MINUS
group
= "(" §expression ")"
factor = [sign] ( NUMBER | VARIABLE | group )
sign = PLUS | MINUS
group = "(" §expression ")"
#######################################################################
...
...
@@ -53,7 +52,7 @@ group = "(" §expression ")"
#
#######################################################################
PLUS = /\+/
MINUS = /-/
NUMBER = /(?:0|(?:[1-9]\d*))(?:\.\d+)?/~
VARIABLE = /[A-Za-z]/~
PLUS
= /\+/
MINUS
= /-/
NUMBER
= /(?:0|(?:[1-9]\d*))(?:\.\d+)?/~
VARIABLE
= /[A-Za-z]/~
examples/ArithmeticExperimental/ArithmeticExperimentalCompiler.py
View file @
6ef3b9fe
...
...
@@ -58,12 +58,9 @@ def get_preprocessor() -> PreprocessorFunc:
class
ArithmeticExperimentalGrammar
(
Grammar
):
r
"""Parser for an ArithmeticExperimental source file.
"""
addition
=
Forward
()
expression
=
Forward
()
multiplication
=
Forward
()
subtraction
=
Forward
()
term
=
Forward
()
source_hash__
=
"
1811447b927aae855ee58328bce76d20
"
source_hash__
=
"
59c96ad0b1c0703bea6ba8fc50253bea
"
static_analysis_pending__
=
[
True
]
parser_initialization__
=
[
"upon instantiation"
]
resume_rules__
=
{}
...
...
@@ -79,12 +76,12 @@ class ArithmeticExperimentalGrammar(Grammar):
group
=
Series
(
Series
(
DropToken
(
"("
),
dwsp__
),
expression
,
Series
(
DropToken
(
")"
),
dwsp__
),
mandatory
=
1
)
sign
=
Alternative
(
PLUS
,
MINUS
)
factor
=
Series
(
Option
(
sign
),
Alternative
(
NUMBER
,
VARIABLE
,
group
))
div
ision
=
Series
(
term
,
Series
(
DropToken
(
"/"
),
dwsp__
),
Al
ter
native
(
multiplication
,
factor
)
)
mul
tiplication
.
set
(
Series
(
factor
,
Option
(
Series
(
DropToken
(
"*"
),
dwsp__
)),
term
)
)
term
.
set
(
Alternative
(
mul
tiplication
,
division
,
factor
))
sub
traction
.
set
(
Series
(
Alternative
(
addition
,
subtraction
,
term
)
,
Series
(
DropToken
(
"-"
),
dwsp__
),
term
)
)
add
ition
.
set
(
Series
(
Alternative
(
subtraction
,
addition
,
term
)
,
Series
(
DropToken
(
"+"
),
dwsp__
),
term
)
)
expression
.
set
(
Alternative
(
Series
(
Alternative
(
addition
,
subtraction
,
term
),
NegativeLookahead
(
RegExp
(
'[+-]'
))),
Series
(
Alternative
(
subtraction
,
addition
,
term
),
NegativeLookahead
(
RegExp
(
'[-+]'
)))
))
div
=
Series
(
factor
,
Series
(
DropToken
(
"/"
),
dwsp__
),
ter
m
)
mul
=
Series
(
factor
,
Option
(
Series
(
DropToken
(
"*"
),
dwsp__
)),
term
)
term
.
set
(
Alternative
(
mul
,
div
,
factor
))
sub
=
Series
(
term
,
Series
(
DropToken
(
"-"
),
dwsp__
),
expression
)
add
=
Series
(
term
,
Series
(
DropToken
(
"+"
),
dwsp__
),
expression
)
expression
.
set
(
Alternative
(
add
,
sub
,
term
))
root__
=
expression
def
get_grammar
()
->
ArithmeticExperimentalGrammar
:
...
...
examples/ArithmeticExperimental/grammar_tests/03_test_Terms.ini
View file @
6ef3b9fe
...
...
@@ -13,19 +13,19 @@ M7: "-2x"
[fail:term]
[match:mul
tiplication
]
[match:mul]
M1:
"2
*
4"
[ast:mul
tiplication
]
[ast:mul]
[fail:mul
tiplication
]
[fail:mul]
[match:div
ision
]
[match:div]
M1:
"2
/
4"
M2:
"-x
/
7"
[ast:div
ision
]
[ast:div]
[fail:div
ision
]
[fail:div]
examples/ArithmeticExperimental/grammar_tests/04_test_Expressions.ini
View file @
6ef3b9fe
...
...
@@ -13,23 +13,25 @@ M10: "1 + 2 + 3 - 4"
M11:
"1
-
2
+
3
-
4"
M12:
"1
+
2
-
3
-
4"
M13:
"1
-
2
-
3
-
4"
M14:
"1
-
2
*
3
-
4
+
5"
M15:
"1
-
3
+
3
*
4"
[ast:expression]
[fail:expression]
[match:add
ition
]
[match:add]
M1:
"2
+
x"
[ast:add
ition
]
[ast:add]
[fail:add
ition
]
[fail:add]
[match:sub
traction
]
[match:sub]
[ast:sub
traction
]
[ast:sub]
[fail:sub
traction
]
[fail:sub]
setup.py
View file @
6ef3b9fe
...
...
@@ -15,8 +15,8 @@ setup(
name
=
'DHParser'
,
version
=
__version__
,
packages
=
[
'DHParser'
],
ext_modules
=
cythonize
([
'DHParser/
toolkit
.py'
,
'DHParser/
stringview
.py'
,
ext_modules
=
cythonize
([
'DHParser/
stringview
.py'
,
'DHParser/
toolkit
.py'
,
'DHParser/preprocess.py'
,
'DHParser/error.py'
,
'DHParser/syntaxtree.py'
,
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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