diff --git a/pyparsing/core.py b/pyparsing/core.py index 7ed0af9..10f612e 100644 --- a/pyparsing/core.py +++ b/pyparsing/core.py @@ -4703,6 +4703,9 @@ class Or(ParseExpression): if self.exprs: self._may_return_empty = any(e.mayReturnEmpty for e in self.exprs) self.skipWhitespace = all(e.skipWhitespace for e in self.exprs) + # pre-skip whitespace here only if every alternative would have + # done so itself, matching the condition used in parseImpl below + self.callPreparse = all(e.callPreparse for e in self.exprs) else: self._may_return_empty = True @@ -4863,6 +4866,10 @@ class MatchFirst(ParseExpression): if self.exprs: self._may_return_empty = any(e.mayReturnEmpty for e in self.exprs) self.skipWhitespace = all(e.skipWhitespace for e in self.exprs) + # pre-skip whitespace here only if every alternative would have + # done so itself; an alternative starting with White() must not + # lose the whitespace it needs to see + self.callPreparse = all(e.callPreparse for e in self.exprs) else: self._may_return_empty = True diff --git a/tests/test_unit.py b/tests/test_unit.py index 4bd5e70..f6c3cf9 100644 --- a/tests/test_unit.py +++ b/tests/test_unit.py @@ -8910,6 +8910,29 @@ class Test02_WithoutPackrat(ppt.TestParseResultsAsserts, TestCase): "failed testing parse actions being run inside a NotAny", ) + def testParseActionLocOnOrAndMatchFirst(self): + # a parse action on Or ('^') or MatchFirst ('|') should receive the + # whitespace-skipped loc, just as And ('+') does + src = " abc" + expected_loc = src.index("abc") + word = pp.Word(pp.alphas) + + for label, expr in ( + ("Or", word ^ pp.Literal("xyz")), + ("MatchFirst", word | pp.Literal("xyz")), + ): + with self.subTest(label=label): + seen_locs = [] + expr = expr.copy().set_parse_action( + lambda s, loc, toks: seen_locs.append(loc) + ) + expr.parse_string(src) + self.assertEqual( + [expected_loc], + seen_locs, + f"{label} parse action received wrong loc (whitespace not skipped)", + ) + def testParseResultsNameBelowUngroupedName(self): rule_num = pp.Regex("[0-9]+")("LIT_NUM*") list_num = pp.Group(