def __init__(self, input: TokenStream): super().__init__() # The input stream. self._input = None # The error handling strategy for the parser. The default value is a new # instance of {@link DefaultErrorStrategy}. self._errHandler = DefaultErrorStrategy() self._precedenceStack = list() self._precedenceStack.append(0) # The {@link ParserRuleContext} object for the currently executing rule. # self is always non-null during the parsing process. self._ctx = None # Specifies whether or not the parser should construct a parse tree during # the parsing process. The default value is {@code true}. self.buildParseTrees = True # When {@link #setTrace}{@code (true)} is called, a reference to the # {@link TraceListener} is stored here so it can be easily removed in a # later call to {@link #setTrace}{@code (false)}. The listener itself is # implemented as a parser listener so self field is not directly used by # other parser methods. self._tracer = None # The list of {@link ParseTreeListener} listeners registered to receive # events during the parse. self._parseListeners = None # The number of syntax errors reported during parsing. self value is # incremented each time {@link #notifyErrorListeners} is called. self._syntaxErrors = 0 self.setInputStream(input)
def __init__(self, input:TokenStream): super().__init__() # The input stream. self._input = None # The error handling strategy for the parser. The default value is a new # instance of {@link DefaultErrorStrategy}. self._errHandler = DefaultErrorStrategy() self._precedenceStack = list() self._precedenceStack.append(0) # The {@link ParserRuleContext} object for the currently executing rule. # self is always non-null during the parsing process. self._ctx = None # Specifies whether or not the parser should construct a parse tree during # the parsing process. The default value is {@code true}. self.buildParseTrees = True # When {@link #setTrace}{@code (true)} is called, a reference to the # {@link TraceListener} is stored here so it can be easily removed in a # later call to {@link #setTrace}{@code (false)}. The listener itself is # implemented as a parser listener so self field is not directly used by # other parser methods. self._tracer = None # The list of {@link ParseTreeListener} listeners registered to receive # events during the parse. self._parseListeners = None # The number of syntax errors reported during parsing. self value is # incremented each time {@link #notifyErrorListeners} is called. self._syntaxErrors = 0 self.setInputStream(input)
def parse(actions, spdOutput, two_stageParsing): tokens = CommonTokenStream(SPDGrammarLexer(InputStream(spdOutput))) parser = SPDGrammarParser(tokens) visitor = SPDGrammarVisitorImplementation(actions) if not two_stageParsing: visitor.visit(parser.json()) return visitor._errors parser._interp.predictionMode = PredictionMode.SLL parser.removeErrorListeners() parser._errHandler = BailErrorStrategy() try: visitor.visit(parser.json()) except RuntimeError as exception: if isinstance(exception, RecognitionException): tokens.seek(0) parser.addErrorListener(ConsoleErrorListener.INSTANCE) parser._errHandler = DefaultErrorStrategy() parser._interp.predictionMode = PredictionMode.LL visitor.visit(parser.json()) return visitor._errors
def parse(self, expression, error_listener): lexer = DynamoDbGrammarLexer(antlr4.InputStream(expression)) tokens = antlr4.CommonTokenStream(lexer) parser = DynamoDbGrammarParser(tokens) parser.buildParseTrees = True lexer.removeErrorListeners() lexer.addErrorListener(error_listener) parser.removeErrorListeners() # DO NOT CALL addErrorListener(errorListener) for BailErrorStrategy # ExpressionErrorListener converts syntaxErrors to validation exceptions # But when using SLL strategy syntaxErrors can be false # Such that a syntaxError thrown by SLL may not necessarily be a real syntaxError # For such cases we don't want the syntaxError become a validation exception and go up to customers # We need to parse the expression again with LL strategy in case of a syntax error # BailErrorStrategy will re-throw RecognitionExceptions as ParseCancellationException # Such that it's not caught by underlying parsing rule implemented by parseStub parser._interp.predictionMode = antlr4.PredictionMode.SLL parser._errHandler = BailErrorStrategy() try: # Stage 1 parse with PredictionMode.SLL # If there are no issues SLL was enough to parse # If there were problems LL will be used to try again return self.parse_stub(parser) except ParseCancellationException as e: # If there was an error we don't know if it's a real SyntaxError # Or SLL strategy wasn't strong enough # Stage 2 parse with default prediction mode tokens.reset() parser.reset() parser.addErrorListener(error_listener) parser._errHandler = DefaultErrorStrategy() parser._interp.predictionMode = antlr4.PredictionMode.LL return self.parse_stub(parser)
class Parser: _error_strategies: ClassVar[Dict[str, ErrorStrategy]] = { 'default': DefaultErrorStrategy(), 'bail': BailErrorStrategy(), } def __init__(self, file: str): self._parser = self._build_parser(file) self._error_listener = self._setup_listener() def _setup_listener(self) -> WebIDLErrorListener: self._parser.removeErrorListeners() self._parser.addErrorListener(error_listener := WebIDLErrorListener()) return error_listener @staticmethod def _build_parser(file: str) -> WebIDLParser: stream = FileStream(fileName=file, encoding='utf-8') functions = ( WebIDLLexer, CommonTokenStream, WebIDLParser, ) return cast( WebIDLParser, reduce(lambda acc, func: func(acc), functions, stream), ) def setup_parser_strategy(self, strategy: str) -> None: self._parser._errHandler = self._error_strategies[strategy] @_setup_strategy('bail') def parse(self) -> ParserRuleContext: try: return self._parser.webIDL() except ParseCancellationException: raise IDLParseError @_setup_strategy('default') def validate(self) -> List[SyntaxErrorInfo]: self._parser.webIDL() return self._error_listener.errors
def parse(atom): tokens = CommonTokenStream(ASPGrammarLexer(InputStream(atom))) parser = ASPGrammarParser(tokens) visitor = ASPParser() parser._interp.predictionMode = PredictionMode.SLL parser.removeErrorListeners() parser._errHandler = BailErrorStrategy() try: visitor.visit(parser.output()) except RuntimeError as exception: if isinstance(exception, RecognitionException): tokens.seek(0) parser.addErrorListener(ConsoleErrorListener.INSTANCE) parser._errHandler = DefaultErrorStrategy() parser._interp.predictionMode = PredictionMode.LL visitor.visit(parser.output()) return visitor
def parse(answerSets, dlvhexOutput, two_stageParsing): tokens = CommonTokenStream(DLVHEXLexer(InputStream(dlvhexOutput))) parser = DLVHEXParser(tokens) visitor = DLVHEXParserVisitorImplementation(answerSets) if not two_stageParsing: visitor.visit(parser.output()) return parser._interp.predictionMode = PredictionMode.SLL parser.removeErrorListeners() parser._errHandler = BailErrorStrategy() try: visitor.visit(parser.output()) except RuntimeError as exception: if isinstance(exception, RecognitionException): tokens.seek(0) parser.addErrorListener(ConsoleErrorListener.INSTANCE) parser._errHandler = DefaultErrorStrategy() parser._interp.predictionMode = PredictionMode.LL visitor.visit(parser.output())
class Parser (Recognizer): # self field maps from the serialized ATN string to the deserialized {@link ATN} with # bypass alternatives. # # @see ATNDeserializationOptions#isGenerateRuleBypassTransitions() # bypassAltsAtnCache = dict() def __init__(self, input:TokenStream): super().__init__() # The input stream. self._input = None # The error handling strategy for the parser. The default value is a new # instance of {@link DefaultErrorStrategy}. self._errHandler = DefaultErrorStrategy() self._precedenceStack = list() self._precedenceStack.append(0) # The {@link ParserRuleContext} object for the currently executing rule. # self is always non-null during the parsing process. self._ctx = None # Specifies whether or not the parser should construct a parse tree during # the parsing process. The default value is {@code true}. self.buildParseTrees = True # When {@link #setTrace}{@code (true)} is called, a reference to the # {@link TraceListener} is stored here so it can be easily removed in a # later call to {@link #setTrace}{@code (false)}. The listener itself is # implemented as a parser listener so self field is not directly used by # other parser methods. self._tracer = None # The list of {@link ParseTreeListener} listeners registered to receive # events during the parse. self._parseListeners = None # The number of syntax errors reported during parsing. self value is # incremented each time {@link #notifyErrorListeners} is called. self._syntaxErrors = 0 self.setInputStream(input) def __setattr__(self, key, value): object.__setattr__(self, key, value) # reset the parser's state# def reset(self): if self._input is not None: self._input.seek(0) self._errHandler.reset(self) self._ctx = None self._syntaxErrors = 0 self.setTrace(False) self._precedenceStack = list() self._precedenceStack.append(0) if self._interp is not None: self._interp.reset() # Match current input symbol against {@code ttype}. If the symbol type # matches, {@link ANTLRErrorStrategy#reportMatch} and {@link #consume} are # called to complete the match process. # # <p>If the symbol type does not match, # {@link ANTLRErrorStrategy#recoverInline} is called on the current error # strategy to attempt recovery. If {@link #getBuildParseTree} is # {@code true} and the token index of the symbol returned by # {@link ANTLRErrorStrategy#recoverInline} is -1, the symbol is added to # the parse tree by calling {@link ParserRuleContext#addErrorNode}.</p> # # @param ttype the token type to match # @return the matched symbol # @throws RecognitionException if the current input symbol did not match # {@code ttype} and the error strategy could not recover from the # mismatched symbol def match(self, ttype:int): t = self.getCurrentToken() if t.type==ttype: self._errHandler.reportMatch(self) self.consume() else: t = self._errHandler.recoverInline(self) if self.buildParseTrees and t.tokenIndex==-1: # we must have conjured up a new token during single token insertion # if it's not the current symbol self._ctx.addErrorNode(t) return t # Match current input symbol as a wildcard. If the symbol type matches # (i.e. has a value greater than 0), {@link ANTLRErrorStrategy#reportMatch} # and {@link #consume} are called to complete the match process. # # <p>If the symbol type does not match, # {@link ANTLRErrorStrategy#recoverInline} is called on the current error # strategy to attempt recovery. If {@link #getBuildParseTree} is # {@code true} and the token index of the symbol returned by # {@link ANTLRErrorStrategy#recoverInline} is -1, the symbol is added to # the parse tree by calling {@link ParserRuleContext#addErrorNode}.</p> # # @return the matched symbol # @throws RecognitionException if the current input symbol did not match # a wildcard and the error strategy could not recover from the mismatched # symbol def matchWildcard(self): t = self.getCurrentToken() if t.type > 0: self._errHandler.reportMatch(self) self.consume() else: t = self._errHandler.recoverInline(self) if self._buildParseTrees and t.tokenIndex == -1: # we must have conjured up a new token during single token insertion # if it's not the current symbol self._ctx.addErrorNode(t) return t def getParseListeners(self): return list() if self._parseListeners is None else self._parseListeners # Registers {@code listener} to receive events during the parsing process. # # <p>To support output-preserving grammar transformations (including but not # limited to left-recursion removal, automated left-factoring, and # optimized code generation), calls to listener methods during the parse # may differ substantially from calls made by # {@link ParseTreeWalker#DEFAULT} used after the parse is complete. In # particular, rule entry and exit events may occur in a different order # during the parse than after the parser. In addition, calls to certain # rule entry methods may be omitted.</p> # # <p>With the following specific exceptions, calls to listener events are # <em>deterministic</em>, i.e. for identical input the calls to listener # methods will be the same.</p> # # <ul> # <li>Alterations to the grammar used to generate code may change the # behavior of the listener calls.</li> # <li>Alterations to the command line options passed to ANTLR 4 when # generating the parser may change the behavior of the listener calls.</li> # <li>Changing the version of the ANTLR Tool used to generate the parser # may change the behavior of the listener calls.</li> # </ul> # # @param listener the listener to add # # @throws NullPointerException if {@code} listener is {@code null} # def addParseListener(self, listener:ParseTreeListener): if listener is None: raise ReferenceError("listener") if self._parseListeners is None: self._parseListeners = [] self._parseListeners.append(listener) # # Remove {@code listener} from the list of parse listeners. # # <p>If {@code listener} is {@code null} or has not been added as a parse # listener, self method does nothing.</p> # @param listener the listener to remove # def removeParseListener(self, listener:ParseTreeListener): if self._parseListeners is not None: self._parseListeners.remove(listener) if len(self._parseListeners)==0: self._parseListeners = None # Remove all parse listeners. def removeParseListeners(self): self._parseListeners = None # Notify any parse listeners of an enter rule event. def triggerEnterRuleEvent(self): if self._parseListeners is not None: for listener in self._parseListeners: listener.enterEveryRule(self._ctx) self._ctx.enterRule(listener) # # Notify any parse listeners of an exit rule event. # # @see #addParseListener # def triggerExitRuleEvent(self): if self._parseListeners is not None: # reverse order walk of listeners for listener in reversed(self._parseListeners): self._ctx.exitRule(listener) listener.exitEveryRule(self._ctx) def getTokenFactory(self): return self._input.tokenSource._factory # Tell our token source and error strategy about a new way to create tokens.# def setTokenFactory(self, factory:TokenFactory): self._input.tokenSource._factory = factory # The ATN with bypass alternatives is expensive to create so we create it # lazily. # # @throws UnsupportedOperationException if the current parser does not # implement the {@link #getSerializedATN()} method. # def getATNWithBypassAlts(self): serializedAtn = self.getSerializedATN() if serializedAtn is None: raise UnsupportedOperationException("The current parser does not support an ATN with bypass alternatives.") result = self.bypassAltsAtnCache.get(serializedAtn, None) if result is None: deserializationOptions = ATNDeserializationOptions() deserializationOptions.generateRuleBypassTransitions = True result = ATNDeserializer(deserializationOptions).deserialize(serializedAtn) self.bypassAltsAtnCache[serializedAtn] = result return result # The preferred method of getting a tree pattern. For example, here's a # sample use: # # <pre> # ParseTree t = parser.expr(); # ParseTreePattern p = parser.compileParseTreePattern("<ID>+0", MyParser.RULE_expr); # ParseTreeMatch m = p.match(t); # String id = m.get("ID"); # </pre> # def compileParseTreePattern(self, pattern:str, patternRuleIndex:int, lexer:Lexer = None): if lexer is None: if self.getTokenStream() is not None: tokenSource = self.getTokenStream().getTokenSource() if isinstance( tokenSource, Lexer ): lexer = tokenSource if lexer is None: raise UnsupportedOperationException("Parser can't discover a lexer to use") m = ParseTreePatternMatcher(lexer, self) return m.compile(pattern, patternRuleIndex) def getInputStream(self): return self.getTokenStream() def setInputStream(self, input:InputStream): self.setTokenStream(input) def getTokenStream(self): return self._input # Set the token stream and reset the parser.# def setTokenStream(self, input:TokenStream): self._input = None self.reset() self._input = input # Match needs to return the current input symbol, which gets put # into the label for the associated token ref; e.g., x=ID. # def getCurrentToken(self): return self._input.LT(1) def notifyErrorListeners(self, msg:str, offendingToken:Token = None, e:RecognitionException = None): if offendingToken is None: offendingToken = self.getCurrentToken() self._syntaxErrors += 1 line = offendingToken.line column = offendingToken.column listener = self.getErrorListenerDispatch() listener.syntaxError(self, offendingToken, line, column, msg, e) # # Consume and return the {@linkplain #getCurrentToken current symbol}. # # <p>E.g., given the following input with {@code A} being the current # lookahead symbol, self function moves the cursor to {@code B} and returns # {@code A}.</p> # # <pre> # A B # ^ # </pre> # # If the parser is not in error recovery mode, the consumed symbol is added # to the parse tree using {@link ParserRuleContext#addChild(Token)}, and # {@link ParseTreeListener#visitTerminal} is called on any parse listeners. # If the parser <em>is</em> in error recovery mode, the consumed symbol is # added to the parse tree using # {@link ParserRuleContext#addErrorNode(Token)}, and # {@link ParseTreeListener#visitErrorNode} is called on any parse # listeners. # def consume(self): o = self.getCurrentToken() if o.type != Token.EOF: self.getInputStream().consume() hasListener = self._parseListeners is not None and len(self._parseListeners)>0 if self.buildParseTrees or hasListener: if self._errHandler.inErrorRecoveryMode(self): node = self._ctx.addErrorNode(o) else: node = self._ctx.addTokenNode(o) if hasListener: for listener in self._parseListeners: listener.visitTerminal(node) return o def addContextToParseTree(self): # add current context to parent if we have a parent if self._ctx.parentCtx is not None: self._ctx.parentCtx.addChild(self._ctx) # Always called by generated parsers upon entry to a rule. Access field # {@link #_ctx} get the current context. # def enterRule(self, localctx:ParserRuleContext , state:int , ruleIndexint ): self.state = state self._ctx = localctx self._ctx.start = self._input.LT(1) if self.buildParseTrees: self.addContextToParseTree() if self._parseListeners is not None: self.triggerEnterRuleEvent() def exitRule(self): self._ctx.stop = self._input.LT(-1) # trigger event on _ctx, before it reverts to parent if self._parseListeners is not None: self.triggerExitRuleEvent() self.state = self._ctx.invokingState self._ctx = self._ctx.parentCtx def enterOuterAlt(self, localctx:ParserRuleContext, altNum:int): # if we have new localctx, make sure we replace existing ctx # that is previous child of parse tree if self.buildParseTrees and self._ctx != localctx: if self._ctx.parentCtx is not None: self._ctx.parentCtx.removeLastChild() self._ctx.parentCtx.addChild(localctx) self._ctx = localctx if self._parseListeners is not None: self.triggerEnterRuleEvent() # Get the precedence level for the top-most precedence rule. # # @return The precedence level for the top-most precedence rule, or -1 if # the parser context is not nested within a precedence rule. # def getPrecedence(self): if len(self._precedenceStack)==0: return -1 else: return self._precedenceStack[-1] def enterRecursionRule(self, localctx:ParserRuleContext, state:int, ruleIndex:int, precedence:int): self.state = state self._precedenceStack.append(precedence) self._ctx = localctx self._ctx.start = self._input.LT(1) if self._parseListeners is not None: self.triggerEnterRuleEvent() # simulates rule entry for left-recursive rules # # Like {@link #enterRule} but for recursive rules. # def pushNewRecursionContext(self, localctx:ParserRuleContext, state:int, ruleIndex:int): previous = self._ctx previous.parentCtx = localctx previous.invokingState = state previous.stop = self._input.LT(-1) self._ctx = localctx self._ctx.start = previous.start if self.buildParseTrees: self._ctx.addChild(previous) if self._parseListeners is not None: self.triggerEnterRuleEvent() # simulates rule entry for left-recursive rules def unrollRecursionContexts(self, parentCtx:ParserRuleContext): self._precedenceStack.pop() self._ctx.stop = self._input.LT(-1) retCtx = self._ctx # save current ctx (return value) # unroll so _ctx is as it was before call to recursive method if self._parseListeners is not None: while self._ctx is not parentCtx: self.triggerExitRuleEvent() self._ctx = self._ctx.parentCtx else: self._ctx = parentCtx # hook into tree retCtx.parentCtx = parentCtx if self.buildParseTrees and parentCtx is not None: # add return ctx into invoking rule's tree parentCtx.addChild(retCtx) def getInvokingContext(self, ruleIndex:int): ctx = self._ctx while ctx is not None: if ctx.ruleIndex == ruleIndex: return ctx ctx = ctx.parentCtx return None def precpred(self, localctx:RuleContext , precedence:int): return precedence >= self._precedenceStack[-1] def inContext(self, context:str): # TODO: useful in parser? return False # # Checks whether or not {@code symbol} can follow the current state in the # ATN. The behavior of self method is equivalent to the following, but is # implemented such that the complete context-sensitive follow set does not # need to be explicitly constructed. # # <pre> # return getExpectedTokens().contains(symbol); # </pre> # # @param symbol the symbol type to check # @return {@code true} if {@code symbol} can follow the current state in # the ATN, otherwise {@code false}. # def isExpectedToken(self, symbol:int): atn = self._interp.atn ctx = self._ctx s = atn.states[self.state] following = atn.nextTokens(s) if symbol in following: return True if not Token.EPSILON in following: return False while ctx is not None and ctx.invokingState>=0 and Token.EPSILON in following: invokingState = atn.states[ctx.invokingState] rt = invokingState.transitions[0] following = atn.nextTokens(rt.followState) if symbol in following: return True ctx = ctx.parentCtx if Token.EPSILON in following and symbol == Token.EOF: return True else: return False # Computes the set of input symbols which could follow the current parser # state and context, as given by {@link #getState} and {@link #getContext}, # respectively. # # @see ATN#getExpectedTokens(int, RuleContext) # def getExpectedTokens(self): return self._interp.atn.getExpectedTokens(self.state, self._ctx) def getExpectedTokensWithinCurrentRule(self): atn = self._interp.atn s = atn.states[self.state] return atn.nextTokens(s) # Get a rule's index (i.e., {@code RULE_ruleName} field) or -1 if not found.# def getRuleIndex(self, ruleName:str): ruleIndex = self.getRuleIndexMap().get(ruleName, None) if ruleIndex is not None: return ruleIndex else: return -1 # Return List<String> of the rule names in your parser instance # leading up to a call to the current rule. You could override if # you want more details such as the file/line info of where # in the ATN a rule is invoked. # # this is very useful for error messages. # def getRuleInvocationStack(self, p:RuleContext=None): if p is None: p = self._ctx stack = list() while p is not None: # compute what follows who invoked us ruleIndex = p.getRuleIndex() if ruleIndex<0: stack.append("n/a") else: stack.append(self.ruleNames[ruleIndex]) p = p.parentCtx return stack # For debugging and other purposes.# def getDFAStrings(self): return [ str(dfa) for dfa in self._interp.decisionToDFA] # For debugging and other purposes.# def dumpDFA(self): seenOne = False for i in range(0, len(self._interp.decisionToDFA)): dfa = self._interp.decisionToDFA[i] if len(dfa.states)>0: if seenOne: print() print("Decision " + str(dfa.decision) + ":") print(dfa.toString(self.literalNames, self.symbolicNames), end='') seenOne = True def getSourceName(self): return self._input.sourceName # During a parse is sometimes useful to listen in on the rule entry and exit # events as well as token matches. self is for quick and dirty debugging. # def setTrace(self, trace:bool): if not trace: self.removeParseListener(self._tracer) self._tracer = None else: if self._tracer is not None: self.removeParseListener(self._tracer) self._tracer = TraceListener(self) self.addParseListener(self._tracer)
class Parser(Recognizer): # self field maps from the serialized ATN string to the deserialized {@link ATN} with # bypass alternatives. # # @see ATNDeserializationOptions#isGenerateRuleBypassTransitions() # bypassAltsAtnCache = dict() def __init__(self, input: TokenStream): super().__init__() # The input stream. self._input = None # The error handling strategy for the parser. The default value is a new # instance of {@link DefaultErrorStrategy}. self._errHandler = DefaultErrorStrategy() self._precedenceStack = list() self._precedenceStack.append(0) # The {@link ParserRuleContext} object for the currently executing rule. # self is always non-null during the parsing process. self._ctx = None # Specifies whether or not the parser should construct a parse tree during # the parsing process. The default value is {@code true}. self.buildParseTrees = True # When {@link #setTrace}{@code (true)} is called, a reference to the # {@link TraceListener} is stored here so it can be easily removed in a # later call to {@link #setTrace}{@code (false)}. The listener itself is # implemented as a parser listener so self field is not directly used by # other parser methods. self._tracer = None # The list of {@link ParseTreeListener} listeners registered to receive # events during the parse. self._parseListeners = None # The number of syntax errors reported during parsing. self value is # incremented each time {@link #notifyErrorListeners} is called. self._syntaxErrors = 0 self.setInputStream(input) # reset the parser's state# def reset(self): if self._input is not None: self._input.seek(0) self._errHandler.reset(self) self._ctx = None self._syntaxErrors = 0 self.setTrace(False) self._precedenceStack = list() self._precedenceStack.append(0) if self._interp is not None: self._interp.reset() # Match current input symbol against {@code ttype}. If the symbol type # matches, {@link ANTLRErrorStrategy#reportMatch} and {@link #consume} are # called to complete the match process. # # <p>If the symbol type does not match, # {@link ANTLRErrorStrategy#recoverInline} is called on the current error # strategy to attempt recovery. If {@link #getBuildParseTree} is # {@code true} and the token index of the symbol returned by # {@link ANTLRErrorStrategy#recoverInline} is -1, the symbol is added to # the parse tree by calling {@link ParserRuleContext#addErrorNode}.</p> # # @param ttype the token type to match # @return the matched symbol # @throws RecognitionException if the current input symbol did not match # {@code ttype} and the error strategy could not recover from the # mismatched symbol def match(self, ttype: int): t = self.getCurrentToken() if t.type == ttype: self._errHandler.reportMatch(self) self.consume() else: t = self._errHandler.recoverInline(self) if self.buildParseTrees and t.tokenIndex == -1: # we must have conjured up a new token during single token insertion # if it's not the current symbol self._ctx.addErrorNode(t) return t # Match current input symbol as a wildcard. If the symbol type matches # (i.e. has a value greater than 0), {@link ANTLRErrorStrategy#reportMatch} # and {@link #consume} are called to complete the match process. # # <p>If the symbol type does not match, # {@link ANTLRErrorStrategy#recoverInline} is called on the current error # strategy to attempt recovery. If {@link #getBuildParseTree} is # {@code true} and the token index of the symbol returned by # {@link ANTLRErrorStrategy#recoverInline} is -1, the symbol is added to # the parse tree by calling {@link ParserRuleContext#addErrorNode}.</p> # # @return the matched symbol # @throws RecognitionException if the current input symbol did not match # a wildcard and the error strategy could not recover from the mismatched # symbol def matchWildcard(self): t = self.getCurrentToken() if t.type > 0: self._errHandler.reportMatch(self) self.consume() else: t = self._errHandler.recoverInline(self) if self.buildParseTrees and t.tokenIndex == -1: # we must have conjured up a new token during single token insertion # if it's not the current symbol self._ctx.addErrorNode(t) return t def getParseListeners(self): return list() if self._parseListeners is None else self._parseListeners # Registers {@code listener} to receive events during the parsing process. # # <p>To support output-preserving grammar transformations (including but not # limited to left-recursion removal, automated left-factoring, and # optimized code generation), calls to listener methods during the parse # may differ substantially from calls made by # {@link ParseTreeWalker#DEFAULT} used after the parse is complete. In # particular, rule entry and exit events may occur in a different order # during the parse than after the parser. In addition, calls to certain # rule entry methods may be omitted.</p> # # <p>With the following specific exceptions, calls to listener events are # <em>deterministic</em>, i.e. for identical input the calls to listener # methods will be the same.</p> # # <ul> # <li>Alterations to the grammar used to generate code may change the # behavior of the listener calls.</li> # <li>Alterations to the command line options passed to ANTLR 4 when # generating the parser may change the behavior of the listener calls.</li> # <li>Changing the version of the ANTLR Tool used to generate the parser # may change the behavior of the listener calls.</li> # </ul> # # @param listener the listener to add # # @throws NullPointerException if {@code} listener is {@code null} # def addParseListener(self, listener: ParseTreeListener): if listener is None: raise ReferenceError("listener") if self._parseListeners is None: self._parseListeners = [] self._parseListeners.append(listener) # # Remove {@code listener} from the list of parse listeners. # # <p>If {@code listener} is {@code null} or has not been added as a parse # listener, self method does nothing.</p> # @param listener the listener to remove # def removeParseListener(self, listener: ParseTreeListener): if self._parseListeners is not None: self._parseListeners.remove(listener) if len(self._parseListeners) == 0: self._parseListeners = None # Remove all parse listeners. def removeParseListeners(self): self._parseListeners = None # Notify any parse listeners of an enter rule event. def triggerEnterRuleEvent(self): if self._parseListeners is not None: for listener in self._parseListeners: listener.enterEveryRule(self._ctx) self._ctx.enterRule(listener) # # Notify any parse listeners of an exit rule event. # # @see #addParseListener # def triggerExitRuleEvent(self): if self._parseListeners is not None: # reverse order walk of listeners for listener in reversed(self._parseListeners): self._ctx.exitRule(listener) listener.exitEveryRule(self._ctx) def getTokenFactory(self): return self._input.tokenSource._factory # Tell our token source and error strategy about a new way to create tokens.# def setTokenFactory(self, factory: TokenFactory): self._input.tokenSource._factory = factory # The ATN with bypass alternatives is expensive to create so we create it # lazily. # # @throws UnsupportedOperationException if the current parser does not # implement the {@link #getSerializedATN()} method. # def getATNWithBypassAlts(self): serializedAtn = self.getSerializedATN() if serializedAtn is None: raise UnsupportedOperationException( "The current parser does not support an ATN with bypass alternatives." ) result = self.bypassAltsAtnCache.get(serializedAtn, None) if result is None: deserializationOptions = ATNDeserializationOptions() deserializationOptions.generateRuleBypassTransitions = True result = ATNDeserializer(deserializationOptions).deserialize( serializedAtn) self.bypassAltsAtnCache[serializedAtn] = result return result # The preferred method of getting a tree pattern. For example, here's a # sample use: # # <pre> # ParseTree t = parser.expr(); # ParseTreePattern p = parser.compileParseTreePattern("<ID>+0", MyParser.RULE_expr); # ParseTreeMatch m = p.match(t); # String id = m.get("ID"); # </pre> # def compileParseTreePattern(self, pattern: str, patternRuleIndex: int, lexer: Lexer = None): if lexer is None: if self.getTokenStream() is not None: tokenSource = self.getTokenStream().getTokenSource() if isinstance(tokenSource, Lexer): lexer = tokenSource if lexer is None: raise UnsupportedOperationException( "Parser can't discover a lexer to use") m = ParseTreePatternMatcher(lexer, self) return m.compile(pattern, patternRuleIndex) def getInputStream(self): return self.getTokenStream() def setInputStream(self, input: InputStream): self.setTokenStream(input) def getTokenStream(self): return self._input # Set the token stream and reset the parser.# def setTokenStream(self, input: TokenStream): self._input = None self.reset() self._input = input # Match needs to return the current input symbol, which gets put # into the label for the associated token ref; e.g., x=ID. # def getCurrentToken(self): return self._input.LT(1) def notifyErrorListeners(self, msg: str, offendingToken: Token = None, e: RecognitionException = None): if offendingToken is None: offendingToken = self.getCurrentToken() self._syntaxErrors += 1 line = offendingToken.line column = offendingToken.column listener = self.getErrorListenerDispatch() listener.syntaxError(self, offendingToken, line, column, msg, e) # # Consume and return the {@linkplain #getCurrentToken current symbol}. # # <p>E.g., given the following input with {@code A} being the current # lookahead symbol, self function moves the cursor to {@code B} and returns # {@code A}.</p> # # <pre> # A B # ^ # </pre> # # If the parser is not in error recovery mode, the consumed symbol is added # to the parse tree using {@link ParserRuleContext#addChild(Token)}, and # {@link ParseTreeListener#visitTerminal} is called on any parse listeners. # If the parser <em>is</em> in error recovery mode, the consumed symbol is # added to the parse tree using # {@link ParserRuleContext#addErrorNode(Token)}, and # {@link ParseTreeListener#visitErrorNode} is called on any parse # listeners. # def consume(self): o = self.getCurrentToken() if o.type != Token.EOF: self.getInputStream().consume() hasListener = self._parseListeners is not None and len( self._parseListeners) > 0 if self.buildParseTrees or hasListener: if self._errHandler.inErrorRecoveryMode(self): node = self._ctx.addErrorNode(o) else: node = self._ctx.addTokenNode(o) if hasListener: for listener in self._parseListeners: listener.visitTerminal(node) return o def addContextToParseTree(self): # add current context to parent if we have a parent if self._ctx.parentCtx is not None: self._ctx.parentCtx.addChild(self._ctx) # Always called by generated parsers upon entry to a rule. Access field # {@link #_ctx} get the current context. # def enterRule(self, localctx: ParserRuleContext, state: int, ruleIndexint): self.state = state self._ctx = localctx self._ctx.start = self._input.LT(1) if self.buildParseTrees: self.addContextToParseTree() if self._parseListeners is not None: self.triggerEnterRuleEvent() def exitRule(self): self._ctx.stop = self._input.LT(-1) # trigger event on _ctx, before it reverts to parent if self._parseListeners is not None: self.triggerExitRuleEvent() self.state = self._ctx.invokingState self._ctx = self._ctx.parentCtx def enterOuterAlt(self, localctx: ParserRuleContext, altNum: int): # if we have new localctx, make sure we replace existing ctx # that is previous child of parse tree if self.buildParseTrees and self._ctx != localctx: if self._ctx.parentCtx is not None: self._ctx.parentCtx.removeLastChild() self._ctx.parentCtx.addChild(localctx) self._ctx = localctx # Get the precedence level for the top-most precedence rule. # # @return The precedence level for the top-most precedence rule, or -1 if # the parser context is not nested within a precedence rule. # def getPrecedence(self): if len(self._precedenceStack) == 0: return -1 else: return self._precedenceStack[-1] def enterRecursionRule(self, localctx: ParserRuleContext, state: int, ruleIndex: int, precedence: int): self.state = state self._precedenceStack.append(precedence) self._ctx = localctx self._ctx.start = self._input.LT(1) if self._parseListeners is not None: self.triggerEnterRuleEvent( ) # simulates rule entry for left-recursive rules # # Like {@link #enterRule} but for recursive rules. # def pushNewRecursionContext(self, localctx: ParserRuleContext, state: int, ruleIndex: int): previous = self._ctx previous.parentCtx = localctx previous.invokingState = state previous.stop = self._input.LT(-1) self._ctx = localctx self._ctx.start = previous.start if self.buildParseTrees: self._ctx.addChild(previous) if self._parseListeners is not None: self.triggerEnterRuleEvent( ) # simulates rule entry for left-recursive rules def unrollRecursionContexts(self, parentCtx: ParserRuleContext): self._precedenceStack.pop() self._ctx.stop = self._input.LT(-1) retCtx = self._ctx # save current ctx (return value) # unroll so _ctx is as it was before call to recursive method if self._parseListeners is not None: while self._ctx is not parentCtx: self.triggerExitRuleEvent() self._ctx = self._ctx.parentCtx else: self._ctx = parentCtx # hook into tree retCtx.parentCtx = parentCtx if self.buildParseTrees and parentCtx is not None: # add return ctx into invoking rule's tree parentCtx.addChild(retCtx) def getInvokingContext(self, ruleIndex: int): ctx = self._ctx while ctx is not None: if ctx.ruleIndex == ruleIndex: return ctx ctx = ctx.parentCtx return None def precpred(self, localctx: RuleContext, precedence: int): return precedence >= self._precedenceStack[-1] def inContext(self, context: str): # TODO: useful in parser? return False # # Checks whether or not {@code symbol} can follow the current state in the # ATN. The behavior of self method is equivalent to the following, but is # implemented such that the complete context-sensitive follow set does not # need to be explicitly constructed. # # <pre> # return getExpectedTokens().contains(symbol); # </pre> # # @param symbol the symbol type to check # @return {@code true} if {@code symbol} can follow the current state in # the ATN, otherwise {@code false}. # def isExpectedToken(self, symbol: int): atn = self._interp.atn ctx = self._ctx s = atn.states[self.state] following = atn.nextTokens(s) if symbol in following: return True if not Token.EPSILON in following: return False while ctx is not None and ctx.invokingState >= 0 and Token.EPSILON in following: invokingState = atn.states[ctx.invokingState] rt = invokingState.transitions[0] following = atn.nextTokens(rt.followState) if symbol in following: return True ctx = ctx.parentCtx if Token.EPSILON in following and symbol == Token.EOF: return True else: return False # Computes the set of input symbols which could follow the current parser # state and context, as given by {@link #getState} and {@link #getContext}, # respectively. # # @see ATN#getExpectedTokens(int, RuleContext) # def getExpectedTokens(self): return self._interp.atn.getExpectedTokens(self.state, self._ctx) def getExpectedTokensWithinCurrentRule(self): atn = self._interp.atn s = atn.states[self.state] return atn.nextTokens(s) # Get a rule's index (i.e., {@code RULE_ruleName} field) or -1 if not found.# def getRuleIndex(self, ruleName: str): ruleIndex = self.getRuleIndexMap().get(ruleName, None) if ruleIndex is not None: return ruleIndex else: return -1 # Return List<String> of the rule names in your parser instance # leading up to a call to the current rule. You could override if # you want more details such as the file/line info of where # in the ATN a rule is invoked. # # this is very useful for error messages. # def getRuleInvocationStack(self, p: RuleContext = None): if p is None: p = self._ctx stack = list() while p is not None: # compute what follows who invoked us ruleIndex = p.getRuleIndex() if ruleIndex < 0: stack.append("n/a") else: stack.append(self.ruleNames[ruleIndex]) p = p.parentCtx return stack # For debugging and other purposes.# def getDFAStrings(self): return [str(dfa) for dfa in self._interp.decisionToDFA] # For debugging and other purposes.# def dumpDFA(self): seenOne = False for i in range(0, len(self._interp.decisionToDFA)): dfa = self._interp.decisionToDFA[i] if len(dfa.states) > 0: if seenOne: print() print("Decision " + str(dfa.decision) + ":") print(dfa.toString(self.literalNames, self.symbolicNames), end='') seenOne = True def getSourceName(self): return self._input.sourceName # During a parse is sometimes useful to listen in on the rule entry and exit # events as well as token matches. self is for quick and dirty debugging. # def setTrace(self, trace: bool): if not trace: self.removeParseListener(self._tracer) self._tracer = None else: if self._tracer is not None: self.removeParseListener(self._tracer) self._tracer = TraceListener(self) self.addParseListener(self._tracer)