diff options
author | Paul McGuire <ptmcg@austin.rr.com> | 2019-08-09 06:46:56 -0500 |
---|---|---|
committer | Paul McGuire <ptmcg@austin.rr.com> | 2019-08-09 06:46:56 -0500 |
commit | 7c1db54c6b4de188d7bebcc7372b926a13fd3da4 (patch) | |
tree | e224eaeef31b55a4bcf6a672733ec13dc95d7836 | |
parent | c02db7427de3197d607e30ba42031884802a6f94 (diff) | |
download | pyparsing-git-7c1db54c6b4de188d7bebcc7372b926a13fd3da4.tar.gz |
Fixed bug in indentedBlock with a parser using two different types of nested indented blocks with different indent values, but sharing the same indent stack. Raised in comments on #87.
-rw-r--r-- | pyparsing.py | 13 | ||||
-rw-r--r-- | unitTests.py | 39 |
2 files changed, 45 insertions, 7 deletions
diff --git a/pyparsing.py b/pyparsing.py index 23b36dc..aa49a06 100644 --- a/pyparsing.py +++ b/pyparsing.py @@ -96,7 +96,7 @@ classes inherit from. Use the docstrings for examples of how to: """ __version__ = "2.5.0a1" -__versionTime__ = "06 Aug 2019 04:55 UTC" +__versionTime__ = "09 Aug 2019 11:27 UTC" __author__ = "Paul McGuire <ptmcg@users.sourceforge.net>" import string @@ -6015,7 +6015,7 @@ def nestedExpr(opener="(", closer=")", content=None, ignoreExpr=quotedString.cop ret.setName('nested %s%s expression' % (opener, closer)) return ret -def indentedBlock(blockStatementExpr, indentStack, indent=True): +def indentedBlock(blockStatementExpr, indentStack, indent=True, backup_stacks=[]): """Helper method for defining space-delimited indentation blocks, such as those used to define block statements in Python source code. @@ -6096,10 +6096,10 @@ def indentedBlock(blockStatementExpr, indentStack, indent=True): ':', [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] """ - backup_stack = indentStack[:] + backup_stacks.append(indentStack[:]) def reset_stack(): - indentStack[:] = backup_stack + indentStack[:] = backup_stacks[-1] def checkPeerIndent(s, l, t): if l >= len(s): return @@ -6136,7 +6136,10 @@ def indentedBlock(blockStatementExpr, indentStack, indent=True): else: smExpr = Group(Optional(NL) + OneOrMore(PEER + Group(blockStatementExpr) + Optional(NL)) - + UNDENT) + + Optional(UNDENT)) + + # add a parse action to remove backup_stack from list of backups + smExpr.addParseAction(lambda: backup_stacks.pop(-1) and None if backup_stacks else None) smExpr.setFailAction(lambda a, b, c, d: reset_stack()) blockStatementExpr.ignore(_bslash + LineEnd()) return smExpr.setName('indented block') diff --git a/unitTests.py b/unitTests.py index 9fe246e..8601be1 100644 --- a/unitTests.py +++ b/unitTests.py @@ -4217,12 +4217,12 @@ class IndentedBlockTest2(ParseTestCase): key.setParseAction(key_parse_action) header = Suppress("[") + Literal("test") + Suppress("]") - content = (header + OneOrMore(indentedBlock(body, indent_stack, False))) + content = (header - OneOrMore(indentedBlock(body, indent_stack, False))) contents = Forward() suites = indentedBlock(content, indent_stack) - extra = Literal("extra") + Suppress(":") + suites + extra = Literal("extra") + Suppress(":") - suites contents << (content | extra) parser = OneOrMore(contents) @@ -4245,6 +4245,41 @@ class IndentedBlockTest2(ParseTestCase): success, _ = parser.runTests([sample]) self.assertTrue(success, "Failed indentedBlock test for issue #87") + sample2 = dedent(""" + extra: + [test] + one: + two (three) + four: + five (seven) + extra: + [test] + one: + two (three) + four: + five (seven) + + [test] + one: + two (three) + four: + five (seven) + + [test] + eight: + nine (ten) + eleven: + twelve (thirteen) + + fourteen: + fifteen (sixteen) + seventeen: + eighteen (nineteen) + """) + + del indent_stack[1:] + success, _ = parser.runTests([sample2]) + self.assertTrue(success, "Failed indentedBlock multi-block test for issue #87") class IndentedBlockScanTest(ParseTestCase): def get_parser(self): |