Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
badw-it
DHParser
Commits
b5d96c3d
Commit
b5d96c3d
authored
Feb 28, 2020
by
eckhart
Browse files
test_parse.py: Tests for Interleave-Parser
parent
d132b4ba
Changes
2
Hide whitespace changes
Inline
Side-by-side
DHParser/parse.py
View file @
b5d96c3d
...
...
@@ -78,6 +78,7 @@ __all__ = ('ParserError',
'AllOf'
,
'SomeOf'
,
'Unordered'
,
'Interleave'
,
'Required'
,
'Lookahead'
,
'NegativeLookahead'
,
...
...
@@ -318,7 +319,7 @@ class Parser:
self
.
reset
()
def
__deepcopy__
(
self
,
memo
):
"""
Deepcopy method of the parser. Upon instantiation of a Grammar-
"""Deepcopy method of the parser. Upon instantiation of a Grammar-
object, parsers will be deep-copied to the Grammar object. If a
derived parser-class changes the signature of the `__init__`-constructor,
`__deepcopy__`-method must be replaced (i.e. overridden without
...
...
@@ -2187,6 +2188,8 @@ class AllOf(MandatoryNary):
mandatory
:
int
=
NO_MANDATORY
,
err_msgs
:
MessagesType
=
[],
skip
:
ResumeList
=
[])
->
None
:
assert
(
not
isinstance
(
parser
,
Option
)
and
not
isinstance
(
parser
,
OneOrMore
)
and
not
isinstance
(
parser
,
FlowParser
)
for
parser
in
parsers
)
assert
len
(
parsers
)
>
1
,
"AllOf requires at least two sub-parsers."
super
(
AllOf
,
self
).
__init__
(
*
parsers
,
mandatory
=
mandatory
,
err_msgs
=
err_msgs
,
skip
=
skip
)
self
.
num_parsers
=
len
(
self
.
parsers
)
# type: int
...
...
@@ -2261,6 +2264,8 @@ class SomeOf(NaryParser):
def
__init__
(
self
,
*
parsers
:
Parser
)
->
None
:
assert
len
(
parsers
)
>
1
,
"SomeOf requires at least two sub-parsers."
assert
(
not
isinstance
(
parser
,
Option
)
and
not
isinstance
(
parser
,
OneOrMore
)
and
not
isinstance
(
parser
,
FlowParser
)
for
parser
in
parsers
)
super
(
SomeOf
,
self
).
__init__
(
*
parsers
)
def
_parse
(
self
,
text
:
StringView
)
->
Tuple
[
Optional
[
Node
],
StringView
]:
...
...
@@ -2302,18 +2307,32 @@ def Unordered(parser: NaryParser) -> NaryParser:
raise
AssertionError
(
"Unordered can take only Series or Alternative as parser."
)
class
Interleave
(
NaryParser
):
class
Interleave
(
MandatoryNary
):
"""EXPERIMENTAL!!! NOT YET TESTED at all!!!"""
def
__init__
(
self
,
*
parsers
:
Parser
,
mandatory
:
int
=
NO_MANDATORY
,
err_msgs
:
MessagesType
=
[],
skip
:
ResumeList
=
[],
repetitions
:
Sequence
[
Tuple
[
int
,
int
]])
->
None
:
assert
len
(
parsers
)
==
len
(
repetitions
),
\
"Number of repition tuples does not match the number of sub-parsers!"
repetitions
:
Sequence
[
Tuple
[
int
,
int
]]
=
())
->
None
:
assert
(
not
isinstance
(
parser
,
Option
)
and
not
isinstance
(
parser
,
OneOrMore
)
and
not
isinstance
(
parser
,
FlowParser
)
for
parser
in
parsers
)
super
(
Interleave
,
self
).
__init__
(
*
parsers
,
mandatory
=
mandatory
,
err_msgs
=
err_msgs
,
skip
=
skip
)
if
len
(
repetitions
)
==
0
:
repetitions
=
[(
1
,
1
)]
*
len
(
parsers
)
elif
len
(
parsers
)
!=
len
(
repetitions
):
raise
ValueError
(
"Number of repetition-tuples unequal number of sub-parsers!"
)
self
.
repetitions
=
repetitions
self
.
non_mandatory
=
frozenset
(
parsers
[
i
]
for
i
in
range
(
min
(
mandatory
,
len
(
parsers
))))
def
__deepcopy__
(
self
,
memo
):
parsers
=
copy
.
deepcopy
(
self
.
parsers
,
memo
)
duplicate
=
self
.
__class__
(
*
parsers
,
mandatory
=
self
.
mandatory
,
err_msgs
=
self
.
err_msgs
,
skip
=
self
.
skip
,
repetitions
=
self
.
repetitions
)
duplicate
.
pname
=
self
.
pname
copy_parser_attrs
(
self
,
duplicate
)
return
duplicate
def
_parse
(
self
,
text
:
StringView
)
:
results
=
()
# type: Tuple[Node, ...]
...
...
@@ -2324,18 +2343,20 @@ class Interleave(NaryParser):
error
=
None
# type: Optional[Error]
while
parsers
:
for
i
,
parser
in
enumerate
(
parsers
):
node
,
text__
=
parser
(
text_
)
if
node
is
not
None
:
if
node
.
_result
or
not
node
.
tag_name
.
startswith
(
':'
):
# drop anonymous empty nodes
results
+=
(
node
,)
text_
=
text__
counter
[
i
]
+=
1
if
counter
[
i
]
>=
self
.
repetitions
[
i
][
1
]:
consumed
.
add
(
parser
)
del
parsers
[
i
]
break
if
parser
not
in
consumed
:
node
,
text__
=
parser
(
text_
)
if
node
is
not
None
:
if
node
.
_result
or
not
node
.
tag_name
.
startswith
(
':'
):
# drop anonymous empty nodes
results
+=
(
node
,)
text_
=
text__
counter
[
i
]
+=
1
if
counter
[
i
]
>=
self
.
repetitions
[
i
][
1
]:
consumed
.
add
(
parser
)
# del parsers[i] # Bringt die Zählung durcheinander
break
else
:
# TODO: Füge parser zu consumed, bei denen die Minimum-Anzahl überschritten
if
not
self
.
non_mandatory
<=
consumed
:
return
None
,
text
reloc
=
self
.
get_reentry_point
(
text_
)
...
...
@@ -2355,7 +2376,7 @@ class Interleave(NaryParser):
return
nd
,
text_
def
__repr__
(
self
):
return
'
°
'
.
join
(
parser
.
repr
for
parser
in
self
.
parsers
)
return
'
°
'
.
join
(
parser
.
repr
for
parser
in
self
.
parsers
)
########################################################################
...
...
test/test_parse.py
View file @
b5d96c3d
...
...
@@ -32,7 +32,7 @@ from DHParser.log import is_logging, log_ST, log_parsing_history
from
DHParser.error
import
Error
,
is_error
from
DHParser.parse
import
ParserError
,
Parser
,
Grammar
,
Forward
,
TKN
,
ZeroOrMore
,
RE
,
\
RegExp
,
Lookbehind
,
NegativeLookahead
,
OneOrMore
,
Series
,
Alternative
,
AllOf
,
SomeOf
,
\
UnknownParserError
,
MetaParser
,
EMPTY_NODE
Interleave
,
UnknownParserError
,
MetaParser
,
Token
,
EMPTY_NODE
from
DHParser
import
compile_source
from
DHParser.ebnf
import
get_ebnf_grammar
,
get_ebnf_transformer
,
get_ebnf_compiler
,
DHPARSER_IMPORTS
from
DHParser.dsl
import
grammar_provider
...
...
@@ -521,6 +521,30 @@ class TestAllOfSomeOf:
assert
Grammar
(
prefixes
)(
'A B B'
).
error_flag
class
TestInterleave
:
def
test_interleave_most_simple
(
self
):
letterset
=
Interleave
(
Token
(
"A"
),
Token
(
"B"
),
Token
(
"C"
))
gr
=
Grammar
(
letterset
)
st
=
gr
(
'ABC'
)
assert
not
st
.
errors
assert
st
.
content
==
"ABC"
st
=
gr
(
'BCA'
)
assert
not
st
.
errors
assert
st
.
content
==
"BCA"
st
=
gr
(
'BCBA'
)
assert
st
.
errors
st
=
gr
(
'AB'
)
assert
st
.
errors
def
test_interleave
(
self
):
letterset
=
Interleave
(
Token
(
"A"
),
Token
(
"B"
),
Token
(
"C"
),
repetitions
=
[(
1
,
1000
),
(
0
,
1
),
(
1
,
1
)])
gr
=
Grammar
(
letterset
)
st
=
gr
(
'AABC'
)
print
(
st
.
errors
,
st
.
as_sxpr
())
assert
not
st
.
errors
class
TestErrorRecovery
:
def
test_series_skip
(
self
):
lang
=
"""
...
...
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