From 03d5fb1244268fff521df5c2e7d89c6d1361d5a7 Mon Sep 17 00:00:00 2001 From: Renata Hodovan Date: Thu, 11 Aug 2016 00:49:45 +0200 Subject: [PATCH] Make Python targets more pythonic. The Python implementations are completely synchronous with the Java version even if some of the constructs can be expressed with simpler Python solutions. These are typically the all, any, count, next builtins or the list comprehensions, etc. Beside using them makes the code clearer, they are also prefered by the standard and can result in performance speedup. The patch contains such equivalent transformations in the Python targets. --- runtime/Python2/src/antlr4/IntervalSet.py | 12 ++--- runtime/Python2/src/antlr4/ListTokenSource.py | 4 +- .../Python2/src/antlr4/PredictionContext.py | 5 +- .../Python2/src/antlr4/atn/ATNConfigSet.py | 23 +++------ runtime/Python2/src/antlr4/atn/ATNState.py | 5 +- .../src/antlr4/atn/LexerATNSimulator.py | 6 +-- .../Python2/src/antlr4/atn/PredictionMode.py | 47 +++++------------- .../Python2/src/antlr4/atn/SemanticContext.py | 37 ++++---------- runtime/Python2/src/antlr4/dfa/DFAState.py | 9 +--- runtime/Python2/src/antlr4/tree/Trees.py | 3 +- runtime/Python2/src/antlr4/xpath/XPath.py | 17 ++----- runtime/Python3/src/antlr4/IntervalSet.py | 12 ++--- runtime/Python3/src/antlr4/ListTokenSource.py | 4 +- .../Python3/src/antlr4/PredictionContext.py | 5 +- .../Python3/src/antlr4/atn/ATNConfigSet.py | 23 +++------ runtime/Python3/src/antlr4/atn/ATNState.py | 5 +- .../src/antlr4/atn/LexerATNSimulator.py | 6 +-- .../Python3/src/antlr4/atn/PredictionMode.py | 48 +++++-------------- .../Python3/src/antlr4/atn/SemanticContext.py | 38 +++++---------- runtime/Python3/src/antlr4/dfa/DFAState.py | 9 +--- runtime/Python3/src/antlr4/tree/Trees.py | 3 +- runtime/Python3/src/antlr4/xpath/XPath.py | 16 ++----- 22 files changed, 88 insertions(+), 249 deletions(-) diff --git a/runtime/Python2/src/antlr4/IntervalSet.py b/runtime/Python2/src/antlr4/IntervalSet.py index e28a556d4..3a55a2631 100644 --- a/runtime/Python2/src/antlr4/IntervalSet.py +++ b/runtime/Python2/src/antlr4/IntervalSet.py @@ -97,16 +97,10 @@ class IntervalSet(object): if self.intervals is None: return False else: - for i in self.intervals: - if item in i: - return True - return False + return any(item in i for i in self.intervals) def __len__(self): - xlen = 0 - for i in self.intervals: - xlen += len(i) - return xlen + return sum(len(i) for i in self.intervals) def removeRange(self, v): if v.start==v.stop-1: @@ -126,7 +120,7 @@ class IntervalSet(object): # check for included range, remove it elif v.start<=i.start and v.stop>=i.stop: self.intervals.pop(k) - k = k - 1 # need another pass + k -= 1 # need another pass # check for lower boundary elif v.start1: - return True - return False + return any(len(alts) > 1 for alts in altsets) # # Determines if every alternative subset in {@code altsets} is equivalent. @@ -448,13 +436,9 @@ class PredictionMode(object): # @classmethod def allSubsetsEqual(cls, altsets): - first = None - for alts in altsets: - if first is None: - first = alts - elif not alts==first: - return False - return True + if not altsets: + return True + return all(alts == altsets[0] for alts in altsets[1:]) # # Returns the unique alternative predicted by all alternative subsets in @@ -467,10 +451,8 @@ class PredictionMode(object): def getUniqueAlt(cls, altsets): all = cls.getAlts(altsets) if len(all)==1: - for one in all: - return one - else: - return ATN.INVALID_ALT_NUMBER + return all.pop() + return ATN.INVALID_ALT_NUMBER # Gets the complete set of represented alternatives for a collection of # alternative subsets. This method returns the union of each {@link BitSet} @@ -481,10 +463,7 @@ class PredictionMode(object): # @classmethod def getAlts(cls, altsets): - all = set() - for alts in altsets: - all = all | alts - return all + return set.union(*altsets) # # This function gets the conflicting alt subsets from a configuration set. @@ -528,11 +507,7 @@ class PredictionMode(object): @classmethod def hasStateAssociatedWithOneAlt(cls, configs): - x = cls.getStateToAltMap(configs) - for alts in x.values(): - if len(alts)==1: - return True - return False + return any(len(alts) == 1 for alts in cls.getStateToAltMap(configs).values()) @classmethod def getSingleViableAlt(cls, altsets): diff --git a/runtime/Python2/src/antlr4/atn/SemanticContext.py b/runtime/Python2/src/antlr4/atn/SemanticContext.py index 021d4770c..b8fe7b1a0 100644 --- a/runtime/Python2/src/antlr4/atn/SemanticContext.py +++ b/runtime/Python2/src/antlr4/atn/SemanticContext.py @@ -115,14 +115,7 @@ def orContext(a, b): return result def filterPrecedencePredicates(collection): - result = [] - for context in collection: - if isinstance(context, PrecedencePredicate): - if result is None: - result = [] - result.append(context) - return result - + return [context for context in collection if isinstance(context, PrecedencePredicate)] class Predicate(SemanticContext): @@ -187,13 +180,11 @@ class AND(SemanticContext): def __init__(self, a, b): operands = set() if isinstance( a, AND): - for o in a.opnds: - operands.add(o) + operands.update(a.opnds) else: operands.add(a) if isinstance( b, AND): - for o in b.opnds: - operands.add(o) + operands.update(b.opnds) else: operands.add(b) @@ -203,7 +194,7 @@ class AND(SemanticContext): reduced = min(precedencePredicates) operands.add(reduced) - self.opnds = [ o for o in operands ] + self.opnds = list(operands) def __eq__(self, other): if self is other: @@ -227,10 +218,7 @@ class AND(SemanticContext): # unordered.

# def eval(self, parser, outerContext): - for opnd in self.opnds: - if not opnd.eval(parser, outerContext): - return False - return True + return all(opnd.eval(parser, outerContext) for opnd in self.opnds) def evalPrecedence(self, parser, outerContext): differs = False @@ -277,13 +265,11 @@ class OR (SemanticContext): def __init__(self, a, b): operands = set() if isinstance( a, OR): - for o in a.opnds: - operands.add(o) + operands.update(a.opnds) else: operands.add(a) if isinstance( b, OR): - for o in b.opnds: - operands.add(o) + operands.update(b.opnds) else: operands.add(b) @@ -291,10 +277,10 @@ class OR (SemanticContext): if len(precedencePredicates)>0: # interested in the transition with the highest precedence s = sorted(precedencePredicates) - reduced = s[len(s)-1] + reduced = s[-1] operands.add(reduced) - self.opnds = [ o for o in operands ] + self.opnds = list(operands) def __eq__(self, other): if self is other: @@ -315,10 +301,7 @@ class OR (SemanticContext): # unordered.

# def eval(self, parser, outerContext): - for opnd in self.opnds: - if opnd.eval(parser, outerContext): - return True - return False + return any(opnd.eval(parser, outerContext) for opnd in self.opnds) def evalPrecedence(self, parser, outerContext): differs = False diff --git a/runtime/Python2/src/antlr4/dfa/DFAState.py b/runtime/Python2/src/antlr4/dfa/DFAState.py index 85ccac106..7045f7c22 100644 --- a/runtime/Python2/src/antlr4/dfa/DFAState.py +++ b/runtime/Python2/src/antlr4/dfa/DFAState.py @@ -105,14 +105,9 @@ class DFAState(object): # Get the set of all alts mentioned by all ATN configurations in this # DFA state. def getAltSet(self): - alts = set() if self.configs is not None: - for c in self.configs: - alts.add(c.alt) - if len(alts)==0: - return None - else: - return alts + return set(cfg.alt for cfg in self.configs) or None + return None def __hash__(self): return hash(self.configs) diff --git a/runtime/Python2/src/antlr4/tree/Trees.py b/runtime/Python2/src/antlr4/tree/Trees.py index d48f4a904..00a322b45 100644 --- a/runtime/Python2/src/antlr4/tree/Trees.py +++ b/runtime/Python2/src/antlr4/tree/Trees.py @@ -129,8 +129,7 @@ class Trees(object): @classmethod def descendants(cls, t): - nodes = [] - nodes.append(t) + nodes = [t] for i in range(0, t.getChildCount()): nodes.extend(cls.descendants(t.getChild(i))) return nodes diff --git a/runtime/Python2/src/antlr4/xpath/XPath.py b/runtime/Python2/src/antlr4/xpath/XPath.py index eee87da6f..e138d3cdf 100644 --- a/runtime/Python2/src/antlr4/xpath/XPath.py +++ b/runtime/Python2/src/antlr4/xpath/XPath.py @@ -289,12 +289,7 @@ class XPathRuleElement(XPathElement): def evaluate(self, t): # return all children of t that match nodeName - nodes = [] - for c in Trees.getChildren(t): - if isinstance(c, ParserRuleContext ): - if (c.ruleIndex == self.ruleIndex ) == (not self.invert): - nodes.append(c) - return nodes + return [c for c in Trees.getChildren(t) if isinstance(c, ParserRuleContext) and (c.ruleIndex == self.ruleIndex) == (not self.invert)] class XPathTokenAnywhereElement(XPathElement): @@ -314,12 +309,8 @@ class XPathTokenElement(XPathElement): def evaluate(self, t): # return all children of t that match nodeName - nodes = [] - for c in Trees.getChildren(t): - if isinstance(c, TerminalNode): - if (c.symbol.type == self.tokenType ) == (not self.invert): - nodes.append(c) - return nodes + return [c for c in Trees.getChildren(t) if isinstance(c, TerminalNode) and (c.symbol.type == self.tokenType) == (not self.invert)] + class XPathWildcardAnywhereElement(XPathElement): @@ -343,4 +334,4 @@ class XPathWildcardElement(XPathElement): if self.invert: return list() # !* is weird but valid (empty) else: - return Trees.getChildren(t) \ No newline at end of file + return Trees.getChildren(t) diff --git a/runtime/Python3/src/antlr4/IntervalSet.py b/runtime/Python3/src/antlr4/IntervalSet.py index e5f535f45..980509821 100644 --- a/runtime/Python3/src/antlr4/IntervalSet.py +++ b/runtime/Python3/src/antlr4/IntervalSet.py @@ -84,16 +84,10 @@ class IntervalSet(object): if self.intervals is None: return False else: - for i in self.intervals: - if item in i: - return True - return False + return any(item in i for i in self.intervals) def __len__(self): - xlen = 0 - for i in self.intervals: - xlen += len(i) - return xlen + return sum(len(i) for i in self.intervals) def removeRange(self, v): if v.start==v.stop-1: @@ -113,7 +107,7 @@ class IntervalSet(object): # check for included range, remove it elif v.start<=i.start and v.stop>=i.stop: self.intervals.pop(k) - k = k - 1 # need another pass + k -= 1 # need another pass # check for lower boundary elif v.start DFAState: proposed = DFAState(configs=configs) - firstConfigWithRuleStopState = None - for c in configs: - if isinstance(c.state, RuleStopState): - firstConfigWithRuleStopState = c - break + firstConfigWithRuleStopState = next((cfg for cfg in configs if isinstance(cfg.state, RuleStopState)), None) if firstConfigWithRuleStopState is not None: proposed.isAcceptState = True diff --git a/runtime/Python3/src/antlr4/atn/PredictionMode.py b/runtime/Python3/src/antlr4/atn/PredictionMode.py index 03ca896c7..67039c728 100644 --- a/runtime/Python3/src/antlr4/atn/PredictionMode.py +++ b/runtime/Python3/src/antlr4/atn/PredictionMode.py @@ -235,10 +235,7 @@ class PredictionMode(Enum): # {@link RuleStopState}, otherwise {@code false} @classmethod def hasConfigInRuleStopState(cls, configs:ATNConfigSet): - for c in configs: - if isinstance(c.state, RuleStopState): - return True - return False + return any(isinstance(cfg.state, RuleStopState) for cfg in configs) # Checks if all configurations in {@code configs} are in a # {@link RuleStopState}. Configurations meeting this condition have reached @@ -250,10 +247,7 @@ class PredictionMode(Enum): # {@link RuleStopState}, otherwise {@code false} @classmethod def allConfigsInRuleStopStates(cls, configs:ATNConfigSet): - for config in configs: - if not isinstance(config.state, RuleStopState): - return False - return True + return all(isinstance(cfg.state, RuleStopState) for cfg in configs) # # Full LL prediction termination. @@ -422,10 +416,7 @@ class PredictionMode(Enum): # @classmethod def hasNonConflictingAltSet(cls, altsets:list): - for alts in altsets: - if len(alts)==1: - return True - return False + return any(len(alts) == 1 for alts in altsets) # # Determines if any single alternative subset in {@code altsets} contains @@ -437,10 +428,7 @@ class PredictionMode(Enum): # @classmethod def hasConflictingAltSet(cls, altsets:list): - for alts in altsets: - if len(alts)>1: - return True - return False + return any(len(alts) > 1 for alts in altsets) # # Determines if every alternative subset in {@code altsets} is equivalent. @@ -451,13 +439,10 @@ class PredictionMode(Enum): # @classmethod def allSubsetsEqual(cls, altsets:list): - first = None - for alts in altsets: - if first is None: - first = alts - elif not alts==first: - return False - return True + if not altsets: + return True + first = next(iter(altsets)) + return all(alts == first for alts in iter(altsets)) # # Returns the unique alternative predicted by all alternative subsets in @@ -470,10 +455,8 @@ class PredictionMode(Enum): def getUniqueAlt(cls, altsets:list): all = cls.getAlts(altsets) if len(all)==1: - for one in all: - return one - else: - return ATN.INVALID_ALT_NUMBER + return next(iter(all)) + return ATN.INVALID_ALT_NUMBER # Gets the complete set of represented alternatives for a collection of # alternative subsets. This method returns the union of each {@link BitSet} @@ -484,10 +467,7 @@ class PredictionMode(Enum): # @classmethod def getAlts(cls, altsets:list): - all = set() - for alts in altsets: - all = all | alts - return all + return set.union(*altsets) # # This function gets the conflicting alt subsets from a configuration set. @@ -531,11 +511,7 @@ class PredictionMode(Enum): @classmethod def hasStateAssociatedWithOneAlt(cls, configs:ATNConfigSet): - x = cls.getStateToAltMap(configs) - for alts in x.values(): - if len(alts)==1: - return True - return False + return any(len(alts) == 1 for alts in cls.getStateToAltMap(configs).values()) @classmethod def getSingleViableAlt(cls, altsets:list): diff --git a/runtime/Python3/src/antlr4/atn/SemanticContext.py b/runtime/Python3/src/antlr4/atn/SemanticContext.py index c012e35c2..d69165e4d 100644 --- a/runtime/Python3/src/antlr4/atn/SemanticContext.py +++ b/runtime/Python3/src/antlr4/atn/SemanticContext.py @@ -116,13 +116,7 @@ def orContext(a:SemanticContext, b:SemanticContext): return result def filterPrecedencePredicates(collection:list): - result = [] - for context in collection: - if isinstance(context, PrecedencePredicate): - if result is None: - result = [] - result.append(context) - return result + return [context for context in collection if isinstance(context, PrecedencePredicate)] class Predicate(SemanticContext): @@ -188,13 +182,11 @@ class AND(SemanticContext): def __init__(self, a:SemanticContext, b:SemanticContext): operands = set() if isinstance( a, AND ): - for o in a.opnds: - operands.add(o) + operands.update(a.opnds) else: operands.add(a) if isinstance( b, AND ): - for o in b.opnds: - operands.add(o) + operands.update(b.opnds) else: operands.add(b) @@ -204,7 +196,7 @@ class AND(SemanticContext): reduced = min(precedencePredicates) operands.add(reduced) - self.opnds = [ o for o in operands ] + self.opnds = list(operands) def __eq__(self, other): if self is other: @@ -227,11 +219,8 @@ class AND(SemanticContext): # The evaluation of predicates by this context is short-circuiting, but # unordered.

# - def eval(self, parser:Recognizer , outerContext:RuleContext ): - for opnd in self.opnds: - if not opnd.eval(parser, outerContext): - return False - return True + def eval(self, parser:Recognizer, outerContext:RuleContext): + return all(opnd.eval(parser, outerContext) for opnd in self.opnds) def evalPrecedence(self, parser:Recognizer, outerContext:RuleContext): differs = False @@ -278,13 +267,11 @@ class OR (SemanticContext): def __init__(self, a:SemanticContext, b:SemanticContext): operands = set() if isinstance( a, OR ): - for o in a.opnds: - operands.add(o) + operands.update(a.opnds) else: operands.add(a) if isinstance( b, OR ): - for o in b.opnds: - operands.add(o) + operands.update(b.opnds) else: operands.add(b) @@ -292,10 +279,10 @@ class OR (SemanticContext): if len(precedencePredicates)>0: # interested in the transition with the highest precedence s = sorted(precedencePredicates) - reduced = s[len(s)-1] + reduced = s[-1] operands.add(reduced) - self.opnds = [ o for o in operands ] + self.opnds = list(operands) def __eq__(self, other): if self is other: @@ -316,10 +303,7 @@ class OR (SemanticContext): # unordered.

# def eval(self, parser:Recognizer, outerContext:RuleContext): - for opnd in self.opnds: - if opnd.eval(parser, outerContext): - return True - return False + return any(opnd.eval(parser, outerContext) for opnd in self.opnds) def evalPrecedence(self, parser:Recognizer, outerContext:RuleContext): differs = False diff --git a/runtime/Python3/src/antlr4/dfa/DFAState.py b/runtime/Python3/src/antlr4/dfa/DFAState.py index 1ab5a0e77..9ad996384 100644 --- a/runtime/Python3/src/antlr4/dfa/DFAState.py +++ b/runtime/Python3/src/antlr4/dfa/DFAState.py @@ -104,14 +104,9 @@ class DFAState(object): # Get the set of all alts mentioned by all ATN configurations in this # DFA state. def getAltSet(self): - alts = set() if self.configs is not None: - for c in self.configs: - alts.add(c.alt) - if len(alts)==0: - return None - else: - return alts + return set(cfg.alt for cfg in self.configs) or None + return None def __hash__(self): return hash(self.configs) diff --git a/runtime/Python3/src/antlr4/tree/Trees.py b/runtime/Python3/src/antlr4/tree/Trees.py index 101df6d9a..42fde282b 100644 --- a/runtime/Python3/src/antlr4/tree/Trees.py +++ b/runtime/Python3/src/antlr4/tree/Trees.py @@ -130,8 +130,7 @@ class Trees(object): @classmethod def descendants(cls, t:ParseTree): - nodes = [] - nodes.append(t) + nodes = [t] for i in range(0, t.getChildCount()): nodes.extend(cls.descendants(t.getChild(i))) return nodes diff --git a/runtime/Python3/src/antlr4/xpath/XPath.py b/runtime/Python3/src/antlr4/xpath/XPath.py index 6b41a943a..6d3d825a5 100644 --- a/runtime/Python3/src/antlr4/xpath/XPath.py +++ b/runtime/Python3/src/antlr4/xpath/XPath.py @@ -290,12 +290,8 @@ class XPathRuleElement(XPathElement): def evaluate(self, t:ParseTree): # return all children of t that match nodeName - nodes = [] - for c in Trees.getChildren(t): - if isinstance(c, ParserRuleContext ): - if (c.ruleIndex == self.ruleIndex ) == (not self.invert): - nodes.append(c) - return nodes + return [c for c in Trees.getChildren(t) if isinstance(c, ParserRuleContext) and (c.ruleIndex == self.ruleIndex) == (not self.invert)] + class XPathTokenAnywhereElement(XPathElement): @@ -315,12 +311,8 @@ class XPathTokenElement(XPathElement): def evaluate(self, t:ParseTree): # return all children of t that match nodeName - nodes = [] - for c in Trees.getChildren(t): - if isinstance(c, TerminalNode): - if (c.symbol.type == self.tokenType ) == (not self.invert): - nodes.append(c) - return nodes + return [c for c in Trees.getChildren(t) if isinstance(c, TerminalNode) and (c.symbol.type == self.tokenType) == (not self.invert)] + class XPathWildcardAnywhereElement(XPathElement):