Skip to content

Commit

Permalink
Fixed bug in NotAny where expr parse action was not being run - see I…
Browse files Browse the repository at this point in the history
…ssue #482
  • Loading branch information
ptmcg committed May 19, 2023
1 parent 4afd5b5 commit f6ba79d
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 9 deletions.
5 changes: 5 additions & 0 deletions CHANGES
Expand Up @@ -19,6 +19,11 @@ Version 3.1.0b2 - (in development)
version 3.0. Fixes Issue #477 (railroad diagrams generated with black bars),
reported by Sam Morley-Short.

- Fixed bug in `NotAny`, where parse actions on the negated expr were not being run.
This could cause `NotAny` to incorrectly fail if the expr would normally match,
but would fail to match if a condition used as a parse action returned False.
Fixes Issue #482, raised by byaka, thank you!

- Fixed `create_diagram()` to accept keyword args, to be passed through to the
`template.render()` method to generate the output HTML (PR submitted by Aussie Schnore,
good catch!)
Expand Down
25 changes: 16 additions & 9 deletions pyparsing/core.py
Expand Up @@ -903,17 +903,24 @@ def _parseNoCache(

return loc, ret_tokens

def try_parse(self, instring: str, loc: int, raise_fatal: bool = False) -> int:
def try_parse(
self,
instring: str,
loc: int,
*,
raise_fatal: bool = False,
do_actions: bool = False,
) -> int:
try:
return self._parse(instring, loc, doActions=False)[0]
return self._parse(instring, loc, doActions=do_actions)[0]
except ParseFatalException:
if raise_fatal:
raise
raise ParseException(instring, loc, self.errmsg, self)

def can_parse_next(self, instring: str, loc: int) -> bool:
def can_parse_next(self, instring: str, loc: int, do_actions: bool = False) -> bool:
try:
self.try_parse(instring, loc)
self.try_parse(instring, loc, do_actions=do_actions)
except (ParseException, IndexError):
return False
else:
Expand Down Expand Up @@ -4649,7 +4656,7 @@ def parseImpl(self, instring, loc, doActions=True):

# see if self.expr matches at the current location - if not it will raise an exception
# and no further work is necessary
self.expr.try_parse(instring, anchor_loc, doActions)
self.expr.try_parse(instring, anchor_loc, do_actions=doActions)

indent_col = col(anchor_loc, instring)
peer_detect_expr = self._Indent(indent_col)
Expand Down Expand Up @@ -4927,7 +4934,7 @@ def __init__(self, expr: Union[ParserElement, str]):
self.errmsg = "Found unwanted token, " + str(self.expr)

def parseImpl(self, instring, loc, doActions=True):
if self.expr.can_parse_next(instring, loc):
if self.expr.can_parse_next(instring, loc, do_actions=doActions):
raise ParseException(instring, loc, self.errmsg, self)
return loc, []

Expand Down Expand Up @@ -6060,9 +6067,9 @@ def autoname_elements() -> None:
(Regex(r'"""(?:[^"\\]|""(?!")|"(?!"")|\\.)*', flags=re.MULTILINE) + '"""').set_name(
"multiline double quoted string"
)
^ (Regex(r"'''(?:[^'\\]|''(?!')|'(?!'')|\\.)*", flags=re.MULTILINE) + "'''").set_name(
"multiline single quoted string"
)
^ (
Regex(r"'''(?:[^'\\]|''(?!')|'(?!'')|\\.)*", flags=re.MULTILINE) + "'''"
).set_name("multiline single quoted string")
^ (Regex(r'"(?:[^"\n\r\\]|(?:\\")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*') + '"').set_name(
"double quoted string"
)
Expand Down
22 changes: 22 additions & 0 deletions tests/test_unit.py
Expand Up @@ -7455,6 +7455,28 @@ def _(t):

self.assertParseAndCheckList(named_number_list, test_string, expected)

def testParseActionRunsInNotAny(self):
# see Issue #482
data = """ [gog1] [G1] [gog2] [gog3] [gog4] [G2] [gog5] [G3] [gog6] """

poi_type = pp.Word(pp.alphas).set_results_name("type")
poi = pp.Suppress("[") + poi_type + pp.Char(pp.nums) + pp.Suppress("]")

def cnd_is_type(val):
return lambda toks: toks.type == val

poi_gog = poi("gog").add_condition(cnd_is_type("gog"))
poi_g = poi("g").add_condition(cnd_is_type("G"))

pattern = poi_gog + ~poi_g

matches = pattern.search_string(data).as_list()
self.assertEqual(
[["gog", "2"], ["gog", "3"], ["gog", "6"]],
matches,
"failed testing parse actions being run inside a NotAny",
)

def testParseResultsNameBelowUngroupedName(self):
rule_num = pp.Regex("[0-9]+")("LIT_NUM*")
list_num = pp.Group(
Expand Down

0 comments on commit f6ba79d

Please sign in to comment.