Commit 76299488 authored by Eckhart Arnold's avatar Eckhart Arnold
Browse files

DHParser/parse.py: flag `complete_match` added to Gramma.__call__()

parent 24980e81
......@@ -956,6 +956,7 @@ class Grammar:
def __call__(self,
document: str,
start_parser: Union[str, Parser] = "root_parser__",
*, complete_match: bool = True,
track_history: bool = False) -> RootNode:
"""
Parses a document with with parser-combinators.
......@@ -965,6 +966,8 @@ class Grammar:
start_parser (str or Parser): The name of the parser with which
to start. This is useful for testing particular parsers
(i.e. particular parts of the EBNF-Grammar.)
complete_match (bool): If True, an error is generated, if
`start_parser` did not match the entire document.
track_history (bool): If true, the parsing history will be
recorded in self.history__. If logging is turned on (i.e.
DHParser.log.is_logging() returns true), the parsing history
......@@ -1043,7 +1046,7 @@ class Grammar:
max_parser_dropouts = self.max_parser_dropouts__
while rest and len(stitches) < max_parser_dropouts:
result, rest = parser(rest)
if rest:
if rest and complete_match:
fwd = rest.find("\n") + 1 or len(rest)
skip, rest = rest[:fwd], rest[fwd:]
if result is None:
......@@ -1096,6 +1099,8 @@ class Grammar:
# self.history__.append(record)
# stop history tracking when parser returned too early
self.history_tracking__ = False
else:
rest = '' # if complete_match is False, ignore the rest and leave while loop
if stitches:
if rest:
stitches.append(Node(ZOMBIE_TAG, rest))
......
......@@ -355,6 +355,17 @@ class TestGrammar:
CST = grammar('3+4')
assert not CST.error_flag, CST.as_sxpr()
def test_incomplete_matching(self):
"""Tests whether the flag `complete_match` works as expected when
calling a grammar object in order to parse a document."""
gr = grammar_provider('word = ~/\\w+/\n')()
st = gr('eins')
assert not st.errors
st = gr('eins zwei')
assert st.errors[0].code == Error.PARSER_STOPPED_BEFORE_END
st = gr('eins zwei', complete_match=False)
assert not st.errors
class TestSeries:
def test_non_mandatory(self):
......
......@@ -311,12 +311,12 @@ class TestLookahead:
def test_unit_lookahead(self):
gr = self.grammar_fac()
# Case 1: Lookahead string is part of the test case; parser fails but for the lookahead
result = gr(self.cases['category']['match'][1], 'category', True)
result = gr(self.cases['category']['match'][1], 'category', track_history=True)
assert any(e.code in (Error.PARSER_LOOKAHEAD_FAILURE_ONLY,
Error.PARSER_LOOKAHEAD_MATCH_ONLY)
for e in result.errors)
for e in result.errors), str(result.errors)
# Case 2: Lookahead string is not part of the test case; parser matches but for the mandatory continuation
result = gr(self.cases['category']['match'][2], 'category', True)
result = gr(self.cases['category']['match'][2], 'category', track_history=True)
assert any(e.code == Error.MANDATORY_CONTINUATION_AT_EOF for e in result.errors)
errata = grammar_unit(self.cases, self.grammar_fac, self.trans_fac,
'REPORT_TestLookahead')
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment