Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
The container registry cleanup task is now completed and the registry can be used normally.
Open sidebar
badw-it
DHParser
Commits
543f48a3
Commit
543f48a3
authored
May 17, 2020
by
eckhart
Browse files
left recursion 1st try
parent
f939c268
Changes
4
Hide whitespace changes
Inline
Side-by-side
.vscode/settings.json
View file @
543f48a3
{
"python.pythonPath"
:
"/bin/python"
,
"python.pythonPath"
:
"/
Applications/Xcode.app/Contents/Developer/usr/
bin/python
3
"
,
"python.linting.pylintEnabled"
:
true
,
"python.linting.enabled"
:
true
,
"python.testing.nosetestArgs"
:
[
...
...
DHParser/configuration.py
View file @
543f48a3
...
...
@@ -204,7 +204,7 @@ CONFIG_PRESET['flatten_tree'] = True
# because of python's recursion depth limit
# Left recursion handling can be turned off by setting this value to zero
# Default value: 5
CONFIG_PRESET
[
'left_recursion_depth'
]
=
5
CONFIG_PRESET
[
'left_recursion_depth'
]
=
0
# Maximum allowed number of retries after errors where the parser
# would exit before the complete document has been parsed. Should
...
...
DHParser/parse.py
View file @
543f48a3
...
...
@@ -583,10 +583,10 @@ class Parser:
@
property
def
grammar
(
self
)
->
'Grammar'
:
try
:
if
self
.
_grammar
!=
GRAMMAR_PLACEHOLDER
:
if
self
.
_grammar
is
not
GRAMMAR_PLACEHOLDER
:
return
self
.
_grammar
else
:
raise
Assertion
Error
(
'Grammar has not yet been set!'
)
raise
Value
Error
(
'Grammar has not yet been set!'
)
except
(
AttributeError
,
NameError
):
raise
AttributeError
(
'Parser placeholder does not have a grammar!'
)
...
...
@@ -3163,8 +3163,12 @@ class Forward(UnaryParser):
def
__init__
(
self
):
super
(
Forward
,
self
).
__init__
(
PARSER_PLACEHOLDER
)
# self.parser = PARSER_PLACEHOLDER # type: Parser
self
.
cycle_reached
=
False
# self.recursion = dict() # type: Dict[int, Tuple[int, int]]
self
.
cycle_reached
=
False
# type: bool
self
.
memoization
=
True
# type: bool
def
reset
(
self
):
super
(
Forward
,
self
).
reset
()
self
.
recursion
=
dict
()
# type: Dict[int, Tuple[int, int]]
def
__deepcopy__
(
self
,
memo
):
duplicate
=
self
.
__class__
()
...
...
@@ -3185,25 +3189,46 @@ class Forward(UnaryParser):
`Synonym`, which might be a meaningful marker for the syntax tree,
parser Forward should never appear in the syntax tree.
"""
return
self
.
parser
(
text
)
# location = self.grammar.document_length__ - text._len
# if location in self.recursion:
# depth, oracle = self.recursion[location]
# if depth >= oracle:
# self.recursion[location] = (0, oracle + 1)
# return None, text
# else:
# self.recursion[location] = (depth + 1, oracle)
# return self.parser(text)
# else:
# self.recursion[location] = (0, 0)
# best = None, text
# while True:
# node, text_ = self.parser(text)
# oracle = self.recursion[location][1]
# if node is None or oracle == 0:
# break
# best = node, text_
# if not isinstance(self.parser, Alternative):
# return self.parser(text)
# TODO: For indirect recursion, recursion counters should not only
# depend on location, but on location and call stack depth
location
=
self
.
grammar
.
document_length__
-
text
.
_len
depth
,
oracle
=
self
.
recursion
.
get
(
location
,
(
-
1
,
-
1
))
if
oracle
>=
0
:
if
depth
>=
oracle
:
self
.
recursion
[
location
]
=
(
0
,
oracle
+
1
)
node
,
_text
=
None
,
text
else
:
self
.
recursion
[
location
]
=
(
depth
+
1
,
oracle
)
node
,
_text
=
self
.
parser
(
text
)
oracle
=
self
.
recursion
[
location
][
1
]
self
.
recursion
[
location
]
=
(
depth
,
oracle
)
self
.
memoization
=
self
.
grammar
.
memoization__
self
.
grammar
.
memoization__
=
False
return
node
,
_text
else
:
self
.
recursion
[
location
]
=
(
0
,
0
)
longest
=
None
,
text
length
=
0
while
True
:
node
,
text_
=
self
.
parser
(
text
)
depth
,
oracle
=
self
.
recursion
[
location
]
if
oracle
==
0
:
longest
=
node
,
text_
break
elif
node
is
None
:
break
else
:
l
=
len
(
node
)
if
l
<=
length
:
break
length
=
l
longest
=
node
,
text_
self
.
recursion
[
location
]
=
(
-
1
,
-
1
)
self
.
grammar
.
memoization__
=
self
.
memoization
return
longest
def
set_proxy
(
self
,
proxy
:
Optional
[
ParseFunc
]):
"""`set_proxy` has no effects on Forward-objects!"""
...
...
tests/test_parse.py
View file @
543f48a3
...
...
@@ -111,6 +111,16 @@ class TestParserClass:
class
TestInfiLoopsAndRecursion
:
def
test_very_simple
(
self
):
minilang
=
"""
term = term (`*`|`/`) factor | factor
factor = /[0-9]+/
"""
parser
=
grammar_provider
(
minilang
)()
snippet
=
"5*4*3"
st
=
parser
(
snippet
)
assert
not
is_error
(
st
.
error_flag
)
def
test_direct_left_recursion1
(
self
):
minilang
=
"""@literalws = right
expr = expr ("+"|"-") term | term
...
...
@@ -149,6 +159,7 @@ class TestInfiLoopsAndRecursion:
Sum = Expr { ('+' | '-') Expr }+
Value = /[0-9.]+/~ | '(' §Expr ')'
"""
# print(raw_compileEBNF(minilang).result)
parser
=
grammar_provider
(
minilang
)()
snippet
=
"8 * 4"
syntax_tree
=
parser
(
snippet
)
...
...
@@ -395,7 +406,7 @@ class TestGrammar:
"""
pyparser
,
messages
,
_
=
compile_source
(
grammar
,
None
,
get_ebnf_grammar
(),
get_ebnf_transformer
(),
get_ebnf_compiler
(
"PosTest"
))
assert
pyparser
assert
pyparser
,
str
(
messages
)
assert
not
messages
,
str
(
messages
)
def
test_pos_values_initialized
(
self
):
...
...
Write
Preview
Supports
Markdown
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