v4: Add TSymbol generic type parameter to Recognizer, BaseRecognizer, ParserATNSimulator, ParserRuleContext, ParseTreeListener, ANTLRErrorStrategy, ANTLRErrorListener, TreeParserRuleContext

Move ParserRuleContext.tree/getTree to the generated contexts, implement ASTContext<T> for strongly typed getTree() method

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 9379]
This commit is contained in:
sharwell 2011-11-17 19:40:48 -08:00
parent 73907aacd3
commit 65f8b9f124
36 changed files with 564 additions and 309 deletions

View File

@ -32,7 +32,7 @@ package org.antlr.v4.runtime;
import com.sun.istack.internal.Nullable;
/** How to emit recognition errors */
public interface ANTLRErrorListener {
public interface ANTLRErrorListener<TSymbol> {
/** Upon syntax error, notify any interested parties. This is not how to
* recover from errors or compute error messages. The parser
* ANTLRErrorStrategy specifies how to recover from syntax errors
@ -48,7 +48,7 @@ public interface ANTLRErrorListener {
* @param recognizer
* What parser got the error. From this object, you
* can access the context as well as the input stream.
* @param offendingToken
* @param offendingSymbol
* The offending token in the input token stream, unless recognizer
* is a lexer (then it's null)
* If no viable alternative error, e has token
@ -66,8 +66,8 @@ public interface ANTLRErrorListener {
* the parser was able to recover in line without exiting the
* surrounding rule.
*/
public void error(Recognizer recognizer,
@Nullable Token offendingToken,
public void error(Recognizer<TSymbol, ?> recognizer,
@Nullable TSymbol offendingSymbol,
int line,
int charPositionInLine,
String msg,

View File

@ -21,9 +21,9 @@ package org.antlr.v4.runtime;
*
* TODO: what to do about lexers
*/
public interface ANTLRErrorStrategy {
public interface ANTLRErrorStrategy<TSymbol> {
/** Report any kind of RecognitionException. */
void reportError(BaseRecognizer recognizer,
void reportError(BaseRecognizer<TSymbol> recognizer,
RecognitionException e)
throws RecognitionException;
@ -43,7 +43,7 @@ public interface ANTLRErrorStrategy {
* "inserting" tokens, we need to specify what that implicitly created
* token is. We use object, because it could be a tree node.
*/
Object recoverInline(BaseRecognizer recognizer)
TSymbol recoverInline(BaseRecognizer<TSymbol> recognizer)
throws RecognitionException;
/** Resynchronize the parser by consuming tokens until we find one
@ -51,7 +51,7 @@ public interface ANTLRErrorStrategy {
* the current rule. The exception contains info you might want to
* use to recover better.
*/
void recover(BaseRecognizer recognizer,
void recover(BaseRecognizer<TSymbol> recognizer,
RecognitionException e);
/** Make sure that the current lookahead symbol is consistent with
@ -81,14 +81,14 @@ public interface ANTLRErrorStrategy {
* turn off this functionality by simply overriding this method as
* a blank { }.
*/
void sync(BaseRecognizer recognizer);
void sync(BaseRecognizer<TSymbol> recognizer);
/** Notify handler that parser has entered an error state. The
* parser currently doesn't call this--the handler itself calls this
* in report error methods. But, for symmetry with endErrorCondition,
* this method is in the interface.
*/
void beginErrorCondition(BaseRecognizer recognizer);
void beginErrorCondition(BaseRecognizer<TSymbol> recognizer);
/** Is the parser in the process of recovering from an error? Upon
* a syntax error, the parser enters recovery mode and stays there until
@ -96,11 +96,11 @@ public interface ANTLRErrorStrategy {
* avoid sending out spurious error messages. We only want one error
* message per syntax error
*/
boolean inErrorRecoveryMode(BaseRecognizer recognizer);
boolean inErrorRecoveryMode(BaseRecognizer<TSymbol> recognizer);
/** Reset the error handler. Call this when the parser
* matches a valid token (indicating no longer in recovery mode)
* and from its own reset method.
*/
void endErrorCondition(BaseRecognizer recognizer);
void endErrorCondition(BaseRecognizer<TSymbol> recognizer);
}

View File

@ -41,7 +41,7 @@ import java.util.*;
*
* TODO: rename since lexer not under. or reorg parser/treeparser; treeparser under parser?
*/
public abstract class BaseRecognizer extends Recognizer<ParserATNSimulator> {
public abstract class BaseRecognizer<TSymbol> extends Recognizer<TSymbol, ParserATNSimulator<TSymbol>> {
public static final String NEXT_TOKEN_RULE_NAME = "nextToken";
/** The RuleContext object for the currently executing rule. This
@ -49,7 +49,7 @@ public abstract class BaseRecognizer extends Recognizer<ParserATNSimulator> {
* When somebody calls the start rule, this gets set to the
* root context.
*/
protected ParserRuleContext _ctx;
protected ParserRuleContext<TSymbol> _ctx;
protected boolean buildParseTrees;
protected boolean traceATNStates;
@ -80,9 +80,9 @@ public abstract class BaseRecognizer extends Recognizer<ParserATNSimulator> {
* to the set of symbols that can follow rule ref.
* TODO: mv into Parser etc... to get more precise return value/efficiency
*/
public Object match(int ttype) throws RecognitionException {
public TSymbol match(int ttype) throws RecognitionException {
// System.out.println("match "+((TokenStream)input).LT(1)+" vs expected "+ttype);
Object currentSymbol = getCurrentInputSymbol();
TSymbol currentSymbol = getCurrentInputSymbol();
if ( getInputStream().LA(1)==ttype ) {
_errHandler.endErrorCondition(this);
consume();
@ -147,6 +147,9 @@ public abstract class BaseRecognizer extends Recognizer<ParserATNSimulator> {
return syntaxErrors;
}
@Override
public abstract ObjectStream<TSymbol> getInputStream();
/** Match needs to return the current input symbol, which gets put
* into the label for the associated token ref; e.g., x=ID. Token
* and tree parsers need to return different objects. Rather than test
@ -154,27 +157,32 @@ public abstract class BaseRecognizer extends Recognizer<ParserATNSimulator> {
* a simple method to ask the recognizer to tell me what the current
* input symbol is.
*/
protected Object getCurrentInputSymbol() { return null; }
public abstract TSymbol getCurrentInputSymbol();
public void notifyListeners(String msg) {
notifyListeners((Token)getCurrentInputSymbol(), msg, null);
notifyListeners(getCurrentInputSymbol(), msg, null);
}
public void notifyListeners(Token offendingToken, String msg,
public void notifyListeners(TSymbol offendingToken, String msg,
@Nullable RecognitionException e)
{
int line = offendingToken.getLine();
int charPositionInLine = offendingToken.getCharPositionInLine();
if ( _listeners==null || _listeners.size()==0 ) {
int line = -1;
int charPositionInLine = -1;
if (offendingToken instanceof Token) {
line = ((Token) offendingToken).getLine();
charPositionInLine = ((Token) offendingToken).getCharPositionInLine();
}
ANTLRErrorListener<TSymbol>[] listeners = getListeners();
if ( listeners.length == 0 ) {
System.err.println("line "+line+":"+charPositionInLine+" "+msg);
return;
}
for (ANTLRErrorListener pl : _listeners) {
for (ANTLRErrorListener<TSymbol> pl : listeners) {
pl.error(this, offendingToken, line, charPositionInLine, msg, e);
}
}
public void enterOuterAlt(ParserRuleContext localctx, int altNum) {
public void enterOuterAlt(ParserRuleContext<TSymbol> 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 ) {
@ -197,8 +205,8 @@ public abstract class BaseRecognizer extends Recognizer<ParserATNSimulator> {
* If the parser is creating parse trees, the current symbol
* would also be added as a child to the current context (node).
*/
public Object consume() {
Object o = getCurrentInputSymbol();
public TSymbol consume() {
TSymbol o = getCurrentInputSymbol();
getInputStream().consume();
if ( buildParseTrees ) {
// TODO: tree parsers?
@ -219,22 +227,22 @@ public abstract class BaseRecognizer extends Recognizer<ParserATNSimulator> {
}
}
public abstract void enterRule(ParserRuleContext localctx, int ruleIndex);
public abstract void enterRule(ParserRuleContext<TSymbol> localctx, int ruleIndex);
public void exitRule(int ruleIndex) {
_ctx = (ParserRuleContext)_ctx.parent;
_ctx = (ParserRuleContext<TSymbol>)_ctx.parent;
}
public ParserRuleContext getInvokingContext(int ruleIndex) {
ParserRuleContext p = _ctx;
public ParserRuleContext<TSymbol> getInvokingContext(int ruleIndex) {
ParserRuleContext<TSymbol> p = _ctx;
while ( p!=null ) {
if ( p.getRuleIndex() == ruleIndex ) return p;
p = (ParserRuleContext)p.parent;
p = (ParserRuleContext<TSymbol>)p.parent;
}
return null;
}
public ParserRuleContext getContext() {
public ParserRuleContext<TSymbol> getContext() {
return _ctx;
}

View File

@ -29,13 +29,17 @@
package org.antlr.v4.runtime;
import com.sun.istack.internal.NotNull;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.runtime.tree.AST;
import org.antlr.v4.runtime.tree.ASTAdaptor;
import org.antlr.v4.runtime.tree.Tree;
/** This is the default error handling mechanism for ANTLR parsers
* and tree parsers.
*/
public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
public class DefaultANTLRErrorStrategy<TSymbol> implements ANTLRErrorStrategy<TSymbol> {
/** This is true after we see an error and before having successfully
* matched a token. Prevents generation of more than one error message
* per error.
@ -53,24 +57,24 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
protected IntervalSet lastErrorStates;
@Override
public void beginErrorCondition(BaseRecognizer recognizer) {
public void beginErrorCondition(BaseRecognizer<TSymbol> recognizer) {
errorRecoveryMode = true;
}
@Override
public boolean inErrorRecoveryMode(BaseRecognizer recognizer) {
public boolean inErrorRecoveryMode(BaseRecognizer<TSymbol> recognizer) {
return errorRecoveryMode;
}
@Override
public void endErrorCondition(BaseRecognizer recognizer) {
public void endErrorCondition(BaseRecognizer<TSymbol> recognizer) {
errorRecoveryMode = false;
lastErrorStates = null;
lastErrorIndex = -1;
}
@Override
public void reportError(BaseRecognizer recognizer,
public void reportError(BaseRecognizer<TSymbol> recognizer,
RecognitionException e)
throws RecognitionException
{
@ -94,7 +98,7 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
else {
System.err.println("unknown recognition error type: "+e.getClass().getName());
if ( recognizer!=null ) {
recognizer.notifyListeners(e.offendingToken, e.getMessage(), e);
recognizer.notifyListeners((TSymbol)e.offendingNode, e.getMessage(), e);
}
}
}
@ -103,7 +107,7 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
* token that the match() routine could not recover from.
*/
@Override
public void recover(BaseRecognizer recognizer, RecognitionException e) {
public void recover(BaseRecognizer<TSymbol> recognizer, RecognitionException e) {
// System.out.println("recover in "+recognizer.getRuleInvocationStack()+
// " index="+recognizer.getInputStream().index()+
// ", lastErrorIndex="+
@ -143,7 +147,7 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
* We opt to stay in the loop as long as possible.
*/
@Override
public void sync(BaseRecognizer recognizer) {
public void sync(BaseRecognizer<TSymbol> recognizer) {
ATNState s = recognizer._interp.atn.states.get(recognizer._ctx.s);
// System.err.println("sync @ "+s.stateNumber+"="+s.getClass().getSimpleName());
// If already recovering, don't try to sync
@ -154,10 +158,10 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
// System.err.println("sync expecting: "+expecting);
// TODO: subclass this class for treeparsers
TokenStream tokens = (TokenStream)recognizer.getInputStream();
Token la = tokens.LT(1);
ObjectStream<TSymbol> tokens = recognizer.getInputStream();
int la = tokens.LA(1);
// Return but don't end recovery. only do that upon valid token match
if ( la.getType()==Token.EOF || expecting.contains(la.getType()) ) return;
if ( la==Token.EOF || expecting.contains(la) ) return;
if ( s instanceof PlusBlockStartState ||
s instanceof StarLoopEntryState ||
@ -179,40 +183,45 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
// do nothing if we can't identify the exact kind of ATN state
}
public void reportNoViableAlternative(BaseRecognizer recognizer,
public void reportNoViableAlternative(BaseRecognizer<TSymbol> recognizer,
NoViableAltException e)
throws RecognitionException
{
TokenStream tokens = (TokenStream)recognizer.getInputStream();
String input = tokens.toString(e.startToken, e.offendingToken);
ObjectStream<TSymbol> tokens = recognizer.getInputStream();
String input;
if (tokens instanceof TokenStream) {
input = ((TokenStream)tokens).toString(e.startToken, e.offendingToken);
} else {
input = "<unknown input>";
}
String msg = "no viable alternative at input "+escapeWSAndQuote(input);
recognizer.notifyListeners(e.offendingToken, msg, e);
recognizer.notifyListeners((TSymbol)e.offendingNode, msg, e);
}
public void reportInputMismatch(BaseRecognizer recognizer,
public void reportInputMismatch(BaseRecognizer<TSymbol> recognizer,
InputMismatchException e)
throws RecognitionException
{
String msg = "mismatched input "+getTokenErrorDisplay(e.offendingToken)+
String msg = "mismatched input "+getTokenErrorDisplay((TSymbol)e.offendingNode)+
" expecting "+e.getExpectedTokens().toString(recognizer.getTokenNames());
recognizer.notifyListeners(e.offendingToken, msg, e);
recognizer.notifyListeners((TSymbol)e.offendingNode, msg, e);
}
public void reportFailedPredicate(BaseRecognizer recognizer,
public void reportFailedPredicate(BaseRecognizer<TSymbol> recognizer,
FailedPredicateException e)
throws RecognitionException
{
String ruleName = recognizer.getRuleNames()[recognizer._ctx.getRuleIndex()];
String msg = "rule "+ruleName+" "+e.msg;
recognizer.notifyListeners(e.offendingToken, msg, e);
recognizer.notifyListeners((TSymbol)e.offendingNode, msg, e);
}
public void reportUnwantedToken(BaseRecognizer recognizer) {
public void reportUnwantedToken(BaseRecognizer<TSymbol> recognizer) {
if (errorRecoveryMode) return;
recognizer.syntaxErrors++;
beginErrorCondition(recognizer);
Token t = (Token)recognizer.getCurrentInputSymbol();
TSymbol t = recognizer.getCurrentInputSymbol();
String tokenName = getTokenErrorDisplay(t);
IntervalSet expecting = getExpectedTokens(recognizer);
String msg = "extraneous input "+tokenName+" expecting "+
@ -220,12 +229,12 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
recognizer.notifyListeners(t, msg, null);
}
public void reportMissingToken(BaseRecognizer recognizer) {
public void reportMissingToken(BaseRecognizer<TSymbol> recognizer) {
if (errorRecoveryMode) return;
recognizer.syntaxErrors++;
beginErrorCondition(recognizer);
Token t = (Token)recognizer.getCurrentInputSymbol();
TSymbol t = recognizer.getCurrentInputSymbol();
IntervalSet expecting = getExpectedTokens(recognizer);
String msg = "missing "+expecting.toString(recognizer.getTokenNames())+
" at "+getTokenErrorDisplay(t);
@ -263,11 +272,11 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
* reference in rule atom. It can assume that you forgot the ')'.
*/
@Override
public Object recoverInline(BaseRecognizer recognizer)
public TSymbol recoverInline(BaseRecognizer<TSymbol> recognizer)
throws RecognitionException
{
// SINGLE TOKEN DELETION
Object matchedSymbol = singleTokenDeletion(recognizer);
TSymbol matchedSymbol = singleTokenDeletion(recognizer);
if ( matchedSymbol!=null ) {
// we have deleted the extra token.
// now, move past ttype token as if all were ok
@ -285,8 +294,8 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
}
// if next token is what we are looking for then "delete" this token
public boolean singleTokenInsertion(BaseRecognizer recognizer) {
Object currentSymbol = recognizer.getCurrentInputSymbol();
public boolean singleTokenInsertion(BaseRecognizer<TSymbol> recognizer) {
int currentSymbolType = recognizer.getInputStream().LA(1);
// if current token is consistent with what could come after current
// ATN state, then we know we're missing a token; error recovery
// is free to conjure up and insert the missing token
@ -294,14 +303,14 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
ATNState next = currentState.transition(0).target;
IntervalSet expectingAtLL2 = recognizer._interp.atn.nextTokens(next, recognizer._ctx);
// System.out.println("LT(2) set="+expectingAtLL2.toString(recognizer.getTokenNames()));
if ( expectingAtLL2.contains(((Token)currentSymbol).getType()) ) {
if ( expectingAtLL2.contains(currentSymbolType) ) {
reportMissingToken(recognizer);
return true;
}
return false;
}
public Object singleTokenDeletion(BaseRecognizer recognizer) {
public TSymbol singleTokenDeletion(BaseRecognizer<TSymbol> recognizer) {
int nextTokenType = recognizer.getInputStream().LA(2);
IntervalSet expecting = getExpectedTokens(recognizer);
if ( expecting.contains(nextTokenType) ) {
@ -314,7 +323,7 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
*/
recognizer.consume(); // simply delete extra token
// we want to return the token we're actually matching
Object matchedSymbol = recognizer.getCurrentInputSymbol();
TSymbol matchedSymbol = recognizer.getCurrentInputSymbol();
endErrorCondition(recognizer); // we know current token is correct
return matchedSymbol;
}
@ -340,14 +349,19 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
* If you change what tokens must be created by the lexer,
* override this method to create the appropriate tokens.
*/
protected Object getMissingSymbol(BaseRecognizer recognizer) {
protected TSymbol getMissingSymbol(BaseRecognizer<TSymbol> recognizer) {
TSymbol currentSymbol = recognizer.getCurrentInputSymbol();
if (!(currentSymbol instanceof Token)) {
throw new UnsupportedOperationException("This error strategy only supports Token symbols.");
}
IntervalSet expecting = getExpectedTokens(recognizer);
int expectedTokenType = expecting.getMinElement(); // get any element
String tokenText = null;
String tokenText;
if ( expectedTokenType== Token.EOF ) tokenText = "<missing EOF>";
else tokenText = "<missing "+recognizer.getTokenNames()[expectedTokenType]+">";
CommonToken t = new CommonToken(expectedTokenType, tokenText);
Token current = (Token)recognizer.getCurrentInputSymbol();
Token current = (Token)currentSymbol;
if ( current.getType() == Token.EOF ) {
current = ((TokenStream)recognizer.getInputStream()).LT(-1);
}
@ -356,10 +370,10 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
t.channel = Token.DEFAULT_CHANNEL;
t.source = current.getTokenSource();
t.index = -1; // indicate we conjured this up because it has no index
return t;
return (TSymbol)t;
}
public IntervalSet getExpectedTokens(BaseRecognizer recognizer) {
public IntervalSet getExpectedTokens(BaseRecognizer<TSymbol> recognizer) {
return recognizer.getExpectedTokens();
}
@ -371,20 +385,40 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
* your token objects because you don't have to go modify your lexer
* so that it creates a new Java type.
*/
public String getTokenErrorDisplay(Token t) {
public String getTokenErrorDisplay(TSymbol t) {
if ( t==null ) return "<no token>";
String s = t.getText();
String s = getSymbolText(t);
if ( s==null ) {
if ( t.getType()==Token.EOF ) {
if ( getSymbolType(t)==Token.EOF ) {
s = "<EOF>";
}
else {
s = "<"+t.getType()+">";
s = "<"+getSymbolType(t)+">";
}
}
return escapeWSAndQuote(s);
}
protected String getSymbolText(@NotNull TSymbol symbol) {
if (symbol instanceof Token) {
return ((Token)symbol).getText();
} else if (symbol instanceof AST) {
return ((AST)symbol).getText();
} else {
return symbol.toString();
}
}
protected int getSymbolType(@NotNull TSymbol symbol) {
if (symbol instanceof Token) {
return ((Token)symbol).getType();
} else if (symbol instanceof AST) {
return ((AST)symbol).getType();
} else {
return Token.INVALID_TYPE;
}
}
protected String escapeWSAndQuote(String s) {
// if ( s==null ) return s;
s = s.replaceAll("\n","\\\\n");
@ -485,7 +519,7 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
* Like Grosch I implement context-sensitive FOLLOW sets that are combined
* at run-time upon error to avoid overhead during parsing.
*/
protected IntervalSet getErrorRecoverySet(BaseRecognizer recognizer) {
protected IntervalSet getErrorRecoverySet(BaseRecognizer<TSymbol> recognizer) {
ATN atn = recognizer._interp.atn;
RuleContext ctx = recognizer._ctx;
IntervalSet recoverSet = new IntervalSet();
@ -502,7 +536,7 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
}
/** Consume tokens until one matches the given token set */
public void consumeUntil(BaseRecognizer recognizer, IntervalSet set) {
public void consumeUntil(BaseRecognizer<TSymbol> recognizer, IntervalSet set) {
// System.err.println("consumeUntil("+set.toString(recognizer.getTokenNames())+")");
int ttype = recognizer.getInputStream().LA(1);
while (ttype != Token.EOF && !set.contains(ttype) ) {

View File

@ -34,18 +34,18 @@ import org.antlr.v4.runtime.tree.gui.TreeViewer;
import java.util.*;
public class DefaultANTLRTreeGrammarErrorStrategy<T> extends DefaultANTLRErrorStrategy {
public class DefaultANTLRTreeGrammarErrorStrategy<T> extends DefaultANTLRErrorStrategy<T> {
@Override
public void beginErrorCondition(BaseRecognizer recognizer) {
public void beginErrorCondition(BaseRecognizer<T> recognizer) {
}
@Override
public void reportError(BaseRecognizer recognizer, RecognitionException e)
public void reportError(BaseRecognizer<T> recognizer, RecognitionException e)
throws RecognitionException
{
super.reportError(recognizer, e);
TreeParser<T> parser = (TreeParser<T>)recognizer;
ASTNodeStream input = parser.getInputStream();
ASTNodeStream<T> input = parser.getInputStream();
Object root = input.getTreeSource();
// If instanceof Tree, we can show in TreeViewer
if ( root instanceof Tree ) {
@ -67,15 +67,15 @@ public class DefaultANTLRTreeGrammarErrorStrategy<T> extends DefaultANTLRErrorSt
}
@Override
public void reportNoViableAlternative(BaseRecognizer recognizer,
public void reportNoViableAlternative(BaseRecognizer<T> recognizer,
NoViableAltException e)
throws RecognitionException
{
TreeParser<T> parser = (TreeParser<T>)recognizer;
ASTNodeStream input = parser.getInputStream();
ASTNodeStream<T> input = parser.getInputStream();
List<T> unmatchedNodes =
getNodeList(input, (NoViableTreeGrammarAltException)e);
StringBuffer buf = new StringBuffer();
StringBuilder buf = new StringBuilder();
ASTAdaptor<T> adap = input.getTreeAdaptor();
for (int i = 0; i < unmatchedNodes.size(); i++) {
if ( i>0 ) buf.append(" ");
@ -84,10 +84,10 @@ public class DefaultANTLRTreeGrammarErrorStrategy<T> extends DefaultANTLRErrorSt
}
String s = buf.toString();
String msg = "no viable alternative at node(s) "+escapeWSAndQuote(s);
recognizer.notifyListeners(e.offendingToken, msg, e);
recognizer.notifyListeners((T)e.offendingNode, msg, e);
}
protected List<T> getNodeList(ASTNodeStream input,
protected List<T> getNodeList(ASTNodeStream<T> input,
NoViableTreeGrammarAltException nva)
{
List<T> unmatchedNodes;
@ -113,27 +113,27 @@ public class DefaultANTLRTreeGrammarErrorStrategy<T> extends DefaultANTLRErrorSt
}
@Override
public Object recoverInline(BaseRecognizer recognizer) throws RecognitionException {
public T recoverInline(BaseRecognizer<T> recognizer) throws RecognitionException {
InputMismatchException e = new InputMismatchException(recognizer);
reportError(recognizer, e);
throw e;
}
@Override
public void recover(BaseRecognizer recognizer, RecognitionException e) {
public void recover(BaseRecognizer<T> recognizer, RecognitionException e) {
throw new RuntimeException(e);
}
@Override
public void sync(BaseRecognizer recognizer) {
public void sync(BaseRecognizer<T> recognizer) {
}
@Override
public boolean inErrorRecoveryMode(BaseRecognizer recognizer) {
public boolean inErrorRecoveryMode(BaseRecognizer<T> recognizer) {
return false;
}
@Override
public void endErrorCondition(BaseRecognizer recognizer) {
public void endErrorCondition(BaseRecognizer<T> recognizer) {
}
}

View File

@ -42,11 +42,11 @@ public class FailedPredicateException extends RecognitionException {
public int predIndex;
public String msg;
public FailedPredicateException(BaseRecognizer recognizer) {
public FailedPredicateException(BaseRecognizer<?> recognizer) {
this(recognizer, null);
}
public FailedPredicateException(BaseRecognizer recognizer, @Nullable String msg) {
public FailedPredicateException(BaseRecognizer<?> recognizer, @Nullable String msg) {
super(recognizer, recognizer.getInputStream(), recognizer._ctx);
ATNState s = recognizer._interp.atn.states.get(recognizer._ctx.s);
PredicateTransition trans = (PredicateTransition)s.transition(0);
@ -54,8 +54,8 @@ public class FailedPredicateException extends RecognitionException {
predIndex = trans.predIndex;
this.msg = msg;
Object la = recognizer.getCurrentInputSymbol();
this.offendingNode = la;
if ( la instanceof AST) {
this.offendingNode = la;
this.offendingToken = ((AST)la).getPayload();
}
else {

View File

@ -6,11 +6,11 @@ import org.antlr.v4.runtime.tree.AST;
* when the current input does not match the expected token or tree node.
*/
public class InputMismatchException extends RecognitionException {
public InputMismatchException(BaseRecognizer recognizer) {
public InputMismatchException(BaseRecognizer<?> recognizer) {
super(recognizer, recognizer.getInputStream(), recognizer._ctx);
Object la = recognizer.getCurrentInputSymbol();
this.offendingNode = la;
if ( la instanceof AST ) {
this.offendingNode = la;
this.offendingToken = ((AST)la).getPayload();
}
else {

View File

@ -38,7 +38,7 @@ import java.util.EmptyStackException;
* uses simplified match() and error recovery mechanisms in the interest
* of speed.
*/
public abstract class Lexer extends Recognizer<LexerATNSimulator>
public abstract class Lexer extends Recognizer<Integer, LexerATNSimulator>
implements TokenSource
{
public static final int DEFAULT_MODE = 0;
@ -313,13 +313,14 @@ public abstract class Lexer extends Recognizer<LexerATNSimulator>
public void notifyListeners(LexerNoViableAltException e) {
String msg = "token recognition error at: '"+
input.substring(tokenStartCharIndex,input.index())+"'";
if ( _listeners==null || _listeners.size()==0 ) {
ANTLRErrorListener<Integer>[] listeners = getListeners();
if ( listeners.length == 0 ) {
System.err.println("line "+tokenStartLine+":"+
tokenStartCharPositionInLine+" "+
msg);
return;
}
for (ANTLRErrorListener pl : _listeners) {
for (ANTLRErrorListener<Integer> pl : listeners) {
pl.error(this, null, tokenStartLine, tokenStartCharPositionInLine, msg, e);
}
}

View File

@ -45,24 +45,27 @@ public class NoViableAltException extends RecognitionException {
*/
public Token startToken;
public NoViableAltException(BaseRecognizer recognizer) { // LL(1) error
public <T extends Token> NoViableAltException(BaseRecognizer<T> recognizer) { // LL(1) error
this(recognizer,recognizer.getInputStream(),
(Token)recognizer.getCurrentInputSymbol(),
(Token)recognizer.getCurrentInputSymbol(),
recognizer.getCurrentInputSymbol(),
recognizer.getCurrentInputSymbol(),
recognizer.getCurrentInputSymbol(),
null,
recognizer._ctx);
}
public NoViableAltException(BaseRecognizer recognizer,
IntStream input,
public <T> NoViableAltException(BaseRecognizer<T> recognizer,
ObjectStream<T> input,
Token startToken,
Token offendingToken,
T offendingNode,
OrderedHashSet<ATNConfig> deadEndConfigs,
RuleContext ctx)
{
super(recognizer, input, ctx);
this.deadEndConfigs = deadEndConfigs;
this.startToken = startToken;
this.offendingNode = offendingNode;
this.offendingToken = offendingToken;
}
}

View File

@ -32,31 +32,31 @@ package org.antlr.v4.runtime;
import org.antlr.v4.runtime.atn.ATNConfig;
import org.antlr.v4.runtime.misc.OrderedHashSet;
import org.antlr.v4.runtime.tree.ASTNodeStream;
import org.antlr.v4.runtime.tree.TreeParser;
public class NoViableTreeGrammarAltException extends NoViableAltException {
protected Object startNode;
protected Object offendingNode;
public NoViableTreeGrammarAltException(BaseRecognizer recognizer) {
public <T> NoViableTreeGrammarAltException(TreeParser<T> recognizer) {
this(recognizer,
(ASTNodeStream<Object>)recognizer.getInputStream(),
recognizer.getInputStream(),
recognizer.getCurrentInputSymbol(),
recognizer.getCurrentInputSymbol(),
null,
recognizer._ctx);
}
public NoViableTreeGrammarAltException(BaseRecognizer recognizer,
ASTNodeStream<Object> input,
Object startNode,
Object offendingNode,
public <T> NoViableTreeGrammarAltException(BaseRecognizer<T> recognizer,
ASTNodeStream<T> input,
T startNode,
T offendingNode,
OrderedHashSet<ATNConfig> deadEndConfigs,
RuleContext ctx) {
super(recognizer, input,
input.getTreeAdaptor().getToken(startNode),
input.getTreeAdaptor().getToken(offendingNode),
offendingNode,
deadEndConfigs, ctx);
this.startNode = startNode;
this.offendingNode = offendingNode;
}
}

View File

@ -29,15 +29,10 @@
package org.antlr.v4.runtime;
import org.antlr.v4.runtime.tree.ASTAdaptor;
import org.antlr.v4.runtime.tree.CommonASTAdaptor;
/** A parser for TokenStreams. "parser grammars" result in a subclass
* of this.
*/
public class Parser extends BaseRecognizer {
public ASTAdaptor _adaptor = new CommonASTAdaptor();
public class Parser extends BaseRecognizer<Token> {
protected TokenStream _input;
public Parser(TokenStream input) {
@ -60,7 +55,7 @@ public class Parser extends BaseRecognizer {
* to get trace facilities.
*/
@Override
public void enterRule(ParserRuleContext localctx, int ruleIndex) {
public void enterRule(ParserRuleContext<Token> localctx, int ruleIndex) {
_ctx = localctx;
_ctx.start = _input.LT(1);
_ctx.ruleIndex = ruleIndex;
@ -69,12 +64,12 @@ public class Parser extends BaseRecognizer {
@Override
public Token match(int ttype) throws RecognitionException {
return (Token)super.match(ttype);
return super.match(ttype);
}
@Override
protected Object getCurrentInputSymbol() {
return ((TokenStream)_input).LT(1);
public Token getCurrentInputSymbol() {
return _input.LT(1);
}
@Override
@ -91,7 +86,7 @@ public class Parser extends BaseRecognizer {
}
public TokenStream getTokenStream() {
return ((TokenStream)_input);
return _input;
}
@Override

View File

@ -48,9 +48,8 @@ import org.stringtemplate.v4.ST;
* group values such as this aggregate. The getters/setters are there to
* satisfy the superclass interface.
*/
public class ParserRuleContext extends RuleContext {
public Token start, stop;
public Object tree;
public class ParserRuleContext<SymbolType> extends RuleContext {
public SymbolType start, stop;
public ST st;
/** Set during parsing to identify which rule parser is in. */
@ -63,7 +62,7 @@ public class ParserRuleContext extends RuleContext {
/** COPY a ctx
*/
public void copyFrom(ParserRuleContext ctx) {
public void copyFrom(ParserRuleContext<SymbolType> ctx) {
// from RuleContext
this.parent = ctx.parent;
this.s = ctx.s;
@ -71,7 +70,6 @@ public class ParserRuleContext extends RuleContext {
this.start = ctx.start;
this.stop = ctx.stop;
this.tree = ctx.tree;
this.st = ctx.st;
this.ruleIndex = ctx.ruleIndex;
}
@ -83,8 +81,7 @@ public class ParserRuleContext extends RuleContext {
@Override
public int getRuleIndex() { return ruleIndex; }
public Object getTree() { return tree; }
public ST getTemplate() { return st; }
public Token getStart() { return start; }
public Token getStop() { return stop; }
public SymbolType getStart() { return start; }
public SymbolType getStop() { return stop; }
}

View File

@ -38,7 +38,7 @@ import org.antlr.v4.runtime.misc.IntervalSet;
*/
public class RecognitionException extends RuntimeException {
/** Who threw the exception? */
protected Recognizer recognizer;
protected Recognizer<?, ?> recognizer;
// TODO: make a dummy recognizer for the interpreter to use?
// Next two (ctx,input) should be what is in recognizer, but
@ -64,7 +64,7 @@ public class RecognitionException extends RuntimeException {
protected int offendingState;
public RecognitionException(Recognizer recognizer, IntStream input,
public RecognitionException(Recognizer<?, ?> recognizer, IntStream input,
RuleContext ctx)
{
this.recognizer = recognizer;
@ -82,8 +82,9 @@ public class RecognitionException extends RuntimeException {
public int getOffendingState() { return offendingState; }
public IntervalSet getExpectedTokens() {
// TODO: do we really need this type check?
if ( recognizer!=null && recognizer instanceof BaseRecognizer) {
return ((BaseRecognizer)recognizer)._interp.atn.nextTokens(ctx);
return recognizer._interp.atn.nextTokens(ctx);
}
return null;
}
@ -100,7 +101,7 @@ public class RecognitionException extends RuntimeException {
return offendingToken;
}
public Recognizer getRecognizer() {
public Recognizer<?, ?> getRecognizer() {
return recognizer;
}

View File

@ -29,15 +29,21 @@
package org.antlr.v4.runtime;
import com.sun.istack.internal.NotNull;
import com.sun.istack.internal.Nullable;
import org.antlr.v4.runtime.atn.ATN;
import org.antlr.v4.runtime.atn.ATNSimulator;
import java.util.*;
public abstract class Recognizer<ATNInterpreter> {
public abstract class Recognizer<TSymbol, ATNInterpreter extends ATNSimulator> {
public static final int EOF=-1;
protected ANTLRErrorStrategy _errHandler = new DefaultANTLRErrorStrategy();
protected List<ANTLRErrorListener> _listeners;
protected ANTLRErrorStrategy<TSymbol> _errHandler = new DefaultANTLRErrorStrategy();
private List<ANTLRErrorListener<TSymbol>> _listeners;
private static final ANTLRErrorListener[] EMPTY_LISTENERS = new ANTLRErrorListener[0];
protected ATNInterpreter _interp;
@ -194,32 +200,38 @@ public abstract class Recognizer<ATNInterpreter> {
return "'"+s+"'";
}
public void addListener(ANTLRErrorListener pl) {
public void addListener(ANTLRErrorListener<TSymbol> pl) {
if ( _listeners ==null ) {
_listeners =
Collections.synchronizedList(new ArrayList<ANTLRErrorListener>(2));
Collections.synchronizedList(new ArrayList<ANTLRErrorListener<TSymbol>>(2));
}
if ( pl!=null ) _listeners.add(pl);
}
public void removeListener(ANTLRErrorListener pl) { _listeners.remove(pl); }
public void removeListener(ANTLRErrorListener<TSymbol> pl) { _listeners.remove(pl); }
public void removeListeners() { _listeners.clear(); }
public List<ANTLRErrorListener> getListeners() { return _listeners; }
public @NotNull ANTLRErrorListener<TSymbol>[] getListeners() {
if (_listeners == null) {
return EMPTY_LISTENERS;
}
public ANTLRErrorStrategy getErrorHandler() { return _errHandler; }
return _listeners.toArray(EMPTY_LISTENERS);
}
public void setErrorHandler(ANTLRErrorStrategy h) { this._errHandler = h; }
public ANTLRErrorStrategy<TSymbol> getErrorHandler() { return _errHandler; }
public void setErrorHandler(ANTLRErrorStrategy<TSymbol> h) { this._errHandler = h; }
// subclass needs to override these if there are sempreds or actions
// that the ATN interp needs to execute
public boolean sempred(RuleContext _localctx, int ruleIndex, int actionIndex) {
public boolean sempred(@Nullable RuleContext _localctx, int ruleIndex, int actionIndex) {
return true;
}
/** In lexer, both indexes are same; one action per rule. */
public void action(RuleContext _localctx, int ruleIndex, int actionIndex) {
public void action(@Nullable RuleContext _localctx, int ruleIndex, int actionIndex) {
}
/** Create context for a rule reference IN fromRuleIndex using parent _localctx.

View File

@ -310,18 +310,18 @@ public class RuleContext implements ParseTree.RuleNode {
return new Interval(start, stop);
}
public void inspect(BaseRecognizer parser) {
public void inspect(BaseRecognizer<?> parser) {
TreeViewer viewer = new TreeViewer(parser, this);
viewer.open();
}
public void save(BaseRecognizer parser, String fileName)
public void save(BaseRecognizer<?> parser, String fileName)
throws IOException, PrintException
{
Trees.writePS(this, parser, fileName);
}
public void save(BaseRecognizer parser, String fileName,
public void save(BaseRecognizer<?> parser, String fileName,
String fontName, int fontSize)
throws IOException
{
@ -332,25 +332,25 @@ public class RuleContext implements ParseTree.RuleNode {
* (root child1 .. childN). Print just a node if this is a leaf.
* We have to know the recognizer so we can get rule names.
*/
public String toStringTree(BaseRecognizer recog) {
public String toStringTree(BaseRecognizer<?> recog) {
return Trees.toStringTree(this, recog);
}
@Override
public String toStringTree() { return toStringTree(null); }
public void enterRule(ParseTreeListener listener) { }
public void exitRule(ParseTreeListener listener) { }
public void enterRule(ParseTreeListener<?> listener) { }
public void exitRule(ParseTreeListener<?> listener) { }
public String toString() {
return toString(null);
}
public String toString(BaseRecognizer recog) {
public String toString(BaseRecognizer<?> recog) {
return toString(recog, RuleContext.EMPTY);
}
public String toString(BaseRecognizer recog, RuleContext stop) {
public String toString(BaseRecognizer<?> recog, RuleContext stop) {
StringBuilder buf = new StringBuilder();
RuleContext p = this;
buf.append("[");

View File

@ -1,19 +1,6 @@
package org.antlr.v4.runtime;
import org.stringtemplate.v4.ST;
public class TreeParserRuleContext extends ParserRuleContext {
// TODO: heh, these are duplicates of the fields above!
public Object start, stop;
public Object tree;
public ST st;
/** Set during parsing to identify which rule parser is in. */
public int ruleIndex;
/** Set during parsing to identify which alt of rule parser is in. */
public int altNum;
public class TreeParserRuleContext<T> extends ParserRuleContext<T> {
public TreeParserRuleContext() {
super();
}

View File

@ -142,7 +142,7 @@ public class ATNConfig {
return toString(null, true);
}
public String toString(Recognizer<?> recog, boolean showAlt) {
public String toString(Recognizer<?, ?> recog, boolean showAlt) {
StringBuilder buf = new StringBuilder();
// if ( state.ruleIndex>=0 ) {
// if ( recog!=null ) buf.append(recog.getRuleNames()[state.ruleIndex]+":");

View File

@ -37,7 +37,7 @@ import org.stringtemplate.v4.misc.MultiMap;
import java.util.*;
public class ParserATNSimulator extends ATNSimulator {
public class ParserATNSimulator<TSymbol> extends ATNSimulator {
public static boolean debug = false;
public static boolean dfa_debug = false;
@ -47,7 +47,7 @@ public class ParserATNSimulator extends ATNSimulator {
public static int retry_with_context_indicates_no_conflict = 0;
protected BaseRecognizer parser;
protected BaseRecognizer<TSymbol> parser;
public Map<RuleContext, DFA[]> ctxToDFAs;
public Map<RuleContext, DFA>[] decisionToDFAPerCtx; // TODO: USE THIS ONE
@ -73,7 +73,7 @@ public class ParserATNSimulator extends ATNSimulator {
decisionToDFA = new DFA[atn.getNumberOfDecisions()];
}
public ParserATNSimulator(BaseRecognizer parser, ATN atn) {
public ParserATNSimulator(BaseRecognizer<TSymbol> parser, ATN atn) {
super(atn);
this.parser = parser;
ctxToDFAs = new HashMap<RuleContext, DFA[]>();
@ -83,7 +83,7 @@ public class ParserATNSimulator extends ATNSimulator {
// System.out.println(dot.getDOT(atn.rules.get(1), parser.getRuleNames()));
}
public int adaptivePredict(ObjectStream input, int decision, RuleContext outerContext) {
public int adaptivePredict(ObjectStream<TSymbol> input, int decision, RuleContext outerContext) {
predict_calls++;
DFA dfa = decisionToDFA[decision];
if ( dfa==null || dfa.s0==null ) {
@ -108,7 +108,7 @@ public class ParserATNSimulator extends ATNSimulator {
}
}
public int predictATN(DFA dfa, ObjectStream input,
public int predictATN(DFA dfa, ObjectStream<TSymbol> input,
RuleContext outerContext,
boolean useContext)
{
@ -146,7 +146,7 @@ public class ParserATNSimulator extends ATNSimulator {
}
// doesn't create DFA when matching
public int matchATN(ObjectStream input, ATNState startState) {
public int matchATN(ObjectStream<TSymbol> input, ATNState startState) {
DFA dfa = new DFA(startState);
if ( outerContext==null ) outerContext = RuleContext.EMPTY;
RuleContext ctx = RuleContext.EMPTY;
@ -154,7 +154,7 @@ public class ParserATNSimulator extends ATNSimulator {
return execATN(input, dfa, input.index(), s0_closure, false);
}
public int execDFA(ObjectStream input, DFA dfa, DFAState s0, RuleContext outerContext) {
public int execDFA(ObjectStream<TSymbol> input, DFA dfa, DFAState s0, RuleContext outerContext) {
// dump(dfa);
if ( outerContext==null ) outerContext = RuleContext.EMPTY;
this.outerContext = outerContext;
@ -241,17 +241,17 @@ public class ParserATNSimulator extends ATNSimulator {
return prevAcceptState.prediction;
}
public String getInputString(ObjectStream input, int start) {
public String getInputString(ObjectStream<TSymbol> input, int start) {
if ( input instanceof TokenStream ) {
return ((TokenStream)input).toString(start,input.index());
}
else if ( input instanceof ASTNodeStream) {
return ((ASTNodeStream)input).toString(start,input.index());
return ((ASTNodeStream<TSymbol>)input).toString(input.get(start),input.LT(1));
}
return "n/a";
}
public int execATN(ObjectStream input,
public int execATN(ObjectStream<TSymbol> input,
DFA dfa,
int startIndex,
OrderedHashSet<ATNConfig> s0,
@ -405,7 +405,7 @@ public class ParserATNSimulator extends ATNSimulator {
return exitAlt;
}
public int retryWithContext(ObjectStream input,
public int retryWithContext(ObjectStream<TSymbol> input,
DFA dfa,
int startIndex,
RuleContext originalContext,
@ -823,7 +823,7 @@ public class ParserATNSimulator extends ATNSimulator {
return String.valueOf(t);
}
public String getLookaheadName(ObjectStream input) {
public String getLookaheadName(ObjectStream<TSymbol> input) {
return getTokenName(input.LA(1));
}
@ -849,16 +849,16 @@ public class ParserATNSimulator extends ATNSimulator {
}
}
public int throwNoViableAlt(ObjectStream input, RuleContext outerContext,
public int throwNoViableAlt(ObjectStream<TSymbol> input, RuleContext outerContext,
OrderedHashSet<ATNConfig> configs, int startIndex)
{
if ( parser instanceof TreeParser) {
Object startNode = null;
TSymbol startNode = null;
if ( input instanceof BufferedASTNodeStream ) {
startNode = input.get(startIndex);
}
throw new NoViableTreeGrammarAltException(parser,
(ASTNodeStream<Object>)input,
(ASTNodeStream<TSymbol>)input,
startNode,
input.LT(1),
configs, outerContext);
@ -867,6 +867,7 @@ public class ParserATNSimulator extends ATNSimulator {
throw new NoViableAltException(parser, input,
(Token)input.get(startIndex),
(Token)input.LT(1),
input.LT(1),
configs, outerContext);
}
}

View File

@ -0,0 +1,34 @@
/*
[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.tree;
public interface ASTContext<T> {
T getTree();
}

View File

@ -258,18 +258,18 @@ public abstract class BaseAST implements AST {
*/
public List<? extends Tree> getAncestors() { return Trees.getAncestors(this); }
public void inspect(BaseRecognizer parser) {
public void inspect(BaseRecognizer<?> parser) {
TreeViewer viewer = new TreeViewer(parser, this);
viewer.open();
}
public void save(BaseRecognizer parser, String fileName)
public void save(BaseRecognizer<?> parser, String fileName)
throws IOException
{
Trees.writePS(this, parser, fileName);
}
public void save(BaseRecognizer parser, String fileName,
public void save(BaseRecognizer<?> parser, String fileName,
String fontName, int fontSize)
throws IOException
{

View File

@ -32,8 +32,8 @@ package org.antlr.v4.runtime.tree;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
public interface ParseTreeListener {
public interface ParseTreeListener<TSymbol> {
void visitToken(Token token);
void enterEveryRule(ParserRuleContext ctx);
void exitEveryRule(ParserRuleContext ctx);
void enterEveryRule(ParserRuleContext<TSymbol> ctx);
void exitEveryRule(ParserRuleContext<TSymbol> ctx);
}

View File

@ -34,7 +34,7 @@ import org.antlr.v4.runtime.ParserRuleContext;
public class ParseTreeWalker {
public static final ParseTreeWalker DEFAULT = new ParseTreeWalker();
public void walk(ParseTreeListener listener, ParseTree t) {
public <TSymbol> void walk(ParseTreeListener<TSymbol> listener, ParseTree t) {
if ( t instanceof ParseTree.TokenNode) {
visitToken(listener, (ParseTree.TokenNode) t);
return;
@ -48,7 +48,7 @@ public class ParseTreeWalker {
exitRule(listener, r);
}
protected void visitToken(ParseTreeListener listener, ParseTree.TokenNode t) {
protected <TSymbol> void visitToken(ParseTreeListener<TSymbol> listener, ParseTree.TokenNode t) {
listener.visitToken(t.getToken());
}
@ -57,14 +57,14 @@ public class ParseTreeWalker {
* First we trigger the generic and then the rule specific.
* We to them in reverse order upon finishing the node.
*/
protected void enterRule(ParseTreeListener listener, ParseTree.RuleNode r) {
ParserRuleContext ctx = (ParserRuleContext)r.getRuleContext();
listener.enterEveryRule((ParserRuleContext) r.getRuleContext());
protected <TSymbol> void enterRule(ParseTreeListener<TSymbol> listener, ParseTree.RuleNode r) {
ParserRuleContext<TSymbol> ctx = (ParserRuleContext<TSymbol>)r.getRuleContext();
listener.enterEveryRule((ParserRuleContext<TSymbol>) r.getRuleContext());
ctx.enterRule(listener);
}
protected void exitRule(ParseTreeListener listener, ParseTree.RuleNode r) {
ParserRuleContext ctx = (ParserRuleContext)r.getRuleContext();
protected <TSymbol> void exitRule(ParseTreeListener<TSymbol> listener, ParseTree.RuleNode r) {
ParserRuleContext<TSymbol> ctx = (ParserRuleContext<TSymbol>)r.getRuleContext();
ctx.exitRule(listener);
listener.exitEveryRule(ctx);
}

View File

@ -75,7 +75,7 @@ or both. In our case, we need to call @m applyOnce in both. On the way
down, we'll look for @r vmult patterns. On the way up,
we'll look for @r mult0 patterns.
*/
public class TreeFilter<T> extends TreeParser {
public class TreeFilter<T> extends TreeParser<T> {
public interface fptr {
public void rule() throws RecognitionException;
}
@ -94,15 +94,15 @@ public class TreeFilter<T> extends TreeParser {
try {
// share TreeParser object but not parsing-related state
_input = new CommonASTNodeStream<T>(originalAdaptor, t);
((CommonASTNodeStream) _input).setTokenStream(originalTokenStream);
((CommonASTNodeStream<T>) _input).setTokenStream(originalTokenStream);
whichRule.rule();
}
catch (RecognitionException e) { }
}
public void downup(T t) {
TreeVisitor v = new TreeVisitor(new CommonASTAdaptor());
TreeVisitorAction actions = new TreeVisitorAction<T>() {
TreeVisitor<T> v = new TreeVisitor<T>((ASTAdaptor<T>)new CommonASTAdaptor());
TreeVisitorAction<T> actions = new TreeVisitorAction<T>() {
@Override
public T pre(T t) { applyOnce(t, topdown_fptr); return t; }
@Override

View File

@ -37,7 +37,7 @@ import java.util.regex.*;
* of this. All the error reporting and recovery is shared with Parser via
* the BaseRecognizer superclass.
*/
public class TreeParser<T> extends BaseRecognizer {
public class TreeParser<T> extends BaseRecognizer<T> {
public static final int DOWN = Token.DOWN;
public static final int UP = Token.UP;
@ -65,7 +65,7 @@ public class TreeParser<T> extends BaseRecognizer {
}
@Override
protected T getCurrentInputSymbol() { return _input.LT(1); }
public T getCurrentInputSymbol() { return _input.LT(1); }
@Override
public ASTNodeStream<T> getInputStream() { return _input; }
@ -79,13 +79,14 @@ public class TreeParser<T> extends BaseRecognizer {
*
* This is flexible because users do not have to regenerate parsers
* to get trace facilities.
*
* TODO: this shouldn't be needed now that ParserRuleContext is generic.
*/
@Override
public void enterRule(ParserRuleContext localctx, int ruleIndex) {
TreeParserRuleContext tctx = (TreeParserRuleContext)localctx;
_ctx = tctx;
tctx.start = _input.LT(1);
tctx.ruleIndex = ruleIndex;
public void enterRule(ParserRuleContext<T> localctx, int ruleIndex) {
_ctx = localctx;
_ctx.start = _input.LT(1);
_ctx.ruleIndex = ruleIndex;
}
@Override

View File

@ -34,22 +34,23 @@ import org.antlr.v4.runtime.*;
public class TreePatternParser {
protected TreePatternLexer tokenizer;
protected int ttype;
protected TreeWizard wizard;
protected ASTAdaptor adaptor;
protected TreeWizard<?> wizard;
// TODO: would be nice to use ASTAdaptor<TreeWizard.TreePattern>...
protected ASTAdaptor<CommonAST> adaptor;
public TreePatternParser(TreePatternLexer tokenizer, TreeWizard wizard, ASTAdaptor adaptor) {
public TreePatternParser(TreePatternLexer tokenizer, TreeWizard<?> wizard, ASTAdaptor<CommonAST> adaptor) {
this.tokenizer = tokenizer;
this.wizard = wizard;
this.adaptor = adaptor;
ttype = tokenizer.nextToken(); // kickstart
}
public Object pattern() {
public TreeWizard.TreePattern pattern() {
if ( ttype==TreePatternLexer.BEGIN ) {
return parseTree();
}
else if ( ttype==TreePatternLexer.ID ) {
Object node = parseNode();
TreeWizard.TreePattern node = parseNode();
if ( ttype==TreePatternLexer.EOF ) {
return node;
}
@ -58,12 +59,12 @@ public class TreePatternParser {
return null;
}
public Object parseTree() {
public TreeWizard.TreePattern parseTree() {
if ( ttype != TreePatternLexer.BEGIN ) {
throw new RuntimeException("no BEGIN");
}
ttype = tokenizer.nextToken();
Object root = parseNode();
TreeWizard.TreePattern root = parseNode();
if ( root==null ) {
return null;
}
@ -73,11 +74,11 @@ public class TreePatternParser {
ttype==TreePatternLexer.DOT )
{
if ( ttype==TreePatternLexer.BEGIN ) {
Object subtree = parseTree();
TreeWizard.TreePattern subtree = parseTree();
adaptor.addChild(root, subtree);
}
else {
Object child = parseNode();
TreeWizard.TreePattern child = parseNode();
if ( child==null ) {
return null;
}
@ -91,7 +92,7 @@ public class TreePatternParser {
return root;
}
public Object parseNode() {
public TreeWizard.TreePattern parseNode() {
// "%label:" prefix
String label = null;
if ( ttype == TreePatternLexer.PERCENT ) {
@ -126,7 +127,7 @@ public class TreePatternParser {
String tokenName = tokenizer.sval.toString();
ttype = tokenizer.nextToken();
if ( tokenName.equals("nil") ) {
return adaptor.nil();
return (TreeWizard.TreePattern)adaptor.nil();
}
String text = tokenName;
// check for arg
@ -142,13 +143,13 @@ public class TreePatternParser {
if ( treeNodeType== Token.INVALID_TYPE ) {
return null;
}
Object node;
node = adaptor.create(treeNodeType, text);
TreeWizard.TreePattern node;
node = (TreeWizard.TreePattern)adaptor.create(treeNodeType, text);
if ( label!=null && node.getClass()==TreeWizard.TreePattern.class ) {
((TreeWizard.TreePattern)node).label = label;
node.label = label;
}
if ( arg!=null && node.getClass()==TreeWizard.TreePattern.class ) {
((TreeWizard.TreePattern)node).hasTextArg = true;
node.hasTextArg = true;
}
return node;
}

View File

@ -32,13 +32,14 @@ package org.antlr.v4.runtime.tree;
/** Do a depth first walk of a tree, applying pre() and post() actions
* as we discover and finish nodes.
*/
public class TreeVisitor {
protected ASTAdaptor adaptor;
public class TreeVisitor<T> {
protected ASTAdaptor<T> adaptor;
public TreeVisitor(ASTAdaptor adaptor) {
public TreeVisitor(ASTAdaptor<T> adaptor) {
this.adaptor = adaptor;
}
public TreeVisitor() { this(new CommonASTAdaptor()); }
public TreeVisitor() { this((ASTAdaptor<T>)new CommonASTAdaptor()); }
/** Visit every node in tree t and trigger an action for each node
* before/after having visited all of its children.
@ -50,16 +51,16 @@ public class TreeVisitor {
*
* Return result of applying post action to this node.
*/
public Object visit(Object t, TreeVisitorAction action) {
public T visit(T t, TreeVisitorAction<T> action) {
// System.out.println("visit "+((Tree)t).toStringTree());
boolean isNil = adaptor.isNil(t);
if ( action!=null && !isNil ) {
t = action.pre(t); // if rewritten, walk children of new t
}
for (int i=0; i<adaptor.getChildCount(t); i++) {
Object child = adaptor.getChild(t, i);
Object visitResult = visit(child, action);
Object childAfterVisit = adaptor.getChild(t, i);
T child = adaptor.getChild(t, i);
T visitResult = visit(child, action);
T childAfterVisit = adaptor.getChild(t, i);
if ( visitResult != childAfterVisit ) { // result & child differ?
adaptor.setChild(t, i, visitResult);
}

View File

@ -29,6 +29,7 @@
package org.antlr.v4.runtime.tree;
import com.sun.istack.internal.Nullable;
import org.antlr.v4.runtime.Token;
import java.util.*;
@ -49,20 +50,21 @@ import java.util.*;
* patterns like "(A B C)". You can create a tree from that pattern or
* match subtrees against it.
*/
public class TreeWizard {
protected ASTAdaptor adaptor;
protected Map tokenNameToTypeMap;
public class TreeWizard<T> {
protected ASTAdaptor<T> adaptor;
protected Map<String, Integer> tokenNameToTypeMap;
public interface ContextVisitor {
public interface ContextVisitor<T> {
// TODO: should this be called visit or something else?
public void visit(Object t, Object parent, int childIndex, Map labels);
public void visit(T t, Object parent, int childIndex, @Nullable Map<String, T> labels);
}
public static abstract class Visitor implements ContextVisitor {
public void visit(Object t, Object parent, int childIndex, Map labels) {
public static abstract class Visitor<T> implements ContextVisitor<T> {
@Override
public void visit(T t, Object parent, int childIndex, Map<String, T> labels) {
visit(t);
}
public abstract void visit(Object t);
public abstract void visit(T t);
}
/** When using %label:TOKENNAME in a tree for parse(), we must
@ -118,35 +120,35 @@ public class TreeWizard {
protected Set tokenTypesToReverseIndex = null;
*/
public TreeWizard(ASTAdaptor adaptor) {
public TreeWizard(ASTAdaptor<T> adaptor) {
this.adaptor = adaptor;
}
public TreeWizard(ASTAdaptor adaptor, Map tokenNameToTypeMap) {
public TreeWizard(ASTAdaptor<T> adaptor, Map<String, Integer> tokenNameToTypeMap) {
this.adaptor = adaptor;
this.tokenNameToTypeMap = tokenNameToTypeMap;
}
public TreeWizard(ASTAdaptor adaptor, String[] tokenNames) {
public TreeWizard(ASTAdaptor<T> adaptor, String[] tokenNames) {
this.adaptor = adaptor;
this.tokenNameToTypeMap = computeTokenTypes(tokenNames);
}
public TreeWizard(String[] tokenNames) {
this(new CommonASTAdaptor(), tokenNames);
this((ASTAdaptor<T>)new TreePatternASTAdaptor(), tokenNames);
}
/** Compute a Map<String, Integer> that is an inverted index of
* tokenNames (which maps int token types to names).
*/
public Map computeTokenTypes(String[] tokenNames) {
Map m = new HashMap();
public Map<String, Integer> computeTokenTypes(String[] tokenNames) {
Map<String, Integer> m = new HashMap<String, Integer>();
if ( tokenNames==null ) {
return m;
}
for (int ttype = Token.MIN_TOKEN_TYPE; ttype < tokenNames.length; ttype++) {
String name = tokenNames[ttype];
m.put(name, new Integer(ttype));
m.put(name, ttype);
}
return m;
}
@ -156,9 +158,9 @@ public class TreeWizard {
if ( tokenNameToTypeMap==null ) {
return Token.INVALID_TYPE;
}
Integer ttypeI = (Integer)tokenNameToTypeMap.get(tokenName);
Integer ttypeI = tokenNameToTypeMap.get(tokenName);
if ( ttypeI!=null ) {
return ttypeI.intValue();
return ttypeI;
}
return Token.INVALID_TYPE;
}
@ -170,36 +172,37 @@ public class TreeWizard {
*
* TODO: save this index so that find and visit are faster
*/
public Map index(Object t) {
Map m = new HashMap();
public Map<Integer, List<T>> index(T t) {
Map<Integer, List<T>> m = new HashMap<Integer, List<T>>();
_index(t, m);
return m;
}
/** Do the work for index */
protected void _index(Object t, Map m) {
protected void _index(T t, Map<Integer, List<T>> m) {
if ( t==null ) {
return;
}
int ttype = adaptor.getType(t);
List elements = (List)m.get(new Integer(ttype));
List<T> elements = m.get(ttype);
if ( elements==null ) {
elements = new ArrayList();
m.put(new Integer(ttype), elements);
elements = new ArrayList<T>();
m.put(ttype, elements);
}
elements.add(t);
int n = adaptor.getChildCount(t);
for (int i=0; i<n; i++) {
Object child = adaptor.getChild(t, i);
T child = adaptor.getChild(t, i);
_index(child, m);
}
}
/** Return a List of tree nodes with token type ttype */
public List find(Object t, int ttype) {
final List nodes = new ArrayList();
visit(t, ttype, new TreeWizard.Visitor() {
public void visit(Object t) {
public List<T> find(T t, int ttype) {
final List<T> nodes = new ArrayList<T>();
visit(t, ttype, new TreeWizard.Visitor<T>() {
@Override
public void visit(T t) {
nodes.add(t);
}
});
@ -207,13 +210,13 @@ public class TreeWizard {
}
/** Return a List of subtrees matching pattern. */
public List find(Object t, String pattern) {
final List subtrees = new ArrayList();
public List<T> find(T t, String pattern) {
final List<T> subtrees = new ArrayList<T>();
// Create a TreePattern from the pattern
TreePatternLexer tokenizer = new TreePatternLexer(pattern);
TreePatternParser parser =
new TreePatternParser(tokenizer, this, new TreePatternASTAdaptor());
final TreePattern tpattern = (TreePattern)parser.pattern();
final TreePattern tpattern = parser.pattern();
// don't allow invalid patterns
if ( tpattern==null ||
tpattern.isNil() ||
@ -222,8 +225,9 @@ public class TreeWizard {
return null;
}
int rootTokenType = tpattern.getType();
visit(t, rootTokenType, new TreeWizard.ContextVisitor() {
public void visit(Object t, Object parent, int childIndex, Map labels) {
visit(t, rootTokenType, new TreeWizard.ContextVisitor<T>() {
@Override
public void visit(T t, Object parent, int childIndex, Map<String, T> labels) {
if ( _parse(t, tpattern, null) ) {
subtrees.add(t);
}
@ -232,11 +236,11 @@ public class TreeWizard {
return subtrees;
}
public Object findFirst(Object t, int ttype) {
public T findFirst(T t, int ttype) {
return null;
}
public Object findFirst(Object t, String pattern) {
public T findFirst(T t, String pattern) {
return null;
}
@ -245,12 +249,12 @@ public class TreeWizard {
* of the visitor action method is never set (it's null) since using
* a token type rather than a pattern doesn't let us set a label.
*/
public void visit(Object t, int ttype, ContextVisitor visitor) {
public void visit(T t, int ttype, ContextVisitor<T> visitor) {
_visit(t, null, 0, ttype, visitor);
}
/** Do the recursive work for visit */
protected void _visit(Object t, Object parent, int childIndex, int ttype, ContextVisitor visitor) {
protected void _visit(T t, @Nullable Object parent, int childIndex, int ttype, ContextVisitor<T> visitor) {
if ( t==null ) {
return;
}
@ -259,7 +263,7 @@ public class TreeWizard {
}
int n = adaptor.getChildCount(t);
for (int i=0; i<n; i++) {
Object child = adaptor.getChild(t, i);
T child = adaptor.getChild(t, i);
_visit(child, t, i, ttype, visitor);
}
}
@ -269,12 +273,12 @@ public class TreeWizard {
* with visit(t, ttype, visitor) so nil-rooted patterns are not allowed.
* Patterns with wildcard roots are also not allowed.
*/
public void visit(Object t, final String pattern, final ContextVisitor visitor) {
public void visit(T t, final String pattern, final ContextVisitor<T> visitor) {
// Create a TreePattern from the pattern
TreePatternLexer tokenizer = new TreePatternLexer(pattern);
TreePatternParser parser =
new TreePatternParser(tokenizer, this, new TreePatternASTAdaptor());
final TreePattern tpattern = (TreePattern)parser.pattern();
final TreePattern tpattern = parser.pattern();
// don't allow invalid patterns
if ( tpattern==null ||
tpattern.isNil() ||
@ -282,10 +286,11 @@ public class TreeWizard {
{
return;
}
final Map labels = new HashMap(); // reused for each _parse
final Map<String, T> labels = new HashMap<String, T>(); // reused for each _parse
int rootTokenType = tpattern.getType();
visit(t, rootTokenType, new TreeWizard.ContextVisitor() {
public void visit(Object t, Object parent, int childIndex, Map unusedlabels) {
visit(t, rootTokenType, new TreeWizard.ContextVisitor<T>() {
@Override
public void visit(T t, Object parent, int childIndex, Map<String, T> unusedlabels) {
// the unusedlabels arg is null as visit on token type doesn't set.
labels.clear();
if ( _parse(t, tpattern, labels) ) {
@ -306,11 +311,11 @@ public class TreeWizard {
*
* TODO: what's a better way to indicate bad pattern? Exceptions are a hassle
*/
public boolean parse(Object t, String pattern, Map labels) {
public boolean parse(T t, String pattern, @Nullable Map<String, T> labels) {
TreePatternLexer tokenizer = new TreePatternLexer(pattern);
TreePatternParser parser =
new TreePatternParser(tokenizer, this, new TreePatternASTAdaptor());
TreePattern tpattern = (TreePattern)parser.pattern();
TreePattern tpattern = parser.pattern();
/*
System.out.println("t="+((Tree)t).toStringTree());
System.out.println("scant="+tpattern.toStringTree());
@ -319,7 +324,7 @@ public class TreeWizard {
return matched;
}
public boolean parse(Object t, String pattern) {
public boolean parse(T t, String pattern) {
return parse(t, pattern, null);
}
@ -328,7 +333,7 @@ public class TreeWizard {
* text arguments on nodes. Fill labels map with pointers to nodes
* in tree matched against nodes in pattern with labels.
*/
protected boolean _parse(Object t1, TreePattern tpattern, Map labels) {
protected boolean _parse(T t1, TreePattern tpattern, @Nullable Map<String, T> labels) {
// make sure both are non-null
if ( t1==null || tpattern==null ) {
return false;
@ -352,7 +357,7 @@ public class TreeWizard {
return false;
}
for (int i=0; i<n1; i++) {
Object child1 = adaptor.getChild(t1, i);
T child1 = adaptor.getChild(t1, i);
TreePattern child2 = (TreePattern)tpattern.getChild(i);
if ( !_parse(child1, child2, labels) ) {
return false;
@ -374,10 +379,10 @@ public class TreeWizard {
* nil is a special name meaning "give me a nil node". Useful for
* making lists: (nil A B C) is a list of A B C.
*/
public Object create(String pattern) {
public TreePattern create(String pattern) {
TreePatternLexer tokenizer = new TreePatternLexer(pattern);
TreePatternParser parser = new TreePatternParser(tokenizer, this, adaptor);
Object t = parser.pattern();
TreePatternParser parser = new TreePatternParser(tokenizer, this, new TreePatternASTAdaptor());
TreePattern t = parser.pattern();
return t;
}
@ -390,18 +395,18 @@ public class TreeWizard {
* I cannot rely on the tree node's equals() implementation as I make
* no constraints at all on the node types nor interface etc...
*/
public static boolean equals(Object t1, Object t2, ASTAdaptor adaptor) {
public static <T> boolean equals(T t1, T t2, ASTAdaptor<T> adaptor) {
return _equals(t1, t2, adaptor);
}
/** Compare type, structure, and text of two trees, assuming adaptor in
* this instance of a TreeWizard.
*/
public boolean equals(Object t1, Object t2) {
public boolean equals(T t1, T t2) {
return _equals(t1, t2, adaptor);
}
protected static boolean _equals(Object t1, Object t2, ASTAdaptor adaptor) {
protected static <T> boolean _equals(T t1, T t2, ASTAdaptor<T> adaptor) {
// make sure both are non-null
if ( t1==null || t2==null ) {
return false;
@ -420,8 +425,8 @@ public class TreeWizard {
return false;
}
for (int i=0; i<n1; i++) {
Object child1 = adaptor.getChild(t1, i);
Object child2 = adaptor.getChild(t2, i);
T child1 = adaptor.getChild(t1, i);
T child2 = adaptor.getChild(t2, i);
if ( !_equals(child1, child2, adaptor) ) {
return false;
}

View File

@ -44,7 +44,7 @@ import java.util.TreeSet;
/** A set of utility routines useful for all kinds of ANTLR trees */
public class Trees {
public static String getPS(Tree t, BaseRecognizer recog,
public static String getPS(Tree t, BaseRecognizer<?> recog,
String fontName, int fontSize)
{
TreePostScriptGenerator psgen =
@ -52,11 +52,11 @@ public class Trees {
return psgen.getPS();
}
public static String getPS(Tree t, BaseRecognizer recog) {
public static String getPS(Tree t, BaseRecognizer<?> recog) {
return getPS(t, recog, "Helvetica", 11);
}
public static void writePS(Tree t, BaseRecognizer recog,
public static void writePS(Tree t, BaseRecognizer<?> recog,
String fileName,
String fontName, int fontSize)
throws IOException
@ -68,7 +68,7 @@ public class Trees {
bw.close();
}
public static void writePS(Tree t, BaseRecognizer recog, String fileName)
public static void writePS(Tree t, BaseRecognizer<?> recog, String fileName)
throws IOException
{
writePS(t, recog, fileName, "Helvetica", 11);
@ -78,7 +78,7 @@ public class Trees {
* node payloads to get the text for the nodes. Detect
* parse trees and extract data appropriately.
*/
public static String toStringTree(Tree t, BaseRecognizer recog) {
public static String toStringTree(Tree t, BaseRecognizer<?> recog) {
if ( t.getChildCount()==0 ) return getNodeText(t, recog);
StringBuilder buf = new StringBuilder();
boolean nilRoot = t instanceof AST && ((AST)t).isNil();
@ -97,7 +97,7 @@ public class Trees {
return buf.toString();
}
public static String getNodeText(Tree t, BaseRecognizer recog) {
public static String getNodeText(Tree t, BaseRecognizer<?> recog) {
if ( t instanceof AST ) {
return t.toString();
}
@ -174,7 +174,7 @@ public class Trees {
int replacingHowMany = stopChildIndex - startChildIndex + 1;
int replacingWithHowMany;
BaseAST newTree = (BaseAST)t;
List<BaseAST> newChildren = null;
List<BaseAST> newChildren;
// normalize to a list of children to add: newChildren
if ( newTree.isNil() ) {
newChildren = newTree.children;
@ -190,7 +190,7 @@ public class Trees {
if ( delta == 0 ) {
int j = 0; // index into new children
for (int i=startChildIndex; i<=stopChildIndex; i++) {
BaseAST child = (BaseAST)newChildren.get(j);
BaseAST child = newChildren.get(j);
tree.setChild(i, child);
child.setParent(tree);
child.setChildIndex(i);
@ -223,18 +223,18 @@ public class Trees {
//System.out.println("out="+toStringTree());
}
public static AST dupTree(ASTAdaptor adaptor, AST t, AST parent) {
public static <T> T dupTree(ASTAdaptor<T> adaptor, T t, T parent) {
if ( t==null ) {
return null;
}
AST newTree = (AST)adaptor.dupNode(t);
T newTree = adaptor.dupNode(t);
// ensure new subtree root has parent/child index set
adaptor.setChildIndex(newTree, adaptor.getChildIndex(t)); // same index in new tree
adaptor.setParent(newTree, parent);
int n = adaptor.getChildCount(t);
for (int i = 0; i < n; i++) {
AST child = (AST)adaptor.getChild(t, i);
Object newSubTree = dupTree(adaptor, child, t);
T child = adaptor.getChild(t, i);
T newSubTree = dupTree(adaptor, child, t);
adaptor.addChild(newTree, newSubTree);
}
return newTree;
@ -253,12 +253,12 @@ public class Trees {
}
int n = t.getChildCount();
for (int i = 0; i < n; i++) {
setUnknownTokenBoundaries((CommonAST) t.getChild(i));
setUnknownTokenBoundaries(t.getChild(i));
}
if ( t.startIndex>=0 && t.stopIndex>=0 ) return; // already set
if ( t.getChildCount() > 0 ) {
CommonAST firstChild = (CommonAST)t.getChild(0);
CommonAST lastChild = (CommonAST)t.getChild(t.getChildCount()-1);
CommonAST firstChild = t.getChild(0);
CommonAST lastChild = t.getChild(t.getChildCount()-1);
t.startIndex = firstChild.getTokenStartIndex();
t.stopIndex = lastChild.getTokenStopIndex();
}

View File

@ -68,11 +68,11 @@ public class TreePostScriptGenerator {
protected PostScriptDocument doc;
public TreePostScriptGenerator(BaseRecognizer parser, Tree root) {
public TreePostScriptGenerator(BaseRecognizer<?> parser, Tree root) {
this(parser, root, "CourierNew", 11);
}
public TreePostScriptGenerator(BaseRecognizer parser, Tree root,
public TreePostScriptGenerator(BaseRecognizer<?> parser, Tree root,
String fontName, int fontSize)
{
this.root = root;

View File

@ -45,8 +45,9 @@ public class TreeViewer extends JComponent {
public static final Color LIGHT_RED = new Color(244, 213, 211);
public static class DefaultTreeTextProvider implements TreeTextProvider {
BaseRecognizer parser;
public DefaultTreeTextProvider(BaseRecognizer parser) {
BaseRecognizer<?> parser;
public DefaultTreeTextProvider(BaseRecognizer<?> parser) {
this.parser = parser;
}
@ -105,9 +106,9 @@ public class TreeViewer extends JComponent {
protected Color borderColor = Color.white;
protected Color textColor = Color.black;
protected BaseRecognizer parser;
protected BaseRecognizer<?> parser;
public TreeViewer(BaseRecognizer parser, Tree tree) {
public TreeViewer(BaseRecognizer<?> parser, Tree tree) {
this.parser = parser;
setTreeTextProvider(new DefaultTreeTextProvider(parser));
this.treeLayout =

View File

@ -53,8 +53,8 @@ public class Blank<listener.grammarName>Listener implements <listener.grammarNam
@Override public void enterRule(<listener.parserName>.<lname>Context ctx) { \}
@Override public void exitRule(<listener.parserName>.<lname>Context ctx) { \}}; separator="\n">
@Override public void enterEveryRule(ParserRuleContext ctx) { }
@Override public void exitEveryRule(ParserRuleContext ctx) { }
@Override public void enterEveryRule(ParserRuleContext\<<TokenLabelType()> > ctx) { }
@Override public void exitEveryRule(ParserRuleContext\<<TokenLabelType()> > ctx) { }
@Override public void visitToken(Token token) { }
}
>>
@ -459,6 +459,16 @@ setState(<p.stateNumber>);
if (!(<chunks>)) throw new FailedPredicateException(this, <if(p.msg)><p.msg><else><failChunks><endif>);
>>
ParserASTExtensionMembers(s) ::= <<
public ASTAdaptor\<<ASTLabelType()> > _adaptor = (ASTAdaptor)new CommonASTAdaptor();
>>
ParserASTContextInterface(s) ::= "ASTContext\<<ASTLabelType()> >"
ParserASTTreeFieldDecl(s) ::= "<ASTLabelType()> tree"
ParserASTContextMembers(s) ::= <<
@Override public <ASTLabelType()> getTree() { return tree; }
>>
DefaultParserSuperClass(s) ::= "Parser"
DefaultTreeParserSuperClass(s) ::= "TreeParser\<<ASTLabelType()>>"
@ -539,7 +549,7 @@ ListLabelName(label) ::= "<label>_list"
CaptureNextToken(d) ::= "<d.varName> = _input.LT(1);"
CaptureNextTokenType(d) ::= "<d.varName> = _input.LA(1);"
StructDecl(s,attrs,visitorDispatchMethods,interfaces,extensionMembers,superClass="ParserRuleContext") ::= <<
StructDecl(s,attrs,visitorDispatchMethods,interfaces,extensionMembers,superClass={ParserRuleContext\<<TokenLabelType()>>}) ::= <<
public static class <s.name> extends <superClass><if(interfaces)> implements <interfaces; separator=", "><endif> {
<attrs:{a | public <a>;}; separator="\n">
<if(s.ctorAttrs)>public <s.name>(RuleContext parent, int state) { super(parent, state); }<endif>
@ -560,7 +570,7 @@ public static class <s.name> extends <superClass><if(interfaces)> implements <in
>>
TreeParserStructDecl(s,attrs,visitorDispatchMethods) ::= <<
<StructDecl(superClass="TreeParserRuleContext", ...)>
<StructDecl(superClass={TreeParserRuleContext\<<ASTLabelType()> >}, ...)>
>>
AltLabelStructDecl(s,attrs,visitorDispatchMethods) ::= <<

View File

@ -30,11 +30,13 @@
package org.antlr.v4.codegen;
import org.antlr.v4.codegen.model.*;
import org.antlr.v4.codegen.model.actions.ParserASTExtensionMembers;
import org.antlr.v4.codegen.model.ast.*;
import org.antlr.v4.codegen.model.decl.*;
import org.antlr.v4.misc.Utils;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.tool.Alternative;
import org.antlr.v4.tool.Attribute;
import org.antlr.v4.tool.ast.GrammarAST;
import java.util.List;
@ -44,6 +46,26 @@ public class ParserASTExtension extends CodeGeneratorExtension {
super(factory);
}
@Override
public ParserFile parserFile(ParserFile file) {
Action members = file.namedActions.get("members");
if (members == null) {
members = new Action(factory, null);
file.namedActions.put("members", members);
}
members.chunks.add(new ParserASTExtensionMembers());
return super.parserFile(file);
}
@Override
public RuleFunction rule(RuleFunction rf) {
rf.ruleCtx.addDecl(new ParserASTTreeFieldDecl(factory));
rf.ruleCtx.addExtensionMember(new ParserASTContextMembers());
rf.ruleCtx.implementInterface(new ParserASTContextInterface());
return super.rule(rf);
}
@Override
public Choice getChoiceBlock(Choice choice) {
Alternative alt = factory.getCurrentOuterMostAlt();

View File

@ -0,0 +1,33 @@
/*
[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.codegen.model.actions;
public class ParserASTExtensionMembers extends ActionChunk {
}

View File

@ -0,0 +1,35 @@
/*
[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.codegen.model.ast;
import org.antlr.v4.codegen.model.OutputModelObject;
public class ParserASTContextInterface extends OutputModelObject {
}

View File

@ -0,0 +1,35 @@
/*
[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.codegen.model.ast;
import org.antlr.v4.codegen.model.OutputModelObject;
public class ParserASTContextMembers extends OutputModelObject {
}

View File

@ -0,0 +1,38 @@
/*
[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.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory;
public class ParserASTTreeFieldDecl extends AttributeDecl {
public ParserASTTreeFieldDecl(OutputModelFactory factory) {
super(factory, "tree", "Unknown");
}
}