diff options
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | pyparsing.py | 12 | ||||
-rw-r--r-- | unitTests.py | 19 |
3 files changed, 27 insertions, 7 deletions
@@ -93,6 +93,9 @@ Version 3.0.0a1 resulting in as much as 50X improvement in performance! Work inspired by a question posted by Midnighter on StackOverflow. +- Fixed bug in PrecededBy which caused infinite recursion, issue #127 + submitted by EdwardJB. + - Fixed bug in CloseMatch where end location was incorrectly computed; and updated partial_gene_match.py example. diff --git a/pyparsing.py b/pyparsing.py index 91a313c..6c3c7ec 100644 --- a/pyparsing.py +++ b/pyparsing.py @@ -96,7 +96,7 @@ classes inherit from. Use the docstrings for examples of how to: """ __version__ = "3.0.0a1" -__versionTime__ = "27 Sep 2019 10:27 UTC" +__versionTime__ = "13 Oct 2019 05:28 UTC" __author__ = "Paul McGuire <ptmcg@users.sourceforge.net>" import string @@ -4426,6 +4426,7 @@ class PrecededBy(ParseElementEnhance): self.retreat = retreat self.errmsg = "not preceded by " + str(expr) self.skipWhitespace = False + self.parseAction.append(lambda s, l, t: t.__delitem__(slice(None, None))) def parseImpl(self, instring, loc=0, doActions=True): if self.exact: @@ -4436,19 +4437,18 @@ class PrecededBy(ParseElementEnhance): else: # retreat specified a maximum lookbehind window, iterate test_expr = self.expr + StringEnd() - instring_slice = instring[:loc] + instring_slice = instring[max(0, loc - self.retreat):loc] last_expr = ParseException(instring, loc, self.errmsg) - for offset in range(1, min(loc, self.retreat + 1)): + for offset in range(1, min(loc, self.retreat + 1)+1): try: - _, ret = test_expr._parse(instring_slice, loc - offset) + # print('trying', offset, instring_slice, repr(instring_slice[loc - offset:])) + _, ret = test_expr._parse(instring_slice, len(instring_slice) - offset) except ParseBaseException as pbe: last_expr = pbe else: break else: raise last_expr - # return empty list of tokens, but preserve any defined results names - del ret[:] return loc, ret diff --git a/unitTests.py b/unitTests.py index 3bddbf4..7f516b1 100644 --- a/unitTests.py +++ b/unitTests.py @@ -2069,11 +2069,28 @@ class PrecededByTest(ParseTestCase): (finicky_num, [2939], {}), (very_boring_num, [404], {}), ]: - print(expr.searchString(s)) + # print(expr.searchString(s)) result = sum(expr.searchString(s)) print(result.dump()) self.assertParseResultsEquals(result, expected_list, expected_dict) + # infinite loop test - from Issue #127 + string_test = 'notworking' + # negs = pp.Or(['not', 'un'])('negs') + negs_pb = pp.PrecededBy('not', retreat=100)('negs_lb') + # negs_pb = pp.PrecededBy(negs, retreat=100)('negs_lb') + pattern = (negs_pb + pp.Literal('working'))('main') + + results = pattern.searchString(string_test) + try: + print(results.dump()) + except RecursionError: + self.assertTrue(False, "got maximum excursion limit exception") + else: + self.assertTrue(True, "got maximum excursion limit exception") + + + class CountedArrayTest(ParseTestCase): def runTest(self): from pyparsing import Word, nums, OneOrMore, countedArray |