From f80565a285c1cc321344d3da8280c09560091491 Mon Sep 17 00:00:00 2001 From: Eric Wald Date: Sun, 10 Mar 2019 14:38:43 -0600 Subject: Support for simple_unit_tests under Python 2 (#72) --- pyparsing.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'pyparsing.py') diff --git a/pyparsing.py b/pyparsing.py index 4ba5b11..3befc7c 100644 --- a/pyparsing.py +++ b/pyparsing.py @@ -350,7 +350,11 @@ class ParseException(ParseBaseException): callers = inspect.getinnerframes(exc.__traceback__, context=depth) seen = set() for i, ff in enumerate(callers[-depth:]): - frm = ff.frame + if isinstance(ff, tuple): + # Python 2 compatibility + frm = ff[0] + else: + frm = ff.frame f_self = frm.f_locals.get('self', None) if isinstance(f_self, ParserElement): -- cgit v1.2.1 From ed2f5ec744ddc25242f947be8ba798d9fca6a674 Mon Sep 17 00:00:00 2001 From: Eric Wald Date: Sun, 10 Mar 2019 14:53:14 -0600 Subject: Descriptive names for Forward expressions (#71) Resolves the infinite recursion potential by setting a temporary name during resolution. --- pyparsing.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'pyparsing.py') diff --git a/pyparsing.py b/pyparsing.py index 3befc7c..4a79904 100644 --- a/pyparsing.py +++ b/pyparsing.py @@ -4636,18 +4636,18 @@ class Forward(ParseElementEnhance): def __str__( self ): if hasattr(self,"name"): return self.name - return self.__class__.__name__ + ": ..." - # stubbed out for now - creates awful memory and perf issues - self._revertClass = self.__class__ - self.__class__ = _ForwardNoRecurse + # Avoid infinite recursion by setting a temporary name + self.name = self.__class__.__name__ + ": ..." + + # Use the string representation of main expression. try: if self.expr is not None: retString = _ustr(self.expr) else: retString = "None" finally: - self.__class__ = self._revertClass + del self.name return self.__class__.__name__ + ": " + retString def copy(self): @@ -4658,10 +4658,6 @@ class Forward(ParseElementEnhance): ret <<= self return ret -class _ForwardNoRecurse(Forward): - def __str__( self ): - return "..." - class TokenConverter(ParseElementEnhance): """ Abstract subclass of :class:`ParseExpression`, for converting parsed results. -- cgit v1.2.1 From fed0f3da669a9a81829651080b6dfe32ce44c1b0 Mon Sep 17 00:00:00 2001 From: TMiguelT Date: Wed, 13 Mar 2019 10:41:23 +1100 Subject: Fix cases where an indentedBlock partially parsing will cause all other correct indentedBlocks to fail (#75) * Add failing test for indentedBlock * Simplify fix by storing a backup stack --- pyparsing.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'pyparsing.py') diff --git a/pyparsing.py b/pyparsing.py index 4a79904..8781ff7 100644 --- a/pyparsing.py +++ b/pyparsing.py @@ -5854,12 +5854,17 @@ def indentedBlock(blockStatementExpr, indentStack, indent=True): ':', [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] """ + backup_stack = indentStack[:] + + def reset_stack(): + indentStack[:] = backup_stack + def checkPeerIndent(s,l,t): if l >= len(s): return curCol = col(l,s) if curCol != indentStack[-1]: if curCol > indentStack[-1]: - raise ParseFatalException(s,l,"illegal nesting") + raise ParseException(s,l,"illegal nesting") raise ParseException(s,l,"not a peer entry") def checkSubIndent(s,l,t): @@ -5887,6 +5892,7 @@ def indentedBlock(blockStatementExpr, indentStack, indent=True): else: smExpr = Group( Optional(NL) + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) ) + smExpr.setFailAction(lambda a, b, c, d: reset_stack()) blockStatementExpr.ignore(_bslash + LineEnd()) return smExpr.setName('indented block') -- cgit v1.2.1