| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| from io import StringIO |
| from functools import reduce |
| from antlr4.PredictionContext import PredictionContext, merge |
| from antlr4.Utils import str_list |
| from antlr4.atn.ATN import ATN |
| from antlr4.atn.ATNConfig import ATNConfig |
| from antlr4.atn.SemanticContext import SemanticContext |
| from antlr4.error.Errors import UnsupportedOperationException, IllegalStateException |
|
|
| ATNSimulator = None |
|
|
| class ATNConfigSet(object): |
| |
| |
| |
| |
| |
| |
|
|
| def __init__(self, fullCtx:bool=True): |
| |
| |
| self.configLookup = dict() |
| |
| |
| |
| self.fullCtx = fullCtx |
| |
| |
| |
| |
| |
| self.readonly = False |
| |
| self.configs = [] |
|
|
| |
| |
| self.uniqueAlt = 0 |
| self.conflictingAlts = None |
|
|
| |
| |
| self.hasSemanticContext = False |
| self.dipsIntoOuterContext = False |
|
|
| self.cachedHashCode = -1 |
|
|
| def __iter__(self): |
| return self.configs.__iter__() |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| def add(self, config:ATNConfig, mergeCache=None): |
| if self.readonly: |
| raise Exception("This set is readonly") |
| if config.semanticContext is not SemanticContext.NONE: |
| self.hasSemanticContext = True |
| if config.reachesIntoOuterContext > 0: |
| self.dipsIntoOuterContext = True |
| existing = self.getOrAdd(config) |
| if existing is config: |
| self.cachedHashCode = -1 |
| self.configs.append(config) |
| return True |
| |
| rootIsWildcard = not self.fullCtx |
| merged = merge(existing.context, config.context, rootIsWildcard, mergeCache) |
| |
| |
| |
| existing.reachesIntoOuterContext = max(existing.reachesIntoOuterContext, config.reachesIntoOuterContext) |
| |
| if config.precedenceFilterSuppressed: |
| existing.precedenceFilterSuppressed = True |
| existing.context = merged |
| return True |
|
|
| def getOrAdd(self, config:ATNConfig): |
| h = config.hashCodeForConfigSet() |
| l = self.configLookup.get(h, None) |
| if l is not None: |
| r = next((cfg for cfg in l if config.equalsForConfigSet(cfg)), None) |
| if r is not None: |
| return r |
| if l is None: |
| l = [config] |
| self.configLookup[h] = l |
| else: |
| l.append(config) |
| return config |
|
|
| def getStates(self): |
| return set(c.state for c in self.configs) |
|
|
| def getPredicates(self): |
| return list(cfg.semanticContext for cfg in self.configs if cfg.semanticContext!=SemanticContext.NONE) |
|
|
| def get(self, i:int): |
| return self.configs[i] |
|
|
| def optimizeConfigs(self, interpreter:ATNSimulator): |
| if self.readonly: |
| raise IllegalStateException("This set is readonly") |
| if len(self.configs)==0: |
| return |
| for config in self.configs: |
| config.context = interpreter.getCachedContext(config.context) |
|
|
| def addAll(self, coll:list): |
| for c in coll: |
| self.add(c) |
| return False |
|
|
| def __eq__(self, other): |
| if self is other: |
| return True |
| elif not isinstance(other, ATNConfigSet): |
| return False |
|
|
| same = self.configs is not None and \ |
| self.configs==other.configs and \ |
| self.fullCtx == other.fullCtx and \ |
| self.uniqueAlt == other.uniqueAlt and \ |
| self.conflictingAlts == other.conflictingAlts and \ |
| self.hasSemanticContext == other.hasSemanticContext and \ |
| self.dipsIntoOuterContext == other.dipsIntoOuterContext |
|
|
| return same |
|
|
| def __hash__(self): |
| if self.readonly: |
| if self.cachedHashCode == -1: |
| self.cachedHashCode = self.hashConfigs() |
| return self.cachedHashCode |
| return self.hashConfigs() |
|
|
| def hashConfigs(self): |
| return reduce(lambda h, cfg: hash((h, cfg)), self.configs, 0) |
|
|
| def __len__(self): |
| return len(self.configs) |
|
|
| def isEmpty(self): |
| return len(self.configs)==0 |
|
|
| def __contains__(self, config): |
| if self.configLookup is None: |
| raise UnsupportedOperationException("This method is not implemented for readonly sets.") |
| h = config.hashCodeForConfigSet() |
| l = self.configLookup.get(h, None) |
| if l is not None: |
| for c in l: |
| if config.equalsForConfigSet(c): |
| return True |
| return False |
|
|
| def clear(self): |
| if self.readonly: |
| raise IllegalStateException("This set is readonly") |
| self.configs.clear() |
| self.cachedHashCode = -1 |
| self.configLookup.clear() |
|
|
| def setReadonly(self, readonly:bool): |
| self.readonly = readonly |
| self.configLookup = None |
|
|
| def __str__(self): |
| with StringIO() as buf: |
| buf.write(str_list(self.configs)) |
| if self.hasSemanticContext: |
| buf.write(",hasSemanticContext=") |
| buf.write(str(self.hasSemanticContext)) |
| if self.uniqueAlt!=ATN.INVALID_ALT_NUMBER: |
| buf.write(",uniqueAlt=") |
| buf.write(str(self.uniqueAlt)) |
| if self.conflictingAlts is not None: |
| buf.write(",conflictingAlts=") |
| buf.write(str(self.conflictingAlts)) |
| if self.dipsIntoOuterContext: |
| buf.write(",dipsIntoOuterContext") |
| return buf.getvalue() |
|
|
|
|
| class OrderedATNConfigSet(ATNConfigSet): |
|
|
| def __init__(self): |
| super().__init__() |
|
|
|
|
|
|
|
|