forked from jasder/antlr
rename BaseREcognizer as Parser
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 9781]
This commit is contained in:
parent
1b04195a2f
commit
3aeeb2b277
|
@ -32,7 +32,7 @@ import org.antlr.v4.runtime.misc.OrderedHashSet;
|
||||||
*/
|
*/
|
||||||
public interface ANTLRErrorStrategy {
|
public interface ANTLRErrorStrategy {
|
||||||
/** Report any kind of RecognitionException. */
|
/** Report any kind of RecognitionException. */
|
||||||
void reportError(@NotNull BaseRecognizer recognizer,
|
void reportError(@NotNull Parser recognizer,
|
||||||
@Nullable RecognitionException e)
|
@Nullable RecognitionException e)
|
||||||
throws RecognitionException;
|
throws RecognitionException;
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ public interface ANTLRErrorStrategy {
|
||||||
* "inserting" tokens, we need to specify what that implicitly created
|
* "inserting" tokens, we need to specify what that implicitly created
|
||||||
* token is. We use object, because it could be a tree node.
|
* token is. We use object, because it could be a tree node.
|
||||||
*/
|
*/
|
||||||
Token recoverInline(@NotNull BaseRecognizer recognizer)
|
Token recoverInline(@NotNull Parser recognizer)
|
||||||
throws RecognitionException;
|
throws RecognitionException;
|
||||||
|
|
||||||
/** Resynchronize the parser by consuming tokens until we find one
|
/** Resynchronize the parser by consuming tokens until we find one
|
||||||
|
@ -60,7 +60,7 @@ public interface ANTLRErrorStrategy {
|
||||||
* the current rule. The exception contains info you might want to
|
* the current rule. The exception contains info you might want to
|
||||||
* use to recover better.
|
* use to recover better.
|
||||||
*/
|
*/
|
||||||
void recover(@NotNull BaseRecognizer recognizer,
|
void recover(@NotNull Parser recognizer,
|
||||||
@Nullable RecognitionException e);
|
@Nullable RecognitionException e);
|
||||||
|
|
||||||
/** Make sure that the current lookahead symbol is consistent with
|
/** Make sure that the current lookahead symbol is consistent with
|
||||||
|
@ -90,14 +90,14 @@ public interface ANTLRErrorStrategy {
|
||||||
* turn off this functionality by simply overriding this method as
|
* turn off this functionality by simply overriding this method as
|
||||||
* a blank { }.
|
* a blank { }.
|
||||||
*/
|
*/
|
||||||
void sync(@NotNull BaseRecognizer recognizer);
|
void sync(@NotNull Parser recognizer);
|
||||||
|
|
||||||
/** Notify handler that parser has entered an error state. The
|
/** Notify handler that parser has entered an error state. The
|
||||||
* parser currently doesn't call this--the handler itself calls this
|
* parser currently doesn't call this--the handler itself calls this
|
||||||
* in report error methods. But, for symmetry with endErrorCondition,
|
* in report error methods. But, for symmetry with endErrorCondition,
|
||||||
* this method is in the interface.
|
* this method is in the interface.
|
||||||
*/
|
*/
|
||||||
void beginErrorCondition(@NotNull BaseRecognizer recognizer);
|
void beginErrorCondition(@NotNull Parser recognizer);
|
||||||
|
|
||||||
/** Is the parser in the process of recovering from an error? Upon
|
/** Is the parser in the process of recovering from an error? Upon
|
||||||
* a syntax error, the parser enters recovery mode and stays there until
|
* a syntax error, the parser enters recovery mode and stays there until
|
||||||
|
@ -105,13 +105,13 @@ public interface ANTLRErrorStrategy {
|
||||||
* avoid sending out spurious error messages. We only want one error
|
* avoid sending out spurious error messages. We only want one error
|
||||||
* message per syntax error
|
* message per syntax error
|
||||||
*/
|
*/
|
||||||
boolean inErrorRecoveryMode(@NotNull BaseRecognizer recognizer);
|
boolean inErrorRecoveryMode(@NotNull Parser recognizer);
|
||||||
|
|
||||||
/** Reset the error handler. Call this when the parser
|
/** Reset the error handler. Call this when the parser
|
||||||
* matches a valid token (indicating no longer in recovery mode)
|
* matches a valid token (indicating no longer in recovery mode)
|
||||||
* and from its own reset method.
|
* and from its own reset method.
|
||||||
*/
|
*/
|
||||||
void endErrorCondition(@NotNull BaseRecognizer recognizer);
|
void endErrorCondition(@NotNull Parser recognizer);
|
||||||
|
|
||||||
/** Called when the parser detects a true ambiguity: an input sequence can be matched
|
/** Called when the parser detects a true ambiguity: an input sequence can be matched
|
||||||
* literally by two or more pass through the grammar. ANTLR resolves the ambiguity in
|
* literally by two or more pass through the grammar. ANTLR resolves the ambiguity in
|
||||||
|
@ -120,7 +120,7 @@ public interface ANTLRErrorStrategy {
|
||||||
* that can match the input sequence. This method is only called when we are parsing with
|
* that can match the input sequence. This method is only called when we are parsing with
|
||||||
* full context.
|
* full context.
|
||||||
*/
|
*/
|
||||||
void reportAmbiguity(@NotNull BaseRecognizer recognizer,
|
void reportAmbiguity(@NotNull Parser recognizer,
|
||||||
DFA dfa, int startIndex, int stopIndex, @NotNull IntervalSet ambigAlts,
|
DFA dfa, int startIndex, int stopIndex, @NotNull IntervalSet ambigAlts,
|
||||||
@NotNull OrderedHashSet<ATNConfig> configs);
|
@NotNull OrderedHashSet<ATNConfig> configs);
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ public interface ANTLRErrorStrategy {
|
||||||
// @NotNull OrderedHashSet<ATNConfig> configs);
|
// @NotNull OrderedHashSet<ATNConfig> configs);
|
||||||
|
|
||||||
|
|
||||||
void reportAttemptingFullContext(@NotNull BaseRecognizer recognizer,
|
void reportAttemptingFullContext(@NotNull Parser recognizer,
|
||||||
@NotNull DFA dfa,
|
@NotNull DFA dfa,
|
||||||
int startIndex, int stopIndex,
|
int startIndex, int stopIndex,
|
||||||
@NotNull OrderedHashSet<ATNConfig> configs);
|
@NotNull OrderedHashSet<ATNConfig> configs);
|
||||||
|
@ -145,7 +145,7 @@ public interface ANTLRErrorStrategy {
|
||||||
* is more complicated than Strong LL can handle. The parser moved up to full context
|
* is more complicated than Strong LL can handle. The parser moved up to full context
|
||||||
* parsing for that input sequence.
|
* parsing for that input sequence.
|
||||||
*/
|
*/
|
||||||
void reportContextSensitivity(@NotNull BaseRecognizer recognizer,
|
void reportContextSensitivity(@NotNull Parser recognizer,
|
||||||
@NotNull DFA dfa,
|
@NotNull DFA dfa,
|
||||||
int startIndex, int stopIndex,
|
int startIndex, int stopIndex,
|
||||||
@NotNull OrderedHashSet<ATNConfig> configs);
|
@NotNull OrderedHashSet<ATNConfig> configs);
|
||||||
|
@ -155,7 +155,7 @@ public interface ANTLRErrorStrategy {
|
||||||
* If there are fewer than n-1, then we don't know which make it alternative to protect
|
* If there are fewer than n-1, then we don't know which make it alternative to protect
|
||||||
* if the predicates fail.
|
* if the predicates fail.
|
||||||
*/
|
*/
|
||||||
void reportInsufficientPredicates(@NotNull BaseRecognizer recognizer,
|
void reportInsufficientPredicates(@NotNull Parser recognizer,
|
||||||
@NotNull DFA dfa,
|
@NotNull DFA dfa,
|
||||||
int startIndex, int stopIndex, @NotNull IntervalSet ambigAlts,
|
int startIndex, int stopIndex, @NotNull IntervalSet ambigAlts,
|
||||||
DecisionState decState,
|
DecisionState decState,
|
||||||
|
|
|
@ -39,7 +39,7 @@ public class BailErrorStrategy extends DefaultErrorStrategy {
|
||||||
* RuntimeException.
|
* RuntimeException.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void recover(BaseRecognizer recognizer, RecognitionException e) {
|
public void recover(Parser recognizer, RecognitionException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ public class BailErrorStrategy extends DefaultErrorStrategy {
|
||||||
* successfully recovers, it won't throw an exception.
|
* successfully recovers, it won't throw an exception.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Token recoverInline(BaseRecognizer recognizer)
|
public Token recoverInline(Parser recognizer)
|
||||||
throws RecognitionException
|
throws RecognitionException
|
||||||
{
|
{
|
||||||
throw new RuntimeException(new InputMismatchException(recognizer));
|
throw new RuntimeException(new InputMismatchException(recognizer));
|
||||||
|
@ -55,5 +55,5 @@ public class BailErrorStrategy extends DefaultErrorStrategy {
|
||||||
|
|
||||||
/** Make sure we don't attempt to recover from problems in subrules. */
|
/** Make sure we don't attempt to recover from problems in subrules. */
|
||||||
@Override
|
@Override
|
||||||
public void sync(BaseRecognizer recognizer) { }
|
public void sync(Parser recognizer) { }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,473 +0,0 @@
|
||||||
/*
|
|
||||||
[The "BSD license"]
|
|
||||||
Copyright (c) 2011 Terence Parr
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions
|
|
||||||
are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
3. The name of the author may not be used to endorse or promote products
|
|
||||||
derived from this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
package org.antlr.v4.runtime;
|
|
||||||
|
|
||||||
import org.antlr.v4.runtime.atn.*;
|
|
||||||
import org.antlr.v4.runtime.dfa.DFA;
|
|
||||||
import org.antlr.v4.runtime.misc.IntervalSet;
|
|
||||||
import org.antlr.v4.runtime.misc.Nullable;
|
|
||||||
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/** A generic recognizer that can handle recognizers generated from
|
|
||||||
* parser and tree grammars. This is all the parsing
|
|
||||||
* support code essentially; most of it is error recovery stuff and
|
|
||||||
* backtracking.
|
|
||||||
*
|
|
||||||
* TODO: rename / reorg with parser
|
|
||||||
*/
|
|
||||||
public abstract class BaseRecognizer extends Recognizer<Token, v2ParserATNSimulator<Token>> {
|
|
||||||
public static final String NEXT_TOKEN_RULE_NAME = "nextToken";
|
|
||||||
|
|
||||||
protected TokenStream _input;
|
|
||||||
|
|
||||||
/** The RuleContext object for the currently executing rule. This
|
|
||||||
* must be non-null during parsing, but is initially null.
|
|
||||||
* When somebody calls the start rule, this gets set to the
|
|
||||||
* root context.
|
|
||||||
*/
|
|
||||||
protected ParserRuleContext<Token> _ctx;
|
|
||||||
|
|
||||||
protected boolean buildParseTrees;
|
|
||||||
protected boolean traceATNStates;
|
|
||||||
|
|
||||||
/** If the listener is non-null, trigger enter and exit rule events
|
|
||||||
* *during* the parse. This is typically done only when not building
|
|
||||||
* parse trees for later visiting. We either trigger events during
|
|
||||||
* the parse or during tree walks later. Both could be done.
|
|
||||||
* Not intended for tree parsing but would work.
|
|
||||||
*/
|
|
||||||
protected ParseTreeListener<Token> _listener;
|
|
||||||
|
|
||||||
/** Did the recognizer encounter a syntax error? Track how many. */
|
|
||||||
protected int syntaxErrors = 0;
|
|
||||||
|
|
||||||
public BaseRecognizer(IntStream input) {
|
|
||||||
setInputStream(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** reset the parser's state */
|
|
||||||
public void reset() {
|
|
||||||
if ( getInputStream()!=null ) getInputStream().seek(0);
|
|
||||||
_errHandler.endErrorCondition(this);
|
|
||||||
_ctx = null;
|
|
||||||
syntaxErrors = 0;
|
|
||||||
ATNSimulator interpreter = getInterpreter();
|
|
||||||
if (interpreter != null) {
|
|
||||||
interpreter.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Match current input symbol against ttype. Attempt
|
|
||||||
* single token insertion or deletion error recovery. If
|
|
||||||
* that fails, throw MismatchedTokenException.
|
|
||||||
*/
|
|
||||||
public Token match(int ttype) throws RecognitionException {
|
|
||||||
// System.out.println("match "+((TokenStream)input).LT(1)+" vs expected "+ttype);
|
|
||||||
Token currentSymbol = getCurrentToken();
|
|
||||||
if ( getInputStream().LA(1)==ttype ) {
|
|
||||||
_errHandler.endErrorCondition(this);
|
|
||||||
consume();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
currentSymbol = _errHandler.recoverInline(this);
|
|
||||||
if ( buildParseTrees && currentSymbol instanceof Token &&
|
|
||||||
((Token)currentSymbol).getTokenIndex()==-1 )
|
|
||||||
{
|
|
||||||
// we must have conjured up a new token during single token insertion
|
|
||||||
// if it's not the current symbol
|
|
||||||
_ctx.addErrorNode((Token)currentSymbol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return currentSymbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Track the RuleContext objects during the parse and hook them up
|
|
||||||
* using the children list so that it forms a parse tree.
|
|
||||||
* The RuleContext returned from the start rule represents the root
|
|
||||||
* of the parse tree.
|
|
||||||
*
|
|
||||||
* To built parse trees, all we have to do is put a hook in setState()
|
|
||||||
* and enterRule(). In setState(), we add tokens to the current context
|
|
||||||
* as children. By the time we get to enterRule(), we are already
|
|
||||||
* in an invoked rule so we add this context as a child of the parent
|
|
||||||
* (invoking) context. Simple and effective.
|
|
||||||
*
|
|
||||||
* Note that if we are not building parse trees, rule contexts
|
|
||||||
* only point upwards. When a rule exits, it returns the context
|
|
||||||
* but that gets garbage collected if nobody holds a reference.
|
|
||||||
* It points upwards but nobody points at it.
|
|
||||||
*
|
|
||||||
* When we build parse trees, we are adding all of these contexts to
|
|
||||||
* somebody's children list. Contexts are then not candidates
|
|
||||||
* for garbage collection.
|
|
||||||
*/
|
|
||||||
public void setBuildParseTree(boolean buildParseTrees) {
|
|
||||||
this.buildParseTrees = buildParseTrees;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getBuildParseTree() {
|
|
||||||
return buildParseTrees;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTraceATNStates(boolean traceATNStates) {
|
|
||||||
this.traceATNStates = traceATNStates;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getTraceATNStates() {
|
|
||||||
return traceATNStates;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ParseTreeListener<Token> getListener() {
|
|
||||||
return _listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setListener(ParseTreeListener<Token> listener) {
|
|
||||||
this._listener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get number of recognition errors (lexer, parser, tree parser). Each
|
|
||||||
* recognizer tracks its own number. So parser and lexer each have
|
|
||||||
* separate count. Does not count the spurious errors found between
|
|
||||||
* an error and next valid token match
|
|
||||||
*
|
|
||||||
* See also reportError()
|
|
||||||
*/
|
|
||||||
public int getNumberOfSyntaxErrors() {
|
|
||||||
return syntaxErrors;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TokenStream getInputStream() { return getTokenStream(); }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void setInputStream(IntStream input) {
|
|
||||||
setTokenStream((TokenStream)input);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TokenStream getTokenStream() {
|
|
||||||
return _input;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set the token stream and reset the parser */
|
|
||||||
public void setTokenStream(TokenStream input) {
|
|
||||||
this._input = null;
|
|
||||||
reset();
|
|
||||||
this._input = input;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getInputString(int start) {
|
|
||||||
return getInputString(start, getInputStream().index());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getInputString(int start, int stop) {
|
|
||||||
SymbolStream<Token> input = getInputStream();
|
|
||||||
if ( input instanceof TokenStream ) {
|
|
||||||
return ((TokenStream)input).toString(start,stop);
|
|
||||||
}
|
|
||||||
return "n/a";
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Match needs to return the current input symbol, which gets put
|
|
||||||
* into the label for the associated token ref; e.g., x=ID.
|
|
||||||
*/
|
|
||||||
public Token getCurrentToken() {
|
|
||||||
return _input.LT(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void notifyListeners(String msg) {
|
|
||||||
notifyListeners(getCurrentToken(), msg, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void notifyListeners(Token offendingToken, String msg,
|
|
||||||
@Nullable RecognitionException e)
|
|
||||||
{
|
|
||||||
int line = -1;
|
|
||||||
int charPositionInLine = -1;
|
|
||||||
if (offendingToken instanceof Token) {
|
|
||||||
line = ((Token) offendingToken).getLine();
|
|
||||||
charPositionInLine = ((Token) offendingToken).getCharPositionInLine();
|
|
||||||
}
|
|
||||||
ANTLRErrorListener<Token>[] listeners = getListeners();
|
|
||||||
if ( listeners.length == 0 ) {
|
|
||||||
System.err.println("line "+line+":"+charPositionInLine+" "+msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (ANTLRErrorListener<Token> pl : listeners) {
|
|
||||||
pl.error(this, offendingToken, line, charPositionInLine, msg, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void enterOuterAlt(ParserRuleContext<Token> localctx, int altNum) {
|
|
||||||
// if we have new localctx, make sure we replace existing ctx
|
|
||||||
// that is previous child of parse tree
|
|
||||||
if ( buildParseTrees && _ctx != localctx ) {
|
|
||||||
ParserRuleContext parent = (ParserRuleContext)_ctx.parent;
|
|
||||||
parent.removeLastChild();
|
|
||||||
if ( parent!=null ) parent.addChild(localctx);
|
|
||||||
}
|
|
||||||
_ctx = localctx;
|
|
||||||
_ctx.altNum = altNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Consume the current symbol and return it. E.g., given the following
|
|
||||||
* input with A being the current lookahead symbol:
|
|
||||||
*
|
|
||||||
* A B
|
|
||||||
* ^
|
|
||||||
*
|
|
||||||
* this function moves the cursor to B and returns A.
|
|
||||||
*
|
|
||||||
* If the parser is creating parse trees, the current symbol
|
|
||||||
* would also be added as a child to the current context (node).
|
|
||||||
*
|
|
||||||
* Trigger listener events if there's a listener.
|
|
||||||
*/
|
|
||||||
public Token consume() {
|
|
||||||
Token o = getCurrentToken();
|
|
||||||
getInputStream().consume();
|
|
||||||
if ( buildParseTrees ) {
|
|
||||||
// TODO: tree parsers?
|
|
||||||
if ( _errHandler.inErrorRecoveryMode(this) ) {
|
|
||||||
// System.out.println("consume in error recovery mode for "+o);
|
|
||||||
_ctx.addErrorNode((Token) o);
|
|
||||||
}
|
|
||||||
else _ctx.addChild((Token)o);
|
|
||||||
}
|
|
||||||
if ( _listener != null) _listener.visitTerminal(o);
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addContextToParseTree() {
|
|
||||||
ParserRuleContext parent = (ParserRuleContext)_ctx.parent;
|
|
||||||
// add current context to parent if we have a parent
|
|
||||||
if ( parent!=null ) {
|
|
||||||
parent.addChild(_ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Always called by generated parsers upon entry to a rule.
|
|
||||||
* This occurs after the new context has been pushed. Access field
|
|
||||||
* _ctx get the current context.
|
|
||||||
*
|
|
||||||
* This is flexible because users do not have to regenerate parsers
|
|
||||||
* to get trace facilities.
|
|
||||||
*/
|
|
||||||
public void enterRule(ParserRuleContext<Token> localctx, int ruleIndex) {
|
|
||||||
_ctx = localctx;
|
|
||||||
_ctx.start = _input.LT(1);
|
|
||||||
_ctx.ruleIndex = ruleIndex;
|
|
||||||
if ( buildParseTrees ) addContextToParseTree();
|
|
||||||
if ( _listener != null) {
|
|
||||||
_listener.enterEveryRule(_ctx);
|
|
||||||
_ctx.enterRule(_listener);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void exitRule(int ruleIndex) {
|
|
||||||
// trigger event on _ctx, before it reverts to parent
|
|
||||||
if ( _listener != null) {
|
|
||||||
_ctx.exitRule(_listener);
|
|
||||||
_listener.exitEveryRule(_ctx);
|
|
||||||
}
|
|
||||||
_ctx = (ParserRuleContext<Token>)_ctx.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ParserRuleContext<Token> getInvokingContext(int ruleIndex) {
|
|
||||||
ParserRuleContext<Token> p = _ctx;
|
|
||||||
while ( p!=null ) {
|
|
||||||
if ( p.getRuleIndex() == ruleIndex ) return p;
|
|
||||||
p = (ParserRuleContext<Token>)p.parent;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ParserRuleContext<Token> getContext() {
|
|
||||||
return _ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean inContext(String context) {
|
|
||||||
// TODO: useful in parser?
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isExpectedToken(int symbol) {
|
|
||||||
// return getInterpreter().atn.nextTokens(_ctx);
|
|
||||||
ATN atn = getInterpreter().atn;
|
|
||||||
ParserRuleContext ctx = _ctx;
|
|
||||||
ATNState s = atn.states.get(ctx.s);
|
|
||||||
IntervalSet following = atn.nextTokens(s);
|
|
||||||
if (following.contains(symbol)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// System.out.println("following "+s+"="+following);
|
|
||||||
if ( !following.contains(Token.EPSILON) ) return false;
|
|
||||||
|
|
||||||
while ( ctx!=null && ctx.invokingState>=0 && following.contains(Token.EPSILON) ) {
|
|
||||||
ATNState invokingState = atn.states.get(ctx.invokingState);
|
|
||||||
RuleTransition rt = (RuleTransition)invokingState.transition(0);
|
|
||||||
following = atn.nextTokens(rt.followState);
|
|
||||||
if (following.contains(symbol)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = (ParserRuleContext)ctx.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( following.contains(Token.EPSILON) && symbol == Token.EOF ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Compute the set of valid tokens reachable from the current
|
|
||||||
* position in the parse.
|
|
||||||
*/
|
|
||||||
public IntervalSet getExpectedTokens() {
|
|
||||||
ATN atn = getInterpreter().atn;
|
|
||||||
ParserRuleContext ctx = _ctx;
|
|
||||||
ATNState s = atn.states.get(ctx.s);
|
|
||||||
IntervalSet following = atn.nextTokens(s);
|
|
||||||
// System.out.println("following "+s+"="+following);
|
|
||||||
if ( !following.contains(Token.EPSILON) ) return following;
|
|
||||||
IntervalSet expected = new IntervalSet();
|
|
||||||
expected.addAll(following);
|
|
||||||
expected.remove(Token.EPSILON);
|
|
||||||
while ( ctx!=null && ctx.invokingState>=0 && following.contains(Token.EPSILON) ) {
|
|
||||||
ATNState invokingState = atn.states.get(ctx.invokingState);
|
|
||||||
RuleTransition rt = (RuleTransition)invokingState.transition(0);
|
|
||||||
following = atn.nextTokens(rt.followState);
|
|
||||||
expected.addAll(following);
|
|
||||||
expected.remove(Token.EPSILON);
|
|
||||||
ctx = (ParserRuleContext)ctx.parent;
|
|
||||||
}
|
|
||||||
if ( following.contains(Token.EPSILON) ) {
|
|
||||||
expected.add(Token.EOF);
|
|
||||||
}
|
|
||||||
return expected;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IntervalSet getExpectedTokensWithinCurrentRule() {
|
|
||||||
ATN atn = getInterpreter().atn;
|
|
||||||
ATNState s = atn.states.get(_ctx.s);
|
|
||||||
return atn.nextTokens(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
// /** Compute the set of valid tokens reachable from the current
|
|
||||||
// * position in the parse.
|
|
||||||
// */
|
|
||||||
// public IntervalSet nextTokens(@NotNull RuleContext ctx) {
|
|
||||||
// ATN atn = getInterpreter().atn;
|
|
||||||
// ATNState s = atn.states.get(ctx.s);
|
|
||||||
// if ( s == null ) return null;
|
|
||||||
// return atn.nextTokens(s, ctx);
|
|
||||||
// }
|
|
||||||
|
|
||||||
/** 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.
|
|
||||||
*/
|
|
||||||
public List<String> getRuleInvocationStack() {
|
|
||||||
String[] ruleNames = getRuleNames();
|
|
||||||
List<String> stack = new ArrayList<String>();
|
|
||||||
RuleContext p = _ctx;
|
|
||||||
while ( p!=null ) {
|
|
||||||
// compute what follows who invoked us
|
|
||||||
stack.add(ruleNames[p.getRuleIndex()]);
|
|
||||||
p = p.parent;
|
|
||||||
}
|
|
||||||
return stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** For debugging and other purposes, might want the grammar name.
|
|
||||||
* Have ANTLR generate an implementation for this method.
|
|
||||||
*/
|
|
||||||
public String getGrammarFileName() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** For debugging and other purposes */
|
|
||||||
public List<String> getDFAStrings() {
|
|
||||||
List<String> s = new ArrayList<String>();
|
|
||||||
for (int d = 0; d < _interp.decisionToDFA.length; d++) {
|
|
||||||
DFA dfa = _interp.decisionToDFA[d];
|
|
||||||
s.add( dfa.toString(getTokenNames()) );
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** For debugging and other purposes */
|
|
||||||
public void dumpDFA() {
|
|
||||||
boolean seenOne = false;
|
|
||||||
for (int d = 0; d < _interp.decisionToDFA.length; d++) {
|
|
||||||
DFA dfa = _interp.decisionToDFA[d];
|
|
||||||
if ( dfa!=null ) {
|
|
||||||
if ( seenOne ) System.out.println();
|
|
||||||
System.out.println("Decision " + dfa.decision + ":");
|
|
||||||
System.out.print(dfa.toString(getTokenNames()));
|
|
||||||
seenOne = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSourceName() {
|
|
||||||
return _input.getSourceName();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A convenience method for use most often with template rewrites.
|
|
||||||
* Convert a List<Token> to List<String>
|
|
||||||
*/
|
|
||||||
public List<String> toStrings(List<? extends Token> tokens) {
|
|
||||||
if ( tokens==null ) return null;
|
|
||||||
List<String> strings = new ArrayList<String>(tokens.size());
|
|
||||||
for (int i=0; i<tokens.size(); i++) {
|
|
||||||
strings.add(tokens.get(i).getText());
|
|
||||||
}
|
|
||||||
return strings;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Indicate that the recognizer has changed internal state that is
|
|
||||||
* consistent with the ATN state passed in. This way we always know
|
|
||||||
* where we are in the ATN as the parser goes along. The rule
|
|
||||||
* context objects form a stack that lets us see the stack of
|
|
||||||
* invoking rules. Combine this and we have complete ATN
|
|
||||||
* configuration information.
|
|
||||||
*/
|
|
||||||
public void setState(int atnState) {
|
|
||||||
// System.err.println("setState "+atnState);
|
|
||||||
_ctx.s = atnState;
|
|
||||||
if ( traceATNStates ) _ctx.trace(atnState);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -56,24 +56,24 @@ public class DefaultErrorStrategy implements ANTLRErrorStrategy {
|
||||||
protected IntervalSet lastErrorStates;
|
protected IntervalSet lastErrorStates;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beginErrorCondition(BaseRecognizer recognizer) {
|
public void beginErrorCondition(Parser recognizer) {
|
||||||
errorRecoveryMode = true;
|
errorRecoveryMode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean inErrorRecoveryMode(BaseRecognizer recognizer) {
|
public boolean inErrorRecoveryMode(Parser recognizer) {
|
||||||
return errorRecoveryMode;
|
return errorRecoveryMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void endErrorCondition(BaseRecognizer recognizer) {
|
public void endErrorCondition(Parser recognizer) {
|
||||||
errorRecoveryMode = false;
|
errorRecoveryMode = false;
|
||||||
lastErrorStates = null;
|
lastErrorStates = null;
|
||||||
lastErrorIndex = -1;
|
lastErrorIndex = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reportError(BaseRecognizer recognizer,
|
public void reportError(Parser recognizer,
|
||||||
RecognitionException e)
|
RecognitionException e)
|
||||||
throws RecognitionException
|
throws RecognitionException
|
||||||
{
|
{
|
||||||
|
@ -106,7 +106,7 @@ public class DefaultErrorStrategy implements ANTLRErrorStrategy {
|
||||||
* token that the match() routine could not recover from.
|
* token that the match() routine could not recover from.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void recover(BaseRecognizer recognizer, RecognitionException e) {
|
public void recover(Parser recognizer, RecognitionException e) {
|
||||||
// System.out.println("recover in "+recognizer.getRuleInvocationStack()+
|
// System.out.println("recover in "+recognizer.getRuleInvocationStack()+
|
||||||
// " index="+recognizer.getInputStream().index()+
|
// " index="+recognizer.getInputStream().index()+
|
||||||
// ", lastErrorIndex="+
|
// ", lastErrorIndex="+
|
||||||
|
@ -146,7 +146,7 @@ public class DefaultErrorStrategy implements ANTLRErrorStrategy {
|
||||||
* We opt to stay in the loop as long as possible.
|
* We opt to stay in the loop as long as possible.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void sync(BaseRecognizer recognizer) {
|
public void sync(Parser recognizer) {
|
||||||
ATNState s = recognizer.getInterpreter().atn.states.get(recognizer._ctx.s);
|
ATNState s = recognizer.getInterpreter().atn.states.get(recognizer._ctx.s);
|
||||||
// System.err.println("sync @ "+s.stateNumber+"="+s.getClass().getSimpleName());
|
// System.err.println("sync @ "+s.stateNumber+"="+s.getClass().getSimpleName());
|
||||||
// If already recovering, don't try to sync
|
// If already recovering, don't try to sync
|
||||||
|
@ -184,7 +184,7 @@ public class DefaultErrorStrategy implements ANTLRErrorStrategy {
|
||||||
// do nothing if we can't identify the exact kind of ATN state
|
// do nothing if we can't identify the exact kind of ATN state
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reportNoViableAlternative(BaseRecognizer recognizer,
|
public void reportNoViableAlternative(Parser recognizer,
|
||||||
NoViableAltException e)
|
NoViableAltException e)
|
||||||
throws RecognitionException
|
throws RecognitionException
|
||||||
{
|
{
|
||||||
|
@ -201,7 +201,7 @@ public class DefaultErrorStrategy implements ANTLRErrorStrategy {
|
||||||
recognizer.notifyListeners((Token) e.offendingToken, msg, e);
|
recognizer.notifyListeners((Token) e.offendingToken, msg, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reportInputMismatch(BaseRecognizer recognizer,
|
public void reportInputMismatch(Parser recognizer,
|
||||||
InputMismatchException e)
|
InputMismatchException e)
|
||||||
throws RecognitionException
|
throws RecognitionException
|
||||||
{
|
{
|
||||||
|
@ -210,7 +210,7 @@ public class DefaultErrorStrategy implements ANTLRErrorStrategy {
|
||||||
recognizer.notifyListeners((Token)e.offendingToken, msg, e);
|
recognizer.notifyListeners((Token)e.offendingToken, msg, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reportFailedPredicate(BaseRecognizer recognizer,
|
public void reportFailedPredicate(Parser recognizer,
|
||||||
FailedPredicateException e)
|
FailedPredicateException e)
|
||||||
throws RecognitionException
|
throws RecognitionException
|
||||||
{
|
{
|
||||||
|
@ -219,7 +219,7 @@ public class DefaultErrorStrategy implements ANTLRErrorStrategy {
|
||||||
recognizer.notifyListeners((Token)e.offendingToken, msg, e);
|
recognizer.notifyListeners((Token)e.offendingToken, msg, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reportUnwantedToken(BaseRecognizer recognizer) {
|
public void reportUnwantedToken(Parser recognizer) {
|
||||||
if (errorRecoveryMode) return;
|
if (errorRecoveryMode) return;
|
||||||
recognizer.syntaxErrors++;
|
recognizer.syntaxErrors++;
|
||||||
beginErrorCondition(recognizer);
|
beginErrorCondition(recognizer);
|
||||||
|
@ -232,7 +232,7 @@ public class DefaultErrorStrategy implements ANTLRErrorStrategy {
|
||||||
recognizer.notifyListeners(t, msg, null);
|
recognizer.notifyListeners(t, msg, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reportMissingToken(BaseRecognizer recognizer) {
|
public void reportMissingToken(Parser recognizer) {
|
||||||
if (errorRecoveryMode) return;
|
if (errorRecoveryMode) return;
|
||||||
recognizer.syntaxErrors++;
|
recognizer.syntaxErrors++;
|
||||||
beginErrorCondition(recognizer);
|
beginErrorCondition(recognizer);
|
||||||
|
@ -275,7 +275,7 @@ public class DefaultErrorStrategy implements ANTLRErrorStrategy {
|
||||||
* reference in rule atom. It can assume that you forgot the ')'.
|
* reference in rule atom. It can assume that you forgot the ')'.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Token recoverInline(BaseRecognizer recognizer)
|
public Token recoverInline(Parser recognizer)
|
||||||
throws RecognitionException
|
throws RecognitionException
|
||||||
{
|
{
|
||||||
// SINGLE TOKEN DELETION
|
// SINGLE TOKEN DELETION
|
||||||
|
@ -297,7 +297,7 @@ public class DefaultErrorStrategy implements ANTLRErrorStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if next token is what we are looking for then "delete" this token
|
// if next token is what we are looking for then "delete" this token
|
||||||
public boolean singleTokenInsertion(BaseRecognizer recognizer) {
|
public boolean singleTokenInsertion(Parser recognizer) {
|
||||||
int currentSymbolType = recognizer.getInputStream().LA(1);
|
int currentSymbolType = recognizer.getInputStream().LA(1);
|
||||||
// if current token is consistent with what could come after current
|
// if current token is consistent with what could come after current
|
||||||
// ATN state, then we know we're missing a token; error recovery
|
// ATN state, then we know we're missing a token; error recovery
|
||||||
|
@ -313,7 +313,7 @@ public class DefaultErrorStrategy implements ANTLRErrorStrategy {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Token singleTokenDeletion(BaseRecognizer recognizer) {
|
public Token singleTokenDeletion(Parser recognizer) {
|
||||||
int nextTokenType = recognizer.getInputStream().LA(2);
|
int nextTokenType = recognizer.getInputStream().LA(2);
|
||||||
IntervalSet expecting = getExpectedTokens(recognizer);
|
IntervalSet expecting = getExpectedTokens(recognizer);
|
||||||
if ( expecting.contains(nextTokenType) ) {
|
if ( expecting.contains(nextTokenType) ) {
|
||||||
|
@ -352,7 +352,7 @@ public class DefaultErrorStrategy implements ANTLRErrorStrategy {
|
||||||
* If you change what tokens must be created by the lexer,
|
* If you change what tokens must be created by the lexer,
|
||||||
* override this method to create the appropriate tokens.
|
* override this method to create the appropriate tokens.
|
||||||
*/
|
*/
|
||||||
protected Token getMissingSymbol(BaseRecognizer recognizer) {
|
protected Token getMissingSymbol(Parser recognizer) {
|
||||||
Token currentSymbol = recognizer.getCurrentToken();
|
Token currentSymbol = recognizer.getCurrentToken();
|
||||||
if (!(currentSymbol instanceof Token)) {
|
if (!(currentSymbol instanceof Token)) {
|
||||||
throw new UnsupportedOperationException("This error strategy only supports Token symbols.");
|
throw new UnsupportedOperationException("This error strategy only supports Token symbols.");
|
||||||
|
@ -376,7 +376,7 @@ public class DefaultErrorStrategy implements ANTLRErrorStrategy {
|
||||||
return (Token)t;
|
return (Token)t;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IntervalSet getExpectedTokens(BaseRecognizer recognizer) {
|
public IntervalSet getExpectedTokens(Parser recognizer) {
|
||||||
return recognizer.getExpectedTokens();
|
return recognizer.getExpectedTokens();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,7 +520,7 @@ public class DefaultErrorStrategy implements ANTLRErrorStrategy {
|
||||||
* Like Grosch I implement context-sensitive FOLLOW sets that are combined
|
* Like Grosch I implement context-sensitive FOLLOW sets that are combined
|
||||||
* at run-time upon error to avoid overhead during parsing.
|
* at run-time upon error to avoid overhead during parsing.
|
||||||
*/
|
*/
|
||||||
protected IntervalSet getErrorRecoverySet(BaseRecognizer recognizer) {
|
protected IntervalSet getErrorRecoverySet(Parser recognizer) {
|
||||||
ATN atn = recognizer.getInterpreter().atn;
|
ATN atn = recognizer.getInterpreter().atn;
|
||||||
RuleContext ctx = recognizer._ctx;
|
RuleContext ctx = recognizer._ctx;
|
||||||
IntervalSet recoverSet = new IntervalSet();
|
IntervalSet recoverSet = new IntervalSet();
|
||||||
|
@ -538,7 +538,7 @@ public class DefaultErrorStrategy implements ANTLRErrorStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Consume tokens until one matches the given token set */
|
/** Consume tokens until one matches the given token set */
|
||||||
public void consumeUntil(BaseRecognizer recognizer, IntervalSet set) {
|
public void consumeUntil(Parser recognizer, IntervalSet set) {
|
||||||
// System.err.println("consumeUntil("+set.toString(recognizer.getTokenNames())+")");
|
// System.err.println("consumeUntil("+set.toString(recognizer.getTokenNames())+")");
|
||||||
int ttype = recognizer.getInputStream().LA(1);
|
int ttype = recognizer.getInputStream().LA(1);
|
||||||
while (ttype != Token.EOF && !set.contains(ttype) ) {
|
while (ttype != Token.EOF && !set.contains(ttype) ) {
|
||||||
|
@ -550,14 +550,14 @@ public class DefaultErrorStrategy implements ANTLRErrorStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reportAmbiguity(@NotNull BaseRecognizer recognizer,
|
public void reportAmbiguity(@NotNull Parser recognizer,
|
||||||
DFA dfa, int startIndex, int stopIndex, @NotNull IntervalSet ambigAlts,
|
DFA dfa, int startIndex, int stopIndex, @NotNull IntervalSet ambigAlts,
|
||||||
@NotNull OrderedHashSet<ATNConfig> configs)
|
@NotNull OrderedHashSet<ATNConfig> configs)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reportAttemptingFullContext(@NotNull BaseRecognizer recognizer,
|
public void reportAttemptingFullContext(@NotNull Parser recognizer,
|
||||||
@NotNull DFA dfa,
|
@NotNull DFA dfa,
|
||||||
int startIndex, int stopIndex,
|
int startIndex, int stopIndex,
|
||||||
@NotNull OrderedHashSet<ATNConfig> configs)
|
@NotNull OrderedHashSet<ATNConfig> configs)
|
||||||
|
@ -565,13 +565,13 @@ public class DefaultErrorStrategy implements ANTLRErrorStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reportContextSensitivity(@NotNull BaseRecognizer recognizer, @NotNull DFA dfa,
|
public void reportContextSensitivity(@NotNull Parser recognizer, @NotNull DFA dfa,
|
||||||
int startIndex, int stopIndex, @NotNull OrderedHashSet<ATNConfig> configs)
|
int startIndex, int stopIndex, @NotNull OrderedHashSet<ATNConfig> configs)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reportInsufficientPredicates(@NotNull BaseRecognizer recognizer,
|
public void reportInsufficientPredicates(@NotNull Parser recognizer,
|
||||||
@NotNull DFA dfa,
|
@NotNull DFA dfa,
|
||||||
int startIndex, int stopIndex,
|
int startIndex, int stopIndex,
|
||||||
@NotNull IntervalSet ambigAlts,
|
@NotNull IntervalSet ambigAlts,
|
||||||
|
|
|
@ -41,7 +41,7 @@ import java.util.Arrays;
|
||||||
|
|
||||||
public class DiagnosticErrorStrategy extends DefaultErrorStrategy {
|
public class DiagnosticErrorStrategy extends DefaultErrorStrategy {
|
||||||
@Override
|
@Override
|
||||||
public void reportAmbiguity(@NotNull BaseRecognizer recognizer,
|
public void reportAmbiguity(@NotNull Parser recognizer,
|
||||||
DFA dfa, int startIndex, int stopIndex, @NotNull IntervalSet ambigAlts,
|
DFA dfa, int startIndex, int stopIndex, @NotNull IntervalSet ambigAlts,
|
||||||
@NotNull OrderedHashSet<ATNConfig> configs)
|
@NotNull OrderedHashSet<ATNConfig> configs)
|
||||||
{
|
{
|
||||||
|
@ -50,7 +50,7 @@ public class DiagnosticErrorStrategy extends DefaultErrorStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reportAttemptingFullContext(@NotNull BaseRecognizer recognizer,
|
public void reportAttemptingFullContext(@NotNull Parser recognizer,
|
||||||
@NotNull DFA dfa,
|
@NotNull DFA dfa,
|
||||||
int startIndex, int stopIndex,
|
int startIndex, int stopIndex,
|
||||||
@NotNull OrderedHashSet<ATNConfig> configs)
|
@NotNull OrderedHashSet<ATNConfig> configs)
|
||||||
|
@ -60,7 +60,7 @@ public class DiagnosticErrorStrategy extends DefaultErrorStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reportContextSensitivity(@NotNull BaseRecognizer recognizer, @NotNull DFA dfa,
|
public void reportContextSensitivity(@NotNull Parser recognizer, @NotNull DFA dfa,
|
||||||
int startIndex, int stopIndex, @NotNull OrderedHashSet<ATNConfig> configs)
|
int startIndex, int stopIndex, @NotNull OrderedHashSet<ATNConfig> configs)
|
||||||
{
|
{
|
||||||
recognizer.notifyListeners("reportContextSensitivity d="+dfa.decision +": "+ configs + ", input='" +
|
recognizer.notifyListeners("reportContextSensitivity d="+dfa.decision +": "+ configs + ", input='" +
|
||||||
|
@ -68,7 +68,7 @@ public class DiagnosticErrorStrategy extends DefaultErrorStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reportInsufficientPredicates(@NotNull BaseRecognizer recognizer,
|
public void reportInsufficientPredicates(@NotNull Parser recognizer,
|
||||||
@NotNull DFA dfa,
|
@NotNull DFA dfa,
|
||||||
int startIndex, int stopIndex,
|
int startIndex, int stopIndex,
|
||||||
@NotNull IntervalSet ambigAlts,
|
@NotNull IntervalSet ambigAlts,
|
||||||
|
|
|
@ -42,11 +42,11 @@ public class FailedPredicateException extends RecognitionException {
|
||||||
public int predIndex;
|
public int predIndex;
|
||||||
public String msg;
|
public String msg;
|
||||||
|
|
||||||
public FailedPredicateException(BaseRecognizer recognizer) {
|
public FailedPredicateException(Parser recognizer) {
|
||||||
this(recognizer, null);
|
this(recognizer, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FailedPredicateException(BaseRecognizer recognizer, @Nullable String msg) {
|
public FailedPredicateException(Parser recognizer, @Nullable String msg) {
|
||||||
super(recognizer, recognizer.getInputStream(), recognizer._ctx);
|
super(recognizer, recognizer.getInputStream(), recognizer._ctx);
|
||||||
ATNState s = recognizer.getInterpreter().atn.states.get(recognizer._ctx.s);
|
ATNState s = recognizer.getInterpreter().atn.states.get(recognizer._ctx.s);
|
||||||
PredicateTransition trans = (PredicateTransition)s.transition(0);
|
PredicateTransition trans = (PredicateTransition)s.transition(0);
|
||||||
|
|
|
@ -4,7 +4,7 @@ package org.antlr.v4.runtime;
|
||||||
* when the current input does not match the expected token or tree node.
|
* when the current input does not match the expected token or tree node.
|
||||||
*/
|
*/
|
||||||
public class InputMismatchException extends RecognitionException {
|
public class InputMismatchException extends RecognitionException {
|
||||||
public InputMismatchException(BaseRecognizer recognizer) {
|
public InputMismatchException(Parser recognizer) {
|
||||||
super(recognizer, recognizer.getInputStream(), recognizer._ctx);
|
super(recognizer, recognizer.getInputStream(), recognizer._ctx);
|
||||||
Token la = recognizer.getCurrentToken();
|
Token la = recognizer.getCurrentToken();
|
||||||
this.offendingToken = la;
|
this.offendingToken = la;
|
||||||
|
|
|
@ -45,7 +45,7 @@ public class NoViableAltException extends RecognitionException {
|
||||||
*/
|
*/
|
||||||
public Token startToken;
|
public Token startToken;
|
||||||
|
|
||||||
public <Symbol extends Token> NoViableAltException(BaseRecognizer recognizer) { // LL(1) error
|
public <Symbol extends Token> NoViableAltException(Parser recognizer) { // LL(1) error
|
||||||
this(recognizer,recognizer.getInputStream(),
|
this(recognizer,recognizer.getInputStream(),
|
||||||
recognizer.getCurrentToken(),
|
recognizer.getCurrentToken(),
|
||||||
recognizer.getCurrentToken(),
|
recognizer.getCurrentToken(),
|
||||||
|
@ -53,7 +53,7 @@ public class NoViableAltException extends RecognitionException {
|
||||||
recognizer._ctx);
|
recognizer._ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <Symbol> NoViableAltException(BaseRecognizer recognizer,
|
public <Symbol> NoViableAltException(Parser recognizer,
|
||||||
SymbolStream<Symbol> input,
|
SymbolStream<Symbol> input,
|
||||||
Token startToken,
|
Token startToken,
|
||||||
Token offendingToken,
|
Token offendingToken,
|
||||||
|
|
|
@ -1,44 +1,467 @@
|
||||||
/*
|
/*
|
||||||
[The "BSD license"]
|
[The "BSD license"]
|
||||||
Copyright (c) 2011 Terence Parr
|
Copyright (c) 2011 Terence Parr
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions
|
modification, are permitted provided that the following conditions
|
||||||
are met:
|
are met:
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright
|
1. Redistributions of source code must retain the above copyright
|
||||||
notice, this list of conditions and the following disclaimer.
|
notice, this list of conditions and the following disclaimer.
|
||||||
2. Redistributions in binary form must reproduce the above copyright
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
notice, this list of conditions and the following disclaimer in the
|
notice, this list of conditions and the following disclaimer in the
|
||||||
documentation and/or other materials provided with the distribution.
|
documentation and/or other materials provided with the distribution.
|
||||||
3. The name of the author may not be used to endorse or promote products
|
3. The name of the author may not be used to endorse or promote products
|
||||||
derived from this software without specific prior written permission.
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
package org.antlr.v4.runtime;
|
package org.antlr.v4.runtime;
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.atn.*;
|
||||||
|
import org.antlr.v4.runtime.dfa.DFA;
|
||||||
|
import org.antlr.v4.runtime.misc.IntervalSet;
|
||||||
|
import org.antlr.v4.runtime.misc.Nullable;
|
||||||
|
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
||||||
|
|
||||||
/** A parser for TokenStreams. "parser grammars" result in a subclass
|
import java.util.ArrayList;
|
||||||
* of this.
|
import java.util.List;
|
||||||
*/
|
|
||||||
public class Parser extends BaseRecognizer {
|
/** This is all the parsing support code essentially; most of it is error recovery stuff. */
|
||||||
public Parser(TokenStream input) {
|
public abstract class Parser extends Recognizer<Token, v2ParserATNSimulator<Token>> {
|
||||||
super(input);
|
public static final String NEXT_TOKEN_RULE_NAME = "nextToken";
|
||||||
|
|
||||||
|
protected TokenStream _input;
|
||||||
|
|
||||||
|
/** The RuleContext object for the currently executing rule. This
|
||||||
|
* must be non-null during parsing, but is initially null.
|
||||||
|
* When somebody calls the start rule, this gets set to the
|
||||||
|
* root context.
|
||||||
|
*/
|
||||||
|
protected ParserRuleContext<Token> _ctx;
|
||||||
|
|
||||||
|
protected boolean buildParseTrees;
|
||||||
|
protected boolean traceATNStates;
|
||||||
|
|
||||||
|
/** If the listener is non-null, trigger enter and exit rule events
|
||||||
|
* *during* the parse. This is typically done only when not building
|
||||||
|
* parse trees for later visiting. We either trigger events during
|
||||||
|
* the parse or during tree walks later. Both could be done.
|
||||||
|
* Not intended for tree parsing but would work.
|
||||||
|
*/
|
||||||
|
protected ParseTreeListener<Token> _listener;
|
||||||
|
|
||||||
|
/** Did the recognizer encounter a syntax error? Track how many. */
|
||||||
|
protected int syntaxErrors = 0;
|
||||||
|
|
||||||
|
public Parser(IntStream input) {
|
||||||
|
setInputStream(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** reset the parser's state */
|
||||||
|
public void reset() {
|
||||||
|
if ( getInputStream()!=null ) getInputStream().seek(0);
|
||||||
|
_errHandler.endErrorCondition(this);
|
||||||
|
_ctx = null;
|
||||||
|
syntaxErrors = 0;
|
||||||
|
ATNSimulator interpreter = getInterpreter();
|
||||||
|
if (interpreter != null) {
|
||||||
|
interpreter.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Match current input symbol against ttype. Attempt
|
||||||
|
* single token insertion or deletion error recovery. If
|
||||||
|
* that fails, throw MismatchedTokenException.
|
||||||
|
*/
|
||||||
|
public Token match(int ttype) throws RecognitionException {
|
||||||
|
// System.out.println("match "+((TokenStream)input).LT(1)+" vs expected "+ttype);
|
||||||
|
Token currentSymbol = getCurrentToken();
|
||||||
|
if ( getInputStream().LA(1)==ttype ) {
|
||||||
|
_errHandler.endErrorCondition(this);
|
||||||
|
consume();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
currentSymbol = _errHandler.recoverInline(this);
|
||||||
|
if ( buildParseTrees && currentSymbol instanceof Token &&
|
||||||
|
((Token)currentSymbol).getTokenIndex()==-1 )
|
||||||
|
{
|
||||||
|
// we must have conjured up a new token during single token insertion
|
||||||
|
// if it's not the current symbol
|
||||||
|
_ctx.addErrorNode((Token)currentSymbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return currentSymbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Track the RuleContext objects during the parse and hook them up
|
||||||
|
* using the children list so that it forms a parse tree.
|
||||||
|
* The RuleContext returned from the start rule represents the root
|
||||||
|
* of the parse tree.
|
||||||
|
*
|
||||||
|
* To built parse trees, all we have to do is put a hook in setState()
|
||||||
|
* and enterRule(). In setState(), we add tokens to the current context
|
||||||
|
* as children. By the time we get to enterRule(), we are already
|
||||||
|
* in an invoked rule so we add this context as a child of the parent
|
||||||
|
* (invoking) context. Simple and effective.
|
||||||
|
*
|
||||||
|
* Note that if we are not building parse trees, rule contexts
|
||||||
|
* only point upwards. When a rule exits, it returns the context
|
||||||
|
* but that gets garbage collected if nobody holds a reference.
|
||||||
|
* It points upwards but nobody points at it.
|
||||||
|
*
|
||||||
|
* When we build parse trees, we are adding all of these contexts to
|
||||||
|
* somebody's children list. Contexts are then not candidates
|
||||||
|
* for garbage collection.
|
||||||
|
*/
|
||||||
|
public void setBuildParseTree(boolean buildParseTrees) {
|
||||||
|
this.buildParseTrees = buildParseTrees;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getBuildParseTree() {
|
||||||
|
return buildParseTrees;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTraceATNStates(boolean traceATNStates) {
|
||||||
|
this.traceATNStates = traceATNStates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getTraceATNStates() {
|
||||||
|
return traceATNStates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParseTreeListener<Token> getListener() {
|
||||||
|
return _listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setListener(ParseTreeListener<Token> listener) {
|
||||||
|
this._listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get number of recognition errors (lexer, parser, tree parser). Each
|
||||||
|
* recognizer tracks its own number. So parser and lexer each have
|
||||||
|
* separate count. Does not count the spurious errors found between
|
||||||
|
* an error and next valid token match
|
||||||
|
*
|
||||||
|
* See also reportError()
|
||||||
|
*/
|
||||||
|
public int getNumberOfSyntaxErrors() {
|
||||||
|
return syntaxErrors;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
public TokenStream getInputStream() { return getTokenStream(); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void setInputStream(IntStream input) {
|
||||||
|
setTokenStream((TokenStream)input);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TokenStream getTokenStream() {
|
||||||
|
return _input;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set the token stream and reset the parser */
|
||||||
|
public void setTokenStream(TokenStream input) {
|
||||||
|
this._input = null;
|
||||||
|
reset();
|
||||||
|
this._input = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInputString(int start) {
|
||||||
|
return getInputString(start, getInputStream().index());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInputString(int start, int stop) {
|
||||||
|
SymbolStream<Token> input = getInputStream();
|
||||||
|
if ( input instanceof TokenStream ) {
|
||||||
|
return ((TokenStream)input).toString(start,stop);
|
||||||
|
}
|
||||||
|
return "n/a";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Match needs to return the current input symbol, which gets put
|
||||||
|
* into the label for the associated token ref; e.g., x=ID.
|
||||||
|
*/
|
||||||
|
public Token getCurrentToken() {
|
||||||
|
return _input.LT(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void notifyListeners(String msg) {
|
||||||
|
notifyListeners(getCurrentToken(), msg, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void notifyListeners(Token offendingToken, String msg,
|
||||||
|
@Nullable RecognitionException e)
|
||||||
|
{
|
||||||
|
int line = -1;
|
||||||
|
int charPositionInLine = -1;
|
||||||
|
if (offendingToken instanceof Token) {
|
||||||
|
line = ((Token) offendingToken).getLine();
|
||||||
|
charPositionInLine = ((Token) offendingToken).getCharPositionInLine();
|
||||||
|
}
|
||||||
|
ANTLRErrorListener<Token>[] listeners = getListeners();
|
||||||
|
if ( listeners.length == 0 ) {
|
||||||
|
System.err.println("line "+line+":"+charPositionInLine+" "+msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (ANTLRErrorListener<Token> pl : listeners) {
|
||||||
|
pl.error(this, offendingToken, line, charPositionInLine, msg, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void enterOuterAlt(ParserRuleContext<Token> localctx, int altNum) {
|
||||||
|
// if we have new localctx, make sure we replace existing ctx
|
||||||
|
// that is previous child of parse tree
|
||||||
|
if ( buildParseTrees && _ctx != localctx ) {
|
||||||
|
ParserRuleContext parent = (ParserRuleContext)_ctx.parent;
|
||||||
|
parent.removeLastChild();
|
||||||
|
if ( parent!=null ) parent.addChild(localctx);
|
||||||
|
}
|
||||||
|
_ctx = localctx;
|
||||||
|
_ctx.altNum = altNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Consume the current symbol and return it. E.g., given the following
|
||||||
|
* input with A being the current lookahead symbol:
|
||||||
|
*
|
||||||
|
* A B
|
||||||
|
* ^
|
||||||
|
*
|
||||||
|
* this function moves the cursor to B and returns A.
|
||||||
|
*
|
||||||
|
* If the parser is creating parse trees, the current symbol
|
||||||
|
* would also be added as a child to the current context (node).
|
||||||
|
*
|
||||||
|
* Trigger listener events if there's a listener.
|
||||||
|
*/
|
||||||
|
public Token consume() {
|
||||||
|
Token o = getCurrentToken();
|
||||||
|
getInputStream().consume();
|
||||||
|
if ( buildParseTrees ) {
|
||||||
|
// TODO: tree parsers?
|
||||||
|
if ( _errHandler.inErrorRecoveryMode(this) ) {
|
||||||
|
// System.out.println("consume in error recovery mode for "+o);
|
||||||
|
_ctx.addErrorNode((Token) o);
|
||||||
|
}
|
||||||
|
else _ctx.addChild((Token)o);
|
||||||
|
}
|
||||||
|
if ( _listener != null) _listener.visitTerminal(o);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addContextToParseTree() {
|
||||||
|
ParserRuleContext parent = (ParserRuleContext)_ctx.parent;
|
||||||
|
// add current context to parent if we have a parent
|
||||||
|
if ( parent!=null ) {
|
||||||
|
parent.addChild(_ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Always called by generated parsers upon entry to a rule.
|
||||||
|
* This occurs after the new context has been pushed. Access field
|
||||||
|
* _ctx get the current context.
|
||||||
|
*
|
||||||
|
* This is flexible because users do not have to regenerate parsers
|
||||||
|
* to get trace facilities.
|
||||||
|
*/
|
||||||
|
public void enterRule(ParserRuleContext<Token> localctx, int ruleIndex) {
|
||||||
|
_ctx = localctx;
|
||||||
|
_ctx.start = _input.LT(1);
|
||||||
|
_ctx.ruleIndex = ruleIndex;
|
||||||
|
if ( buildParseTrees ) addContextToParseTree();
|
||||||
|
if ( _listener != null) {
|
||||||
|
_listener.enterEveryRule(_ctx);
|
||||||
|
_ctx.enterRule(_listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void exitRule(int ruleIndex) {
|
||||||
|
// trigger event on _ctx, before it reverts to parent
|
||||||
|
if ( _listener != null) {
|
||||||
|
_ctx.exitRule(_listener);
|
||||||
|
_listener.exitEveryRule(_ctx);
|
||||||
|
}
|
||||||
|
_ctx = (ParserRuleContext<Token>)_ctx.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParserRuleContext<Token> getInvokingContext(int ruleIndex) {
|
||||||
|
ParserRuleContext<Token> p = _ctx;
|
||||||
|
while ( p!=null ) {
|
||||||
|
if ( p.getRuleIndex() == ruleIndex ) return p;
|
||||||
|
p = (ParserRuleContext<Token>)p.parent;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParserRuleContext<Token> getContext() {
|
||||||
|
return _ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean inContext(String context) {
|
||||||
|
// TODO: useful in parser?
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isExpectedToken(int symbol) {
|
||||||
|
// return getInterpreter().atn.nextTokens(_ctx);
|
||||||
|
ATN atn = getInterpreter().atn;
|
||||||
|
ParserRuleContext ctx = _ctx;
|
||||||
|
ATNState s = atn.states.get(ctx.s);
|
||||||
|
IntervalSet following = atn.nextTokens(s);
|
||||||
|
if (following.contains(symbol)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// System.out.println("following "+s+"="+following);
|
||||||
|
if ( !following.contains(Token.EPSILON) ) return false;
|
||||||
|
|
||||||
|
while ( ctx!=null && ctx.invokingState>=0 && following.contains(Token.EPSILON) ) {
|
||||||
|
ATNState invokingState = atn.states.get(ctx.invokingState);
|
||||||
|
RuleTransition rt = (RuleTransition)invokingState.transition(0);
|
||||||
|
following = atn.nextTokens(rt.followState);
|
||||||
|
if (following.contains(symbol)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = (ParserRuleContext)ctx.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( following.contains(Token.EPSILON) && symbol == Token.EOF ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Compute the set of valid tokens reachable from the current
|
||||||
|
* position in the parse.
|
||||||
|
*/
|
||||||
|
public IntervalSet getExpectedTokens() {
|
||||||
|
ATN atn = getInterpreter().atn;
|
||||||
|
ParserRuleContext ctx = _ctx;
|
||||||
|
ATNState s = atn.states.get(ctx.s);
|
||||||
|
IntervalSet following = atn.nextTokens(s);
|
||||||
|
// System.out.println("following "+s+"="+following);
|
||||||
|
if ( !following.contains(Token.EPSILON) ) return following;
|
||||||
|
IntervalSet expected = new IntervalSet();
|
||||||
|
expected.addAll(following);
|
||||||
|
expected.remove(Token.EPSILON);
|
||||||
|
while ( ctx!=null && ctx.invokingState>=0 && following.contains(Token.EPSILON) ) {
|
||||||
|
ATNState invokingState = atn.states.get(ctx.invokingState);
|
||||||
|
RuleTransition rt = (RuleTransition)invokingState.transition(0);
|
||||||
|
following = atn.nextTokens(rt.followState);
|
||||||
|
expected.addAll(following);
|
||||||
|
expected.remove(Token.EPSILON);
|
||||||
|
ctx = (ParserRuleContext)ctx.parent;
|
||||||
|
}
|
||||||
|
if ( following.contains(Token.EPSILON) ) {
|
||||||
|
expected.add(Token.EOF);
|
||||||
|
}
|
||||||
|
return expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntervalSet getExpectedTokensWithinCurrentRule() {
|
||||||
|
ATN atn = getInterpreter().atn;
|
||||||
|
ATNState s = atn.states.get(_ctx.s);
|
||||||
|
return atn.nextTokens(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// /** Compute the set of valid tokens reachable from the current
|
||||||
|
// * position in the parse.
|
||||||
|
// */
|
||||||
|
// public IntervalSet nextTokens(@NotNull RuleContext ctx) {
|
||||||
|
// ATN atn = getInterpreter().atn;
|
||||||
|
// ATNState s = atn.states.get(ctx.s);
|
||||||
|
// if ( s == null ) return null;
|
||||||
|
// return atn.nextTokens(s, ctx);
|
||||||
|
// }
|
||||||
|
|
||||||
|
/** 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.
|
||||||
|
*/
|
||||||
|
public List<String> getRuleInvocationStack() {
|
||||||
|
String[] ruleNames = getRuleNames();
|
||||||
|
List<String> stack = new ArrayList<String>();
|
||||||
|
RuleContext p = _ctx;
|
||||||
|
while ( p!=null ) {
|
||||||
|
// compute what follows who invoked us
|
||||||
|
stack.add(ruleNames[p.getRuleIndex()]);
|
||||||
|
p = p.parent;
|
||||||
|
}
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** For debugging and other purposes, might want the grammar name.
|
||||||
|
* Have ANTLR generate an implementation for this method.
|
||||||
|
*/
|
||||||
|
public String getGrammarFileName() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** For debugging and other purposes */
|
||||||
|
public List<String> getDFAStrings() {
|
||||||
|
List<String> s = new ArrayList<String>();
|
||||||
|
for (int d = 0; d < _interp.decisionToDFA.length; d++) {
|
||||||
|
DFA dfa = _interp.decisionToDFA[d];
|
||||||
|
s.add( dfa.toString(getTokenNames()) );
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** For debugging and other purposes */
|
||||||
|
public void dumpDFA() {
|
||||||
|
boolean seenOne = false;
|
||||||
|
for (int d = 0; d < _interp.decisionToDFA.length; d++) {
|
||||||
|
DFA dfa = _interp.decisionToDFA[d];
|
||||||
|
if ( dfa!=null ) {
|
||||||
|
if ( seenOne ) System.out.println();
|
||||||
|
System.out.println("Decision " + dfa.decision + ":");
|
||||||
|
System.out.print(dfa.toString(getTokenNames()));
|
||||||
|
seenOne = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String getSourceName() {
|
public String getSourceName() {
|
||||||
return _input.getSourceName();
|
return _input.getSourceName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A convenience method for use most often with template rewrites.
|
||||||
|
* Convert a List<Token> to List<String>
|
||||||
|
*/
|
||||||
|
public List<String> toStrings(List<? extends Token> tokens) {
|
||||||
|
if ( tokens==null ) return null;
|
||||||
|
List<String> strings = new ArrayList<String>(tokens.size());
|
||||||
|
for (int i=0; i<tokens.size(); i++) {
|
||||||
|
strings.add(tokens.get(i).getText());
|
||||||
|
}
|
||||||
|
return strings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Indicate that the recognizer has changed internal state that is
|
||||||
|
* consistent with the ATN state passed in. This way we always know
|
||||||
|
* where we are in the ATN as the parser goes along. The rule
|
||||||
|
* context objects form a stack that lets us see the stack of
|
||||||
|
* invoking rules. Combine this and we have complete ATN
|
||||||
|
* configuration information.
|
||||||
|
*/
|
||||||
|
public void setState(int atnState) {
|
||||||
|
// System.err.println("setState "+atnState);
|
||||||
|
_ctx.s = atnState;
|
||||||
|
if ( traceATNStates ) _ctx.trace(atnState);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -220,7 +220,7 @@ public class ParserRuleContext<Symbol> extends RuleContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Used for rule context info debugging during runtime, not so much for ATN debugging */
|
/** Used for rule context info debugging during runtime, not so much for ATN debugging */
|
||||||
public String toInfoString(BaseRecognizer recognizer) {
|
public String toInfoString(Parser recognizer) {
|
||||||
List<String> rules = recognizer.getRuleInvocationStack();
|
List<String> rules = recognizer.getRuleInvocationStack();
|
||||||
Collections.reverse(rules);
|
Collections.reverse(rules);
|
||||||
return "ParserRuleContext"+rules+"{" +
|
return "ParserRuleContext"+rules+"{" +
|
||||||
|
|
|
@ -79,8 +79,8 @@ public class RecognitionException extends RuntimeException {
|
||||||
|
|
||||||
public IntervalSet getExpectedTokens() {
|
public IntervalSet getExpectedTokens() {
|
||||||
// TODO: do we really need this type check?
|
// TODO: do we really need this type check?
|
||||||
if ( recognizer!=null && recognizer instanceof BaseRecognizer ) {
|
if ( recognizer!=null && recognizer instanceof Parser) {
|
||||||
return ((BaseRecognizer) recognizer).getExpectedTokens();
|
return ((Parser) recognizer).getExpectedTokens();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -255,18 +255,18 @@ public class RuleContext implements ParseTree.RuleNode {
|
||||||
return new Interval(start, stop);
|
return new Interval(start, stop);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void inspect(BaseRecognizer parser) {
|
public void inspect(Parser parser) {
|
||||||
TreeViewer viewer = new TreeViewer(parser, this);
|
TreeViewer viewer = new TreeViewer(parser, this);
|
||||||
viewer.open();
|
viewer.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save(BaseRecognizer parser, String fileName)
|
public void save(Parser parser, String fileName)
|
||||||
throws IOException, PrintException
|
throws IOException, PrintException
|
||||||
{
|
{
|
||||||
Trees.writePS(this, parser, fileName);
|
Trees.writePS(this, parser, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save(BaseRecognizer parser, String fileName,
|
public void save(Parser parser, String fileName,
|
||||||
String fontName, int fontSize)
|
String fontName, int fontSize)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
|
@ -277,7 +277,7 @@ public class RuleContext implements ParseTree.RuleNode {
|
||||||
* (root child1 .. childN). Print just a node if this is a leaf.
|
* (root child1 .. childN). Print just a node if this is a leaf.
|
||||||
* We have to know the recognizer so we can get rule names.
|
* We have to know the recognizer so we can get rule names.
|
||||||
*/
|
*/
|
||||||
public String toStringTree(BaseRecognizer recog) {
|
public String toStringTree(Parser recog) {
|
||||||
return Trees.toStringTree(this, recog);
|
return Trees.toStringTree(this, recog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
package org.antlr.v4.runtime.atn;
|
package org.antlr.v4.runtime.atn;
|
||||||
|
|
||||||
import org.antlr.v4.runtime.BaseRecognizer;
|
import org.antlr.v4.runtime.Parser;
|
||||||
import org.antlr.v4.runtime.ParserRuleContext;
|
import org.antlr.v4.runtime.ParserRuleContext;
|
||||||
import org.antlr.v4.runtime.RuleContext;
|
import org.antlr.v4.runtime.RuleContext;
|
||||||
import org.antlr.v4.runtime.TokenStream;
|
import org.antlr.v4.runtime.TokenStream;
|
||||||
|
@ -44,7 +44,7 @@ import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class ParserATNPathFinder extends v2ParserATNSimulator {
|
public class ParserATNPathFinder extends v2ParserATNSimulator {
|
||||||
public ParserATNPathFinder(@Nullable BaseRecognizer parser, @NotNull ATN atn) {
|
public ParserATNPathFinder(@Nullable Parser parser, @NotNull ATN atn) {
|
||||||
super(parser, atn);
|
super(parser, atn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -236,7 +236,7 @@ public class v2ParserATNSimulator<Symbol> extends ATNSimulator {
|
||||||
public static int retry_with_context_indicates_no_conflict = 0;
|
public static int retry_with_context_indicates_no_conflict = 0;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
protected final BaseRecognizer parser;
|
protected final Parser parser;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public final DFA[] decisionToDFA;
|
public final DFA[] decisionToDFA;
|
||||||
|
@ -246,7 +246,7 @@ public class v2ParserATNSimulator<Symbol> extends ATNSimulator {
|
||||||
this(null, atn);
|
this(null, atn);
|
||||||
}
|
}
|
||||||
|
|
||||||
public v2ParserATNSimulator(@Nullable BaseRecognizer parser, @NotNull ATN atn) {
|
public v2ParserATNSimulator(@Nullable Parser parser, @NotNull ATN atn) {
|
||||||
super(atn);
|
super(atn);
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
// ctxToDFAs = new HashMap<RuleContext, DFA[]>();
|
// ctxToDFAs = new HashMap<RuleContext, DFA[]>();
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
package org.antlr.v4.runtime.tree;
|
package org.antlr.v4.runtime.tree;
|
||||||
|
|
||||||
import org.antlr.v4.runtime.BaseRecognizer;
|
import org.antlr.v4.runtime.Parser;
|
||||||
import org.antlr.v4.runtime.Token;
|
import org.antlr.v4.runtime.Token;
|
||||||
import org.antlr.v4.runtime.misc.NotNull;
|
import org.antlr.v4.runtime.misc.NotNull;
|
||||||
import org.antlr.v4.runtime.tree.gui.TreePostScriptGenerator;
|
import org.antlr.v4.runtime.tree.gui.TreePostScriptGenerator;
|
||||||
|
@ -44,7 +44,7 @@ import java.util.List;
|
||||||
/** A set of utility routines useful for all kinds of ANTLR trees */
|
/** A set of utility routines useful for all kinds of ANTLR trees */
|
||||||
public class Trees {
|
public class Trees {
|
||||||
|
|
||||||
public static String getPS(Tree t, BaseRecognizer recog,
|
public static String getPS(Tree t, Parser recog,
|
||||||
String fontName, int fontSize)
|
String fontName, int fontSize)
|
||||||
{
|
{
|
||||||
TreePostScriptGenerator psgen =
|
TreePostScriptGenerator psgen =
|
||||||
|
@ -52,11 +52,11 @@ public class Trees {
|
||||||
return psgen.getPS();
|
return psgen.getPS();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getPS(Tree t, BaseRecognizer recog) {
|
public static String getPS(Tree t, Parser recog) {
|
||||||
return getPS(t, recog, "Helvetica", 11);
|
return getPS(t, recog, "Helvetica", 11);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void writePS(Tree t, BaseRecognizer recog,
|
public static void writePS(Tree t, Parser recog,
|
||||||
String fileName,
|
String fileName,
|
||||||
String fontName, int fontSize)
|
String fontName, int fontSize)
|
||||||
throws IOException
|
throws IOException
|
||||||
|
@ -68,7 +68,7 @@ public class Trees {
|
||||||
bw.close();
|
bw.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void writePS(Tree t, BaseRecognizer recog, String fileName)
|
public static void writePS(Tree t, Parser recog, String fileName)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
writePS(t, recog, fileName, "Helvetica", 11);
|
writePS(t, recog, fileName, "Helvetica", 11);
|
||||||
|
@ -78,7 +78,7 @@ public class Trees {
|
||||||
* node payloads to get the text for the nodes. Detect
|
* node payloads to get the text for the nodes. Detect
|
||||||
* parse trees and extract data appropriately.
|
* parse trees and extract data appropriately.
|
||||||
*/
|
*/
|
||||||
public static String toStringTree(Tree t, BaseRecognizer recog) {
|
public static String toStringTree(Tree t, Parser recog) {
|
||||||
if ( t.getChildCount()==0 ) return getNodeText(t, recog);
|
if ( t.getChildCount()==0 ) return getNodeText(t, recog);
|
||||||
StringBuilder buf = new StringBuilder();
|
StringBuilder buf = new StringBuilder();
|
||||||
buf.append("(");
|
buf.append("(");
|
||||||
|
@ -92,7 +92,7 @@ public class Trees {
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <Symbol> String getNodeText(Tree t, BaseRecognizer recog) {
|
public static <Symbol> String getNodeText(Tree t, Parser recog) {
|
||||||
if ( recog!=null ) {
|
if ( recog!=null ) {
|
||||||
if ( t instanceof ParseTree.RuleNode ) {
|
if ( t instanceof ParseTree.RuleNode ) {
|
||||||
int ruleIndex = ((ParseTree.RuleNode)t).getRuleContext().getRuleIndex();
|
int ruleIndex = ((ParseTree.RuleNode)t).getRuleContext().getRuleIndex();
|
||||||
|
|
|
@ -34,7 +34,7 @@ import org.abego.treelayout.NodeExtentProvider;
|
||||||
import org.abego.treelayout.TreeForTreeLayout;
|
import org.abego.treelayout.TreeForTreeLayout;
|
||||||
import org.abego.treelayout.TreeLayout;
|
import org.abego.treelayout.TreeLayout;
|
||||||
import org.abego.treelayout.util.DefaultConfiguration;
|
import org.abego.treelayout.util.DefaultConfiguration;
|
||||||
import org.antlr.v4.runtime.BaseRecognizer;
|
import org.antlr.v4.runtime.Parser;
|
||||||
import org.antlr.v4.runtime.tree.ParseTree;
|
import org.antlr.v4.runtime.tree.ParseTree;
|
||||||
import org.antlr.v4.runtime.tree.Tree;
|
import org.antlr.v4.runtime.tree.Tree;
|
||||||
|
|
||||||
|
@ -71,11 +71,11 @@ public class TreePostScriptGenerator {
|
||||||
|
|
||||||
protected PostScriptDocument doc;
|
protected PostScriptDocument doc;
|
||||||
|
|
||||||
public TreePostScriptGenerator(BaseRecognizer parser, Tree root) {
|
public TreePostScriptGenerator(Parser parser, Tree root) {
|
||||||
this(parser, root, "CourierNew", 11);
|
this(parser, root, "CourierNew", 11);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TreePostScriptGenerator(BaseRecognizer parser, Tree root,
|
public TreePostScriptGenerator(Parser parser, Tree root,
|
||||||
String fontName, int fontSize)
|
String fontName, int fontSize)
|
||||||
{
|
{
|
||||||
this.root = root;
|
this.root = root;
|
||||||
|
|
|
@ -33,7 +33,7 @@ import org.abego.treelayout.NodeExtentProvider;
|
||||||
import org.abego.treelayout.TreeForTreeLayout;
|
import org.abego.treelayout.TreeForTreeLayout;
|
||||||
import org.abego.treelayout.TreeLayout;
|
import org.abego.treelayout.TreeLayout;
|
||||||
import org.abego.treelayout.util.DefaultConfiguration;
|
import org.abego.treelayout.util.DefaultConfiguration;
|
||||||
import org.antlr.v4.runtime.BaseRecognizer;
|
import org.antlr.v4.runtime.Parser;
|
||||||
import org.antlr.v4.runtime.tree.ParseTree;
|
import org.antlr.v4.runtime.tree.ParseTree;
|
||||||
import org.antlr.v4.runtime.tree.Tree;
|
import org.antlr.v4.runtime.tree.Tree;
|
||||||
import org.antlr.v4.runtime.tree.Trees;
|
import org.antlr.v4.runtime.tree.Trees;
|
||||||
|
@ -53,9 +53,9 @@ public class TreeViewer extends JComponent {
|
||||||
public static final Color LIGHT_RED = new Color(244, 213, 211);
|
public static final Color LIGHT_RED = new Color(244, 213, 211);
|
||||||
|
|
||||||
public static class DefaultTreeTextProvider implements TreeTextProvider {
|
public static class DefaultTreeTextProvider implements TreeTextProvider {
|
||||||
BaseRecognizer parser;
|
Parser parser;
|
||||||
|
|
||||||
public DefaultTreeTextProvider(BaseRecognizer parser) {
|
public DefaultTreeTextProvider(Parser parser) {
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,9 +111,9 @@ public class TreeViewer extends JComponent {
|
||||||
protected Color borderColor = null;
|
protected Color borderColor = null;
|
||||||
protected Color textColor = Color.black;
|
protected Color textColor = Color.black;
|
||||||
|
|
||||||
protected BaseRecognizer parser;
|
protected Parser parser;
|
||||||
|
|
||||||
public TreeViewer(BaseRecognizer parser, Tree tree) {
|
public TreeViewer(Parser parser, Tree tree) {
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
setTreeTextProvider(new DefaultTreeTextProvider(parser));
|
setTreeTextProvider(new DefaultTreeTextProvider(parser));
|
||||||
boolean useIdentity = true; // compare node identity
|
boolean useIdentity = true; // compare node identity
|
||||||
|
|
|
@ -38,12 +38,12 @@ public class TestPerformance extends BaseTest {
|
||||||
private static final boolean RUN_PARSER = true;
|
private static final boolean RUN_PARSER = true;
|
||||||
/** True to use {@link BailErrorStrategy}, False to use {@link DefaultErrorStrategy} */
|
/** True to use {@link BailErrorStrategy}, False to use {@link DefaultErrorStrategy} */
|
||||||
private static final boolean BAIL_ON_ERROR = false;
|
private static final boolean BAIL_ON_ERROR = false;
|
||||||
/** This value is passed to {@link BaseRecognizer#setBuildParseTree}. */
|
/** This value is passed to {@link org.antlr.v4.runtime.Parser#setBuildParseTree}. */
|
||||||
private static final boolean BUILD_PARSE_TREES = false;
|
private static final boolean BUILD_PARSE_TREES = false;
|
||||||
/**
|
/**
|
||||||
* Use ParseTreeWalker.DEFAULT.walk with the BlankJavaParserListener to show parse tree walking overhead.
|
* Use ParseTreeWalker.DEFAULT.walk with the BlankJavaParserListener to show parse tree walking overhead.
|
||||||
* If {@link #BUILD_PARSE_TREES} is false, the listener will instead be called during the parsing process via
|
* If {@link #BUILD_PARSE_TREES} is false, the listener will instead be called during the parsing process via
|
||||||
* {@link BaseRecognizer#setListener}.
|
* {@link org.antlr.v4.runtime.Parser#setListener}.
|
||||||
*/
|
*/
|
||||||
private static final boolean BLANK_LISTENER = false;
|
private static final boolean BLANK_LISTENER = false;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue