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
4f01e917
Commit
4f01e917
authored
Jan 05, 2019
by
eckhart
Browse files
- further bugfixes for recovery after error
parent
02f23fae
Changes
2
Hide whitespace changes
Inline
Side-by-side
DHParser/parse.py
View file @
4f01e917
...
...
@@ -136,7 +136,7 @@ def reentry_point(rest: StringView, rules: ResumeList) -> int:
The integer index of the closest reentry point or -1 if no reentry-point
was found.
"""
upper_limit
=
len
(
rest
)
upper_limit
=
len
(
rest
)
+
1
i
=
upper_limit
#find closest match
for
rule
in
rules
:
...
...
@@ -148,7 +148,7 @@ def reentry_point(rest: StringView, rules: ResumeList) -> int:
if
m
:
i
=
min
(
rest
.
index
(
m
.
startswith
()),
i
)
# in case no rule matched return -1
if
i
==
upper_limit
and
upper_limit
>
0
:
if
i
==
upper_limit
:
i
=
-
1
return
i
# return Node(None, rest[:i]), rest[i:]
...
...
@@ -194,12 +194,17 @@ def add_parser_guard(parser_func):
rest
=
error
.
rest
[
len
(
error
.
node
):]
i
=
reentry_point
(
rest
,
rules
)
if
i
>=
0
or
parser
==
grammar
.
root__
:
# apply reentry-rule or catch error at root-parser
if
i
<
0
:
i
=
1
nd
=
Node
(
None
,
rest
[:
i
])
rest
=
rest
[
i
:]
assert
error
.
node
.
children
node
=
Node
(
parser
,
(
Node
(
None
,
text
[:
gap
]),
error
.
node
,
nd
))
if
error
.
first_throw
:
node
=
error
.
node
node
.
result
+=
(
nd
,)
else
:
node
=
Node
(
parser
,
(
Node
(
None
,
text
[:
gap
]),
error
.
node
,
nd
))
elif
error
.
first_throw
:
raise
ParserError
(
error
.
node
,
error
.
rest
,
first_throw
=
False
)
else
:
...
...
test/test_parse.py
View file @
4f01e917
...
...
@@ -600,21 +600,23 @@ class TestBorderlineCases:
class
TestReentryAfterError
:
def
test_reentry_after_mandatory_error
(
self
):
def
setup
(
self
):
lang
=
"""
document = alpha [beta] gamma "."
alpha = "ALPHA" abc
abc = §"a" "b" "c"
beta = "BETA" (bac | bca)
bac = "b" "a" §
"c"
bca = "b" "c" §
"a"
bac = "b" "a" §"c"
bca = "b" "c" §"a"
gamma = "GAMMA" §(cab | cba)
cab = "c" "a" §"b"
cba = "c" "b" §"a"
"""
gr
=
grammar_provider
(
lang
)()
self
.
gr
=
grammar_provider
(
lang
)()
def
test_no_resume_rules
(
self
):
# 1. no resume rules
gr
=
self
.
gr
;
gr
.
resume_rules
=
dict
()
content
=
'ALPHA acb BETA bac GAMMA cab .'
cst
=
gr
(
content
)
# print(cst.as_sxpr())
...
...
@@ -622,8 +624,10 @@ class TestReentryAfterError:
assert
cst
.
content
==
content
assert
cst
.
pick
(
'alpha'
).
content
.
startswith
(
'ALPHA'
)
# 2. simple resume rule
def
test_simple_resume_rule
(
self
):
gr
=
self
.
gr
;
gr
.
resume_rules
=
dict
()
gr
.
resume_rules__
[
'alpha'
]
=
[
'BETA'
]
content
=
'ALPHA acb BETA bac GAMMA cab .'
cst
=
gr
(
content
)
# print(cst.as_sxpr())
assert
cst
.
error_flag
...
...
@@ -632,8 +636,10 @@ class TestReentryAfterError:
# because of resuming, there should be only on error message
assert
len
(
cst
.
collect_errors
())
==
1
# 3. failing resume rule
def
test_failing_resume_rule
(
self
):
gr
=
self
.
gr
;
gr
.
resume_rules
=
dict
()
gr
.
resume_rules__
[
'alpha'
]
=
[
'XXX'
]
content
=
'ALPHA acb BETA bac GAMMA cab .'
cst
=
gr
(
content
)
# print(cst.as_sxpr())
assert
cst
.
error_flag
...
...
@@ -641,8 +647,10 @@ class TestReentryAfterError:
# assert cst.pick('alpha').content.startswith('ALPHA')
# because of resuming, there should be only on error message
# 4. several resume rules
def
test_severl_reentry_points
(
self
):
gr
=
self
.
gr
;
gr
.
resume_rules
=
dict
()
gr
.
resume_rules__
[
'alpha'
]
=
[
'BETA'
,
'GAMMA'
]
content
=
'ALPHA acb BETA bac GAMMA cab .'
cst
=
gr
(
content
)
# print(cst.as_sxpr())
assert
cst
.
error_flag
...
...
@@ -651,17 +659,41 @@ class TestReentryAfterError:
# because of resuming, there should be only on error message
assert
len
(
cst
.
collect_errors
())
==
1
# 4. several resume rules, second rule matching
def
test_several_reentry_points_second_point_matching
(
self
):
gr
=
self
.
gr
;
gr
.
resume_rules
=
dict
()
gr
.
resume_rules__
[
'alpha'
]
=
[
'BETA'
,
'GAMMA'
]
content
=
'ALPHA acb GAMMA cab .'
cst
=
gr
(
content
)
print
(
cst
.
as_sxpr
())
#
print(cst.as_sxpr())
assert
cst
.
error_flag
assert
cst
.
content
==
content
assert
cst
.
pick
(
'alpha'
).
content
.
startswith
(
'ALPHA'
)
# because of resuming, there should be only on error message
assert
len
(
cst
.
collect_errors
())
==
1
def
test_several_resume_rules_innermost_rule_matching
(
self
):
gr
=
self
.
gr
;
gr
.
resume_rules
=
dict
()
gr
.
resume_rules__
[
'alpha'
]
=
[
'BETA'
,
'GAMMA'
]
gr
.
resume_rules__
[
'beta'
]
=
[
'GAMMA'
]
gr
.
resume_rules__
[
'bac'
]
=
[
'GAMMA'
]
content
=
'ALPHA abc BETA bad GAMMA cab .'
cst
=
gr
(
content
)
# print(cst.as_sxpr())
assert
cst
.
error_flag
assert
cst
.
content
==
content
assert
cst
.
pick
(
'alpha'
).
content
.
startswith
(
'ALPHA'
)
# because of resuming, there should be only on error message
assert
len
(
cst
.
collect_errors
())
==
1
# multiple failures
content
=
'ALPHA acb BETA bad GAMMA cab .'
cst
=
gr
(
content
)
# print(cst.as_sxpr())
assert
cst
.
error_flag
assert
cst
.
content
==
content
assert
cst
.
pick
(
'alpha'
).
content
.
startswith
(
'ALPHA'
)
# because of resuming, there should be only on error message
assert
len
(
cst
.
collect_errors
())
==
2
class
TestUnknownParserError
:
def
test_unknown_parser_error
(
self
):
...
...
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