Parse error systemTweaks, removing the debug API since we won't use it

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 9090]
This commit is contained in:
parrt 2011-10-02 12:01:35 -08:00
parent 9894221249
commit 298a15e017
30 changed files with 235 additions and 2574 deletions

View File

@ -31,9 +31,47 @@ package org.antlr.v4.runtime;
import com.sun.istack.internal.Nullable;
/** */
/** How to emit recognition errors */
public interface ANTLRParserListener {
/** 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
* and how to compute error messages. This listener's job is simply to
* emit a computed message, though it has enough information to
* create its own message in many cases.
*
* The RecognitionException is non-null for all syntax errors except
* when we discover mismatched token errors that we can recover from
* in-line, without returning from the surrounding rule (via the
* single token insertion and deletion mechanism).
*
* @param recognizer
* What parser got the error. From this object, you
* can access the context as well as the input stream.
* @param startTokenIndex
* The offending token index in the input token stream.
* If no viable alternative error, it's the token index
* at which we started production for the decision.
* @param stopTokenIndex
* Normally a copy of the offending token index unless we
* found a no viable alternative error. In that case,
* this is the offending token index.
* @param line
* At what line in input to the error occur? This always refers to
* stopTokenIndex
* @param charPositionInLine
* At what character position within that line did the error occur.
* @param msg
* The message to emit
* @param e
* The exception generated by the parser that led to
* the reporting of an error. It is null in the case where
* the parser was able to recover in line without exiting the
* surrounding rule.
*/
public void error(BaseRecognizer recognizer,
int startTokenIndex,
int stopTokenIndex,
int line,
int charPositionInLine,
String msg,

View File

@ -222,7 +222,7 @@ public abstract class BaseRecognizer extends Recognizer<ParserATNSimulator> {
syntaxErrors++; // don't count spurious
errorRecovery = true;
notifyListeners(e.line, e.charPositionInLine, e.getMessage(), e);
notifyListeners(e.offendingToken, e.getMessage(), e);
}
@ -519,15 +519,23 @@ public abstract class BaseRecognizer extends Recognizer<ParserATNSimulator> {
*/
protected Object getCurrentInputSymbol() { return null; }
public void notifyListeners(int line, int charPositionInLine, String msg,
public void notifyListeners(Token offendingToken, String msg,
@Nullable RecognitionException e)
{
int line = offendingToken.getLine();
int charPositionInLine = offendingToken.getCharPositionInLine();
int start = getInputStream().index();
int stop = start;
if ( e instanceof NoViableAltException ) {
start = ((NoViableAltException) e).startIndex;
stop = e.offendingTokenIndex;
}
if ( _listeners==null || _listeners.size()==0 ) {
emitErrorMessage("line "+line+":"+charPositionInLine+" "+msg);
return;
}
for (ANTLRParserListener pl : _listeners) {
pl.error(this, line, charPositionInLine, msg, e);
pl.error(this, start, stop, line, charPositionInLine, msg, e);
}
}

View File

@ -65,7 +65,7 @@ public class BufferedTokenStream implements TokenStream {
*/
protected int p = -1;
protected int range = -1; // how deep have we gone?
// protected int range = -1; // how deep have we gone?
public BufferedTokenStream() {;}
@ -77,7 +77,7 @@ public class BufferedTokenStream implements TokenStream {
public int index() { return p; }
public int range() { return range; }
// public int range() { return range; }
public int mark() {
if ( p == -1 ) setup();
@ -176,7 +176,7 @@ public class BufferedTokenStream implements TokenStream {
// EOF must be last token
return tokens.get(tokens.size()-1);
}
if ( i>range ) range = i;
// if ( i>range ) range = i;
return tokens.get(i);
}

View File

@ -100,7 +100,7 @@ public class CommonTokenStream extends BufferedTokenStream {
i = skipOffTokenChannels(i+1);
n++;
}
if ( i>range ) range = i;
// if ( i>range ) range = i;
return tokens.get(i);
}

View File

@ -47,7 +47,7 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
else {
System.err.println("unknown recognition error type: "+e.getClass().getName());
if ( recognizer!=null ) {
recognizer.notifyListeners(e.line, e.charPositionInLine, e.getMessage(), e);
recognizer.notifyListeners(e.offendingToken, e.getMessage(), e);
}
}
}
@ -84,8 +84,8 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
if ( recognizer.errorRecovery ) return;
trackError(recognizer);
String msg = "no viable alternative at input "+getTokenErrorDisplay(e.token);
recognizer.notifyListeners(e.line, e.charPositionInLine, msg, e);
String msg = "no viable alternative at input "+getTokenErrorDisplay(e.offendingToken);
recognizer.notifyListeners(e.offendingToken, msg, e);
}
public void reportInputMismatch(BaseRecognizer recognizer,
@ -95,9 +95,9 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
if ( recognizer.errorRecovery ) return;
trackError(recognizer);
String msg = "mismatched input "+getTokenErrorDisplay(e.token)+
String msg = "mismatched input "+getTokenErrorDisplay(e.offendingToken)+
" expecting "+e.expecting.toString(recognizer.getTokenNames());
recognizer.notifyListeners(e.line, e.charPositionInLine, msg, e);
recognizer.notifyListeners(e.offendingToken, msg, e);
}
public void reportFailedPredicate(BaseRecognizer recognizer,
@ -110,7 +110,7 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
String ruleName = recognizer.getRuleNames()[recognizer._ctx.getRuleIndex()];
String msg = "rule "+ruleName+" failed predicate: {"+
e.predicateText+"}?";
recognizer.notifyListeners(e.line, e.charPositionInLine, msg, e);
recognizer.notifyListeners(e.offendingToken, msg, e);
}
public void reportUnwantedToken(BaseRecognizer recognizer) {
@ -123,7 +123,7 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
IntervalSet expecting = getExpectedTokens(recognizer);
String msg = "extraneous input "+tokenName+" expecting "+
expecting.toString(recognizer.getTokenNames());
recognizer.notifyListeners(t.getLine(), t.getCharPositionInLine(), msg, null);
recognizer.notifyListeners(t, msg, null);
}
public void reportMissingToken(BaseRecognizer recognizer) {
@ -135,7 +135,7 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
String msg = "missing "+expecting.toString(recognizer.getTokenNames())+
" at "+getTokenErrorDisplay(t);
recognizer.notifyListeners(t.getLine(), t.getCharPositionInLine(), msg, null);
recognizer.notifyListeners(t, msg, null);
}
/** Attempt to recover from a single missing or extra token.
@ -318,7 +318,7 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy {
// if ( recognizer.errorRecovery ) return;
// trackError(recognizer);
//
// recognizer.notifyListeners(e.line, e.charPositionInLine, "dsfdkjasdf");
// recognizer.notifyListeners(e.offendingToken, "dsfdkjasdf");
// }
/* Compute the error recovery set for the current rule. During

View File

@ -46,11 +46,11 @@ public class MissingTokenException extends MismatchedTokenException {
}
public String toString() {
if ( inserted!=null && token!=null ) {
return "MissingTokenException(inserted "+inserted+" at "+token.getText()+")";
if ( inserted!=null && offendingToken !=null ) {
return "MissingTokenException(inserted "+inserted+" at "+ offendingToken.getText()+")";
}
if ( token!=null ) {
return "MissingTokenException(at "+token.getText()+")";
if ( offendingToken !=null ) {
return "MissingTokenException(at "+ offendingToken.getText()+")";
}
return "MissingTokenException";
}

View File

@ -34,6 +34,12 @@ import org.antlr.v4.runtime.misc.OrderedHashSet;
public class NoViableAltException extends RecognitionException {
/** Prediction began at what input index? */
public int startIndex;
/** The token object at the start index; the input stream might
* not be buffering tokens so get a reference to it. (At the
* time the error occurred, of course the stream needs to keep a
* buffer all of the tokens but later we might not have access to those.)
*/
public Token startToken;
/** Which configurations did we try at input.index() that couldn't match input.LT(1)? */
public OrderedHashSet<ATNConfig> deadEndConfigs;
@ -46,17 +52,20 @@ public class NoViableAltException extends RecognitionException {
}
public NoViableAltException(BaseRecognizer recognizer, IntStream input,
Token startToken,
OrderedHashSet<ATNConfig> deadEndConfigs,
RuleContext ctx)
{
super(recognizer, input, ctx);
this.deadEndConfigs = deadEndConfigs;
this.startToken = startToken;
this.startIndex = startToken.getTokenIndex();
}
public String toString() {
if ( recognizer!=null ) {
TokenStream tokens = ((Parser)recognizer).getTokenStream();
String bad = tokens.toString(startIndex, index);
String bad = tokens.toString(startIndex, offendingTokenIndex);
return "NoViableAltException(input=\""+bad+"\" last token type is "+getUnexpectedType()+")";
}
return "NoViableAltException(last token type is "+getUnexpectedType()+")";

View File

@ -28,7 +28,6 @@
*/
package org.antlr.v4.runtime;
import com.sun.org.apache.regexp.internal.RE;
import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.runtime.tree.*;
@ -74,30 +73,22 @@ public class RecognitionException extends RuntimeException {
public IntStream input;
/** What is index of token/char were we looking at when the error occurred? */
public int index;
public int offendingTokenIndex;
/** The current Token when an error occurred. Since not all streams
* can retrieve the ith Token, we have to track the Token object.
* For parsers. Even when it's a tree parser, token might be set.
*/
public Token token;
public Token offendingToken;
/** If this is a tree parser exception, node is set to the node with
* the problem.
*/
public Object node;
public Object offendingNode;
/** The current char when an error occurred. For lexers. */
public int c;
/** Track the line at which the error occurred in case this is
* generated from a lexer. We need to track this since the
* unexpected char doesn't carry the line info.
*/
public int line;
public int charPositionInLine;
/** If you are parsing a tree node stream, you will encounter som
* imaginary nodes w/o line/col info. We now search backwards looking
* for most recent token with line/col info, but notify getErrorHeader()
@ -125,11 +116,9 @@ public class RecognitionException extends RuntimeException {
// this.expecting = viableTokensFollowingThisRule.or(firstSet);
if ( recognizer!=null ) expecting = recognizer._interp.atn.nextTokens(ctx);
this.index = input.index();
this.offendingTokenIndex = input.index();
if ( input instanceof TokenStream ) {
this.token = ((TokenStream)input).LT(1);
this.line = token.getLine();
this.charPositionInLine = token.getCharPositionInLine();
this.offendingToken = ((TokenStream)input).LT(1);
}
else if ( input instanceof ASTNodeStream) {
//extractInformationFromTreeNodeStream(input);
@ -186,14 +175,14 @@ public class RecognitionException extends RuntimeException {
/** Return the token type or char of the unexpected input element */
public int getUnexpectedType() {
if ( recognizer==null ) return token.getType();
if ( recognizer==null ) return offendingToken.getType();
if ( recognizer.getInputStream() instanceof TokenStream) {
return token.getType();
return offendingToken.getType();
}
else if ( recognizer.getInputStream() instanceof ASTNodeStream) {
ASTNodeStream nodes = (ASTNodeStream)recognizer.getInputStream();
ASTAdaptor adaptor = nodes.getTreeAdaptor();
return adaptor.getType(node);
return adaptor.getType(offendingNode);
}
else {
return c;

View File

@ -109,7 +109,7 @@ public class Recognizer<ATNInterpreter> {
else {
tokenName = tokenNames[mte.expecting.getSingleElement()];
}
msg = "missing "+tokenName+" at "+getTokenErrorDisplay(e.token);
msg = "missing "+tokenName+" at "+getTokenErrorDisplay(e.offendingToken);
}
else if ( e instanceof MismatchedTokenException ) {
MismatchedTokenException mte = (MismatchedTokenException)e;
@ -120,7 +120,7 @@ public class Recognizer<ATNInterpreter> {
// else {
// tokenName = tokenNames[mte.expecting.getSingleElement()];
// }
msg = "mismatched input "+getTokenErrorDisplay(e.token)+
msg = "mismatched input "+getTokenErrorDisplay(e.offendingToken)+
" expecting "+tokenName;
}
else if ( e instanceof MismatchedASTNodeException) {
@ -132,7 +132,7 @@ public class Recognizer<ATNInterpreter> {
else {
tokenName = tokenNames[mtne.expecting.getSingleElement()];
}
msg = "mismatched tree node: "+mtne.node+
msg = "mismatched tree node: "+mtne.offendingNode +
" expecting "+tokenName;
}
else if ( e instanceof NoViableAltException ) {
@ -140,16 +140,16 @@ public class Recognizer<ATNInterpreter> {
// for development, can add "decision=<<"+nvae.grammarDecisionDescription+">>"
// and "(decision="+nvae.decisionNumber+") and
// "state "+nvae.stateNumber
msg = "no viable alternative at input "+getTokenErrorDisplay(e.token);
msg = "no viable alternative at input "+getTokenErrorDisplay(e.offendingToken);
}
else if ( e instanceof MismatchedSetException ) {
MismatchedSetException mse = (MismatchedSetException)e;
msg = "mismatched input "+getTokenErrorDisplay(e.token)+
msg = "mismatched input "+getTokenErrorDisplay(e.offendingToken)+
" expecting set "+mse.expecting;
}
else if ( e instanceof MismatchedNotSetException ) {
MismatchedNotSetException mse = (MismatchedNotSetException)e;
msg = "mismatched input "+getTokenErrorDisplay(e.token)+
msg = "mismatched input "+getTokenErrorDisplay(e.offendingToken)+
" expecting set "+mse.expecting;
}
else if ( e instanceof FailedPredicateException ) {
@ -162,7 +162,9 @@ public class Recognizer<ATNInterpreter> {
/** What is the error header, normally line/character position information? */
public String getErrorHeader(RecognitionException e) {
return "line "+e.line+":"+e.charPositionInLine;
int line = e.offendingToken.getLine();
int charPositionInLine = e.offendingToken.getCharPositionInLine();
return "line "+line+":"+charPositionInLine;
}
/** How should a token be displayed in an error message? The default

View File

@ -42,7 +42,7 @@ public interface TokenStream extends IntStream {
/** How far ahead has the stream been asked to look? The return
* value is a valid index from 0..n-1.
*/
int range();
// int range();
/** Get a token at an absolute index i; 0..n-1. This is really only
* needed for profiling and debugging and token stream rewriting.

View File

@ -38,14 +38,14 @@ public class UnwantedTokenException extends MismatchedTokenException {
}
public Token getUnexpectedToken() {
return token;
return offendingToken;
}
public String toString() {
String exp = ", expected "+expecting;
if ( token==null ) {
if ( offendingToken ==null ) {
return "UnwantedTokenException(found="+null+exp+")";
}
return "UnwantedTokenException(found="+token.getText()+exp+")";
return "UnwantedTokenException(found="+ offendingToken.getText()+exp+")";
}
}

View File

@ -81,7 +81,7 @@ public class ParserATNSimulator extends ATNSimulator {
// System.out.println(dot.getDOT(atn.rules.get(1), parser.getRuleNames()));
}
public int adaptivePredict(IntStream input, int decision, RuleContext outerContext) {
public int adaptivePredict(TokenStream input, int decision, RuleContext outerContext) {
predict_calls++;
DFA dfa = decisionToDFA[decision];
if ( dfa==null || dfa.s0==null ) {
@ -100,7 +100,7 @@ public class ParserATNSimulator extends ATNSimulator {
}
}
public int predictATN(DFA dfa, IntStream input,
public int predictATN(DFA dfa, TokenStream input,
RuleContext outerContext,
boolean useContext)
{
@ -133,14 +133,14 @@ public class ParserATNSimulator extends ATNSimulator {
}
// doesn't create DFA when matching
public int matchATN(IntStream input, ATNState startState) {
public int matchATN(TokenStream input, ATNState startState) {
DFA dfa = new DFA(startState);
RuleContext ctx = RuleContext.EMPTY;
OrderedHashSet<ATNConfig> s0_closure = computeStartState(dfa.decision, startState, ctx);
return execATN(input, dfa, input.index(), s0_closure, false);
}
public int execDFA(IntStream input, DFA dfa, DFAState s0, RuleContext outerContext) {
public int execDFA(TokenStream input, DFA dfa, DFAState s0, RuleContext outerContext) {
// dump(dfa);
if ( outerContext==null ) outerContext = RuleContext.EMPTY;
this.outerContext = outerContext;
@ -229,7 +229,7 @@ public class ParserATNSimulator extends ATNSimulator {
return prevAcceptState.prediction;
}
public String getInputString(IntStream input, int start) {
public String getInputString(TokenStream input, int start) {
if ( input instanceof TokenStream ) {
return ((TokenStream)input).toString(start,input.index());
}
@ -239,7 +239,7 @@ public class ParserATNSimulator extends ATNSimulator {
return "n/a";
}
public int execATN(IntStream input,
public int execATN(TokenStream input,
DFA dfa,
int startIndex,
OrderedHashSet<ATNConfig> s0,
@ -365,8 +365,9 @@ public class ParserATNSimulator extends ATNSimulator {
if ( prevAccept==null ) {
System.out.println("no viable token at input "+ getLookaheadName(input) +", index "+input.index());
NoViableAltException nvae = new NoViableAltException(parser, input, closure, outerContext);
nvae.startIndex = startIndex;
NoViableAltException nvae =
new NoViableAltException(parser, input, input.get(startIndex),
closure, outerContext);
throw nvae;
}
@ -395,7 +396,7 @@ public class ParserATNSimulator extends ATNSimulator {
return exitAlt;
}
public int retryWithContext(IntStream input,
public int retryWithContext(TokenStream input,
DFA dfa,
int startIndex,
RuleContext originalContext,
@ -800,11 +801,20 @@ public class ParserATNSimulator extends ATNSimulator {
public String getTokenName(int t) {
if ( t==-1 ) return "EOF";
if ( parser!=null && parser.getTokenNames()!=null ) return parser.getTokenNames()[t]+"<"+t+">";
String[] tokensNames = parser.getTokenNames();
if ( parser!=null && tokensNames !=null ) {
if ( t>=tokensNames.length ) {
System.err.println(t+" ttype out of range: "+Arrays.toString(tokensNames));
System.err.println(((CommonTokenStream)parser.getInputStream()).getTokens());
}
else {
return tokensNames[t]+"<"+t+">";
}
}
return String.valueOf(t);
}
public String getLookaheadName(IntStream input) {
public String getLookaheadName(TokenStream input) {
return getTokenName(input.LA(1));
}

View File

@ -1,75 +0,0 @@
/*
[The "BSD license"]
Copyright (c) 2005-2009 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.debug;
import org.antlr.v4.runtime.*;
/** A blank listener that does nothing; useful for real classes so
* they don't have to have lots of blank methods and are less
* sensitive to updates to debug interface.
*/
public class BlankDebugEventListener implements DebugEventListener {
public void enterRule(String grammarFileName, String ruleName) {}
public void exitRule(String grammarFileName, String ruleName) {}
public void enterAlt(int alt) {}
public void enterSubRule(int decisionNumber) {}
public void exitSubRule(int decisionNumber) {}
public void enterDecision(int decisionNumber, boolean couldBacktrack) {}
public void exitDecision(int decisionNumber) {}
public void location(int line, int pos) {}
public void consumeToken(Token token) {}
public void consumeHiddenToken(Token token) {}
public void LT(int i, Token t) {}
public void mark(int i) {}
public void release(int i) {}
public void seek(int i) {}
public void recognitionException(RecognitionException e) {}
public void beginResync() {}
public void endResync() {}
public void semanticPredicate(boolean result, String predicate) {}
public void commence() {}
public void terminate() {}
// Tree parsing stuff
public void consumeNode(Object t) {}
public void LT(int i, Object t) {}
// AST Stuff
public void nilNode(Object t) {}
public void errorNode(Object t) {}
public void createNode(Object t) {}
public void createNode(Object node, Token token) {}
public void becomeRoot(Object newRoot, Object oldRoot) {}
public void addChild(Object root, Object child) {}
public void setTokenBoundaries(Object t, int tokenStartIndex, int tokenStopIndex) {}
}

View File

@ -1,276 +0,0 @@
/*
[The "BSD license"]
Copyright (c) 2005-2009 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.debug;
import org.antlr.v4.runtime.*;
import java.util.*;
/** Broadcast debug events to multiple listeners. Lets you debug and still
* use the event mechanism to build parse trees etc... Not thread-safe.
* Don't add events in one thread while parser fires events in another.
*
* @see DebugEventRepeater
*/
public class DebugEventHub implements DebugEventListener {
protected List listeners = new ArrayList();
public DebugEventHub(DebugEventListener listener) {
listeners.add(listener);
}
public DebugEventHub(DebugEventListener a, DebugEventListener b) {
listeners.add(a);
listeners.add(b);
}
/** Add another listener to broadcast events too. Not thread-safe.
* Don't add events in one thread while parser fires events in another.
*/
public void addListener(DebugEventListener listener) {
listeners.add(listener);
}
/* To avoid a mess like this:
public void enterRule(final String ruleName) {
broadcast(new Code(){
public void exec(DebugEventListener listener) {listener.enterRule(ruleName);}}
);
}
I am dup'ing the for-loop in each. Where are Java closures!? blech!
*/
public void enterRule(String grammarFileName, String ruleName) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.enterRule(grammarFileName, ruleName);
}
}
public void exitRule(String grammarFileName, String ruleName) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.exitRule(grammarFileName, ruleName);
}
}
public void enterAlt(int alt) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.enterAlt(alt);
}
}
public void enterSubRule(int decisionNumber) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.enterSubRule(decisionNumber);
}
}
public void exitSubRule(int decisionNumber) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.exitSubRule(decisionNumber);
}
}
public void enterDecision(int decisionNumber, boolean couldBacktrack) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.enterDecision(decisionNumber, couldBacktrack);
}
}
public void exitDecision(int decisionNumber) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.exitDecision(decisionNumber);
}
}
public void location(int line, int pos) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.location(line, pos);
}
}
public void consumeToken(Token token) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.consumeToken(token);
}
}
public void consumeHiddenToken(Token token) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.consumeHiddenToken(token);
}
}
public void LT(int index, Token t) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.LT(index, t);
}
}
public void mark(int index) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.mark(index);
}
}
public void seek(int index) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.seek(index);
}
}
public void release(int marker) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.release(marker);
}
}
public void recognitionException(RecognitionException e) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.recognitionException(e);
}
}
public void beginResync() {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.beginResync();
}
}
public void endResync() {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.endResync();
}
}
public void semanticPredicate(boolean result, String predicate) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.semanticPredicate(result, predicate);
}
}
public void commence() {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.commence();
}
}
public void terminate() {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.terminate();
}
}
// Tree parsing stuff
public void consumeNode(Object t) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.consumeNode(t);
}
}
public void LT(int index, Object t) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.LT(index, t);
}
}
// AST Stuff
public void nilNode(Object t) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.nilNode(t);
}
}
public void errorNode(Object t) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.errorNode(t);
}
}
public void createNode(Object t) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.createNode(t);
}
}
public void createNode(Object node, Token token) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.createNode(node, token);
}
}
public void becomeRoot(Object newRoot, Object oldRoot) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.becomeRoot(newRoot, oldRoot);
}
}
public void addChild(Object root, Object child) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.addChild(root, child);
}
}
public void setTokenBoundaries(Object t, int tokenStartIndex, int tokenStopIndex) {
for (int i = 0; i < listeners.size(); i++) {
DebugEventListener listener = (DebugEventListener)listeners.get(i);
listener.setTokenBoundaries(t, tokenStartIndex, tokenStopIndex);
}
}
}

View File

@ -1,310 +0,0 @@
/*
[The "BSD license"]
Copyright (c) 2005-2009 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.debug;
import org.antlr.v4.runtime.*;
/** All debugging events that a recognizer can trigger.
*
* I did not create a separate AST debugging interface as it would create
* lots of extra classes and DebugParser has a dbg var defined, which makes
* it hard to change to ASTDebugEventListener. I looked hard at this issue
* and it is easier to understand as one monolithic event interface for all
* possible events. Hopefully, adding ST debugging stuff won't be bad. Leave
* for future. 4/26/2006.
*/
public interface DebugEventListener {
/** Moved to version 2 for v3.1: added grammar name to enter/exit Rule */
public static final String PROTOCOL_VERSION = "2";
/** serialized version of true */
public static final int TRUE = 1;
public static final int FALSE = 0;
/** The parser has just entered a rule. No decision has been made about
* which alt is predicted. This is fired AFTER init actions have been
* executed. Attributes are defined and available etc...
* The grammarFileName allows composite grammars to jump around among
* multiple grammar files.
*/
public void enterRule(String grammarFileName, String ruleName);
/** Because rules can have lots of alternatives, it is very useful to
* know which alt you are entering. This is 1..n for n alts.
*/
public void enterAlt(int alt);
/** This is the last thing executed before leaving a rule. It is
* executed even if an exception is thrown. This is triggered after
* error reporting and recovery have occurred (unless the exception is
* not caught in this rule). This implies an "exitAlt" event.
* The grammarFileName allows composite grammars to jump around among
* multiple grammar files.
*/
public void exitRule(String grammarFileName, String ruleName);
/** Track entry into any (...) subrule other EBNF construct */
public void enterSubRule(int decisionNumber);
public void exitSubRule(int decisionNumber);
/** Every decision, fixed k or arbitrary, has an enter/exit event
* so that a GUI can easily track what LT/consume events are
* associated with prediction. You will see a single enter/exit
* subrule but multiple enter/exit decision events, one for each
* loop iteration.
*/
public void enterDecision(int decisionNumber, boolean couldBacktrack);
public void exitDecision(int decisionNumber);
/** The parser is going to look arbitrarily ahead; mark this location. */
public void mark(int index);
/** After an arbitrarily long lookahead, this informs the
* debugger that stream should be rewound to the position index.
*/
public void release(int marker);
/** Set the input cursor to the position indicated by index. */
public void seek(int index);
/** An input token was consumed; matched by any kind of element.
* Trigger after the token was matched by things like match(), matchAny().
*/
public void consumeToken(Token t);
/** An off-channel input token was consumed.
* Trigger after the token was matched by things like match(), matchAny().
* (unless of course the hidden token is first stuff in the input stream).
*/
public void consumeHiddenToken(Token t);
/** Somebody (anybody) looked ahead. Note that this actually gets
* triggered by both LA and LT calls. The debugger will want to know
* which Token object was examined. Like consumeToken, this indicates
* what token was seen at that depth. A remote debugger cannot look
* ahead into a file it doesn't have so LT events must pass the token
* even if the info is redundant.
*/
public void LT(int i, Token t);
/** To watch a parser move through the grammar, the parser needs to
* inform the debugger what line/charPos it is passing in the grammar.
* For now, this does not know how to switch from one grammar to the
* other and back for island grammars etc...
*
* This should also allow breakpoints because the debugger can stop
* the parser whenever it hits this line/pos.
*/
public void location(int line, int pos);
/** A recognition exception occurred such as NoViableAltException. I made
* this a generic event so that I can alter the exception hierachy later
* without having to alter all the debug objects.
*
* Upon error, the stack of enter rule/subrule must be properly unwound.
* If no viable alt occurs it is within an enter/exit decision, which
* also must be rewound. Even the rewind for each mark must be unwount.
* In the Java target this is pretty easy using try/finally, if a bit
* ugly in the generated code. The rewind is generated in DFA.predict()
* actually so no code needs to be generated for that. For languages
* w/o this "finally" feature (C++?), the target implementor will have
* to build an event stack or something.
*
* Across a socket for remote debugging, only the RecognitionException
* data fields are transmitted. The token object or whatever that
* caused the problem was the last object referenced by LT. The
* immediately preceding LT event should hold the unexpected Token or
* char.
*
* Here is a sample event trace for grammar:
*
* b : C ({;}A|B) // {;} is there to prevent A|B becoming a set
* | D
* ;
*
* The sequence for this rule (with no viable alt in the subrule) for
* input 'c c' (there are 3 tokens) is:
*
* commence
* LT(1)
* enterRule b
* location 7 1
* enter decision 3
* LT(1)
* exit decision 3
* enterAlt1
* location 7 5
* LT(1)
* consumeToken [c/<4>,1:0]
* location 7 7
* enterSubRule 2
* enter decision 2
* LT(1)
* LT(1)
* recognitionException NoViableAltException 2 1 2
* exit decision 2
* exitSubRule 2
* beginResync
* LT(1)
* consumeToken [c/<4>,1:1]
* LT(1)
* endResync
* LT(-1)
* exitRule b
* terminate
*/
public void recognitionException(RecognitionException e);
/** Indicates the recognizer is about to consume tokens to resynchronize
* the parser. Any consume events from here until the recovered event
* are not part of the parse--they are dead tokens.
*/
public void beginResync();
/** Indicates that the recognizer has finished consuming tokens in order
* to resychronize. There may be multiple beginResync/endResync pairs
* before the recognizer comes out of errorRecovery mode (in which
* multiple errors are suppressed). This will be useful
* in a gui where you want to probably grey out tokens that are consumed
* but not matched to anything in grammar. Anything between
* a beginResync/endResync pair was tossed out by the parser.
*/
public void endResync();
/** A semantic predicate was evaluate with this result and action text */
public void semanticPredicate(boolean result, String predicate);
/** Announce that parsing has begun. Not technically useful except for
* sending events over a socket. A GUI for example will launch a thread
* to connect and communicate with a remote parser. The thread will want
* to notify the GUI when a connection is made. ANTLR parsers
* trigger this upon entry to the first rule (the ruleLevel is used to
* figure this out).
*/
public void commence();
/** Parsing is over; successfully or not. Mostly useful for telling
* remote debugging listeners that it's time to quit. When the rule
* invocation level goes to zero at the end of a rule, we are done
* parsing.
*/
public void terminate();
// T r e e P a r s i n g
/** Input for a tree parser is an AST, but we know nothing for sure
* about a node except its type and text (obtained from the adaptor).
* This is the analog of the consumeToken method. Again, the ID is
* the hashCode usually of the node so it only works if hashCode is
* not implemented. If the type is UP or DOWN, then
* the ID is not really meaningful as it's fixed--there is
* just one UP node and one DOWN navigation node.
* @param t
*/
public void consumeNode(Object t);
/** The tree parser lookedahead. If the type is UP or DOWN,
* then the ID is not really meaningful as it's fixed--there is
* just one UP node and one DOWN navigation node.
*/
public void LT(int i, Object t);
// A S T E v e n t s
/** A nil was created (even nil nodes have a unique ID...
* they are not "null" per se). As of 4/28/2006, this
* seems to be uniquely triggered when starting a new subtree
* such as when entering a subrule in automatic mode and when
* building a tree in rewrite mode.
*
* If you are receiving this event over a socket via
* RemoteDebugEventSocketListener then only t.ID is set.
*/
public void nilNode(Object t);
/** Upon syntax error, recognizers bracket the error with an error node
* if they are building ASTs.
* @param t
*/
public void errorNode(Object t);
/** Announce a new node built from token elements such as type etc...
*
* If you are receiving this event over a socket via
* RemoteDebugEventSocketListener then only t.ID, type, text are
* set.
*/
public void createNode(Object t);
/** Announce a new node built from an existing token.
*
* If you are receiving this event over a socket via
* RemoteDebugEventSocketListener then only node.ID and token.tokenIndex
* are set.
*/
public void createNode(Object node, Token token);
/** Make a node the new root of an existing root. See
*
* Note: the newRootID parameter is possibly different
* than the ASTAdaptor.becomeRoot() newRoot parameter.
* In our case, it will always be the result of calling
* ASTAdaptor.becomeRoot() and not root_n or whatever.
*
* The listener should assume that this event occurs
* only when the current subrule (or rule) subtree is
* being reset to newRootID.
*
* If you are receiving this event over a socket via
* RemoteDebugEventSocketListener then only IDs are set.
*
* @see org.antlr.v4.runtime.tree.ASTAdaptor becomeRoot()
*/
public void becomeRoot(Object newRoot, Object oldRoot);
/** Make childID a child of rootID.
*
* If you are receiving this event over a socket via
* RemoteDebugEventSocketListener then only IDs are set.
*
* @see org.antlr.v4.runtime.tree.ASTAdaptor addChild()
*/
public void addChild(Object root, Object child);
/** Set the token start/stop token index for a subtree root or node.
*
* If you are receiving this event over a socket via
* RemoteDebugEventSocketListener then only t.ID is set.
*/
public void setTokenBoundaries(Object t, int tokenStartIndex, int tokenStopIndex);
}

View File

@ -1,85 +0,0 @@
/*
[The "BSD license"]
Copyright (c) 2005-2009 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.debug;
import org.antlr.v4.runtime.*;
/** A simple event repeater (proxy) that delegates all functionality to the
* listener sent into the ctor. Useful if you want to listen in on a few
* debug events w/o interrupting the debugger. Just subclass the repeater
* and override the methods you want to listen in on. Remember to call
* the method in this class so the event will continue on to the original
* recipient.
*
* @see DebugEventHub
*/
public class DebugEventRepeater implements DebugEventListener {
protected DebugEventListener listener;
public DebugEventRepeater(DebugEventListener listener) {
this.listener = listener;
}
public void enterRule(String grammarFileName, String ruleName) { listener.enterRule(grammarFileName, ruleName); }
public void exitRule(String grammarFileName, String ruleName) { listener.exitRule(grammarFileName, ruleName); }
public void enterAlt(int alt) { listener.enterAlt(alt); }
public void enterSubRule(int decisionNumber) { listener.enterSubRule(decisionNumber); }
public void exitSubRule(int decisionNumber) { listener.exitSubRule(decisionNumber); }
public void enterDecision(int decisionNumber, boolean couldBacktrack) { listener.enterDecision(decisionNumber, couldBacktrack); }
public void exitDecision(int decisionNumber) { listener.exitDecision(decisionNumber); }
public void location(int line, int pos) { listener.location(line, pos); }
public void consumeToken(Token token) { listener.consumeToken(token); }
public void consumeHiddenToken(Token token) { listener.consumeHiddenToken(token); }
public void LT(int i, Token t) { listener.LT(i, t); }
public void mark(int i) { listener.mark(i); }
public void release(int i) { listener.release(i); }
public void seek(int i) { listener.seek(i); }
public void recognitionException(RecognitionException e) { listener.recognitionException(e); }
public void beginResync() { listener.beginResync(); }
public void endResync() { listener.endResync(); }
public void semanticPredicate(boolean result, String predicate) { listener.semanticPredicate(result, predicate); }
public void commence() { listener.commence(); }
public void terminate() { listener.terminate(); }
// Tree parsing stuff
public void consumeNode(Object t) { listener.consumeNode(t); }
public void LT(int i, Object t) { listener.LT(i, t); }
// AST Stuff
public void nilNode(Object t) { listener.nilNode(t); }
public void errorNode(Object t) { listener.errorNode(t); }
public void createNode(Object t) { listener.createNode(t); }
public void createNode(Object node, Token token) { listener.createNode(node, token); }
public void becomeRoot(Object newRoot, Object oldRoot) { listener.becomeRoot(newRoot, oldRoot); }
public void addChild(Object root, Object child) { listener.addChild(root, child); }
public void setTokenBoundaries(Object t, int tokenStartIndex, int tokenStopIndex) {
listener.setTokenBoundaries(t, tokenStartIndex, tokenStopIndex);
}
}

View File

@ -1,351 +0,0 @@
/*
[The "BSD license"]
Copyright (c) 2005-2009 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.debug;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.ASTAdaptor;
import java.io.*;
import java.net.*;
/** A proxy debug event listener that forwards events over a socket to
* a debugger (or any other listener) using a simple text-based protocol;
* one event per line. ANTLRWorks listens on server socket with a
* RemoteDebugEventSocketListener instance. These two objects must therefore
* be kept in sync. New events must be handled on both sides of socket.
*/
public class DebugEventSocketProxy extends BlankDebugEventListener {
public static final int DEFAULT_DEBUGGER_PORT = 49100; // was 49153
protected int port = DEFAULT_DEBUGGER_PORT;
protected ServerSocket serverSocket;
protected Socket socket;
protected String grammarFileName;
protected PrintWriter out;
protected BufferedReader in;
/** Who am i debugging? */
protected BaseRecognizer recognizer;
/** Almost certainly the recognizer will have adaptor set, but
* we don't know how to cast it (Parser or TreeParser) to get
* the adaptor field. Must be set with a constructor. :(
*/
protected ASTAdaptor adaptor;
public DebugEventSocketProxy(BaseRecognizer recognizer, ASTAdaptor adaptor) {
this(recognizer, DEFAULT_DEBUGGER_PORT, adaptor);
}
public DebugEventSocketProxy(BaseRecognizer recognizer, int port, ASTAdaptor adaptor) {
this.grammarFileName = recognizer.getGrammarFileName();
this.adaptor = adaptor;
this.port = port;
}
public void handshake() throws IOException {
if ( serverSocket==null ) {
serverSocket = new ServerSocket(port);
socket = serverSocket.accept();
socket.setTcpNoDelay(true);
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os, "UTF8");
out = new PrintWriter(new BufferedWriter(osw));
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is, "UTF8");
in = new BufferedReader(isr);
out.println("ANTLR "+ DebugEventListener.PROTOCOL_VERSION);
out.println("grammar \""+ grammarFileName);
out.flush();
ack();
}
}
public void commence() {
// don't bother sending event; listener will trigger upon connection
}
public void terminate() {
transmit("terminate");
out.close();
try {
socket.close();
}
catch (IOException ioe) {
ioe.printStackTrace(System.err);
}
}
protected void ack() {
try {
in.readLine();
}
catch (IOException ioe) {
ioe.printStackTrace(System.err);
}
}
protected void transmit(String event) {
out.println(event);
out.flush();
ack();
}
public void enterRule(String grammarFileName, String ruleName) {
transmit("enterRule\t"+grammarFileName+"\t"+ruleName);
}
public void enterAlt(int alt) {
transmit("enterAlt\t"+alt);
}
public void exitRule(String grammarFileName, String ruleName) {
transmit("exitRule\t"+grammarFileName+"\t"+ruleName);
}
public void enterSubRule(int decisionNumber) {
transmit("enterSubRule\t"+decisionNumber);
}
public void exitSubRule(int decisionNumber) {
transmit("exitSubRule\t"+decisionNumber);
}
public void enterDecision(int decisionNumber, boolean couldBacktrack) {
transmit("enterDecision\t"+decisionNumber+"\t"+couldBacktrack);
}
public void exitDecision(int decisionNumber) {
transmit("exitDecision\t"+decisionNumber);
}
public void consumeToken(Token t) {
String buf = serializeToken(t);
transmit("consumeToken\t"+buf);
}
public void consumeHiddenToken(Token t) {
String buf = serializeToken(t);
transmit("consumeHiddenToken\t"+buf);
}
public void LT(int i, Token t) {
if(t != null)
transmit("LT\t"+i+"\t"+serializeToken(t));
}
public void mark(int i) {
transmit("mark\t"+i);
}
public void release(int i) {
transmit("rewind\t"+i);
}
public void rewind() {
transmit("rewind");
}
public void beginBacktrack(int level) {
transmit("beginBacktrack\t"+level);
}
public void endBacktrack(int level, boolean successful) {
transmit("endBacktrack\t"+level+"\t"+(successful?TRUE:FALSE));
}
public void location(int line, int pos) {
transmit("location\t"+line+"\t"+pos);
}
public void recognitionException(RecognitionException e) {
StringBuffer buf = new StringBuffer(50);
buf.append("exception\t");
buf.append(e.getClass().getName());
// dump only the data common to all exceptions for now
buf.append("\t");
buf.append(e.index);
buf.append("\t");
buf.append(e.line);
buf.append("\t");
buf.append(e.charPositionInLine);
transmit(buf.toString());
}
public void beginResync() {
transmit("beginResync");
}
public void endResync() {
transmit("endResync");
}
public void semanticPredicate(boolean result, String predicate) {
StringBuffer buf = new StringBuffer(50);
buf.append("semanticPredicate\t");
buf.append(result);
serializeText(buf, predicate);
transmit(buf.toString());
}
// A S T P a r s i n g E v e n t s
public void consumeNode(Object t) {
StringBuffer buf = new StringBuffer(50);
buf.append("consumeNode");
serializeNode(buf, t);
transmit(buf.toString());
}
public void LT(int i, Object t) {
int ID = adaptor.getUniqueID(t);
String text = adaptor.getText(t);
int type = adaptor.getType(t);
StringBuffer buf = new StringBuffer(50);
buf.append("LN\t"); // lookahead node; distinguish from LT in protocol
buf.append(i);
serializeNode(buf, t);
transmit(buf.toString());
}
protected void serializeNode(StringBuffer buf, Object t) {
int ID = adaptor.getUniqueID(t);
String text = adaptor.getText(t);
int type = adaptor.getType(t);
buf.append("\t");
buf.append(ID);
buf.append("\t");
buf.append(type);
Token token = adaptor.getToken(t);
int line = -1;
int pos = -1;
if ( token!=null ) {
line = token.getLine();
pos = token.getCharPositionInLine();
}
buf.append("\t");
buf.append(line);
buf.append("\t");
buf.append(pos);
int tokenIndex = adaptor.getTokenStartIndex(t);
buf.append("\t");
buf.append(tokenIndex);
serializeText(buf, text);
}
// A S T E v e n t s
public void nilNode(Object t) {
int ID = adaptor.getUniqueID(t);
transmit("nilNode\t"+ID);
}
public void errorNode(Object t) {
int ID = adaptor.getUniqueID(t);
String text = t.toString();
StringBuffer buf = new StringBuffer(50);
buf.append("errorNode\t");
buf.append(ID);
buf.append("\t");
buf.append(Token.INVALID_TYPE);
serializeText(buf, text);
transmit(buf.toString());
}
public void createNode(Object t) {
int ID = adaptor.getUniqueID(t);
String text = adaptor.getText(t);
int type = adaptor.getType(t);
StringBuffer buf = new StringBuffer(50);
buf.append("createNodeFromTokenElements\t");
buf.append(ID);
buf.append("\t");
buf.append(type);
serializeText(buf, text);
transmit(buf.toString());
}
public void createNode(Object node, Token token) {
int ID = adaptor.getUniqueID(node);
int tokenIndex = token.getTokenIndex();
transmit("createNode\t"+ID+"\t"+tokenIndex);
}
public void becomeRoot(Object newRoot, Object oldRoot) {
int newRootID = adaptor.getUniqueID(newRoot);
int oldRootID = adaptor.getUniqueID(oldRoot);
transmit("becomeRoot\t"+newRootID+"\t"+oldRootID);
}
public void addChild(Object root, Object child) {
int rootID = adaptor.getUniqueID(root);
int childID = adaptor.getUniqueID(child);
transmit("addChild\t"+rootID+"\t"+childID);
}
public void setTokenBoundaries(Object t, int tokenStartIndex, int tokenStopIndex) {
int ID = adaptor.getUniqueID(t);
transmit("setTokenBoundaries\t"+ID+"\t"+tokenStartIndex+"\t"+tokenStopIndex);
}
// support
public void setTreeAdaptor(ASTAdaptor adaptor) { this.adaptor = adaptor; }
public ASTAdaptor getTreeAdaptor() { return adaptor; }
protected String serializeToken(Token t) {
StringBuffer buf = new StringBuffer(50);
buf.append(t.getTokenIndex()); buf.append('\t');
buf.append(t.getType()); buf.append('\t');
buf.append(t.getChannel()); buf.append('\t');
buf.append(t.getLine()); buf.append('\t');
buf.append(t.getCharPositionInLine());
serializeText(buf, t.getText());
return buf.toString();
}
protected void serializeText(StringBuffer buf, String text) {
buf.append("\t\"");
if ( text==null ) {
text = "";
}
// escape \n and \r all text for token appears to exist on one line
// this escape is slow but easy to understand
text = escapeNewlines(text);
buf.append(text);
}
protected String escapeNewlines(String txt) {
txt = txt.replaceAll("%","%25"); // escape all escape char ;)
txt = txt.replaceAll("\n","%0A"); // escape \n
txt = txt.replaceAll("\r","%0D"); // escape \r
return txt;
}
}

View File

@ -1,81 +0,0 @@
/*
[The "BSD license"]
Copyright (c) 2005-2009 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.debug;
import org.antlr.v4.runtime.*;
import java.io.IOException;
public class DebugParser extends Parser {
/** Who to notify when events in the parser occur. */
protected DebugEventListener dbg = null;
/** Create a normal parser except wrap the token stream in a debug
* proxy that fires consume events.
*/
public DebugParser(TokenStream input, DebugEventListener dbg) {
super(input instanceof DebugTokenStream?input:new DebugTokenStream(input,dbg));
setDebugListener(dbg);
}
public DebugParser(TokenStream input) {
super(input instanceof DebugTokenStream ? input : new DebugTokenStream(input, null));
}
/** Provide a new debug event listener for this parser. Notify the
* input stream too that it should send events to this listener.
*/
public void setDebugListener(DebugEventListener dbg) {
if ( _input instanceof DebugTokenStream ) {
((DebugTokenStream) _input).setDebugListener(dbg);
}
this.dbg = dbg;
}
public DebugEventListener getDebugListener() {
return dbg;
}
public void reportError(IOException e) {
System.err.println(e);
e.printStackTrace(System.err);
}
public void beginResync() {
dbg.beginResync();
}
public void endResync() {
dbg.endResync();
}
public void reportError(RecognitionException e) {
super.reportError(e);
dbg.recognitionException(e);
}
}

View File

@ -1,146 +0,0 @@
/*
[The "BSD license"]
Copyright (c) 2005-2009 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.debug;
import org.antlr.v4.runtime.*;
public class DebugTokenStream implements TokenStream {
protected DebugEventListener dbg;
public TokenStream input;
protected boolean initialStreamState = true;
/** Track the last mark() call result value for use in rewind(). */
protected int lastMarker;
public DebugTokenStream(TokenStream input, DebugEventListener dbg) {
this.input = input;
setDebugListener(dbg);
// force TokenStream to get at least first valid token
// so we know if there are any hidden tokens first in the stream
input.LT(1);
}
public void setDebugListener(DebugEventListener dbg) {
this.dbg = dbg;
}
public void consume() {
if ( initialStreamState ) {
consumeInitialHiddenTokens();
}
int a = input.index();
Token t = input.LT(1);
input.consume();
int b = input.index();
dbg.consumeToken(t);
if ( b>a+1 ) {
// then we consumed more than one token; must be off channel tokens
for (int i=a+1; i<b; i++) {
dbg.consumeHiddenToken(input.get(i));
}
}
}
/* consume all initial off-channel tokens */
protected void consumeInitialHiddenTokens() {
int firstOnChannelTokenIndex = input.index();
for (int i=0; i<firstOnChannelTokenIndex; i++) {
dbg.consumeHiddenToken(input.get(i));
}
initialStreamState = false;
}
public Token LT(int i) {
if ( initialStreamState ) {
consumeInitialHiddenTokens();
}
dbg.LT(i, input.LT(i));
return input.LT(i);
}
public int LA(int i) {
if ( initialStreamState ) {
consumeInitialHiddenTokens();
}
dbg.LT(i, input.LT(i));
return input.LA(i);
}
public Token get(int i) {
return input.get(i);
}
public int mark() {
lastMarker = input.mark();
dbg.mark(lastMarker);
return lastMarker;
}
public int index() {
return input.index();
}
public int range() {
return input.range();
}
public void release(int index) {
dbg.release(index);
input.release(index);
}
public void seek(int index) {
// TODO: implement seek in dbg interface
// db.seek(index);
input.seek(index);
}
public int size() {
return input.size();
}
public TokenSource getTokenSource() {
return input.getTokenSource();
}
public String getSourceName() {
return getTokenSource().getSourceName();
}
public String toString() {
return input.toString();
}
public String toString(int start, int stop) {
return input.toString(start,stop);
}
public String toString(Token start, Token stop) {
return input.toString(start,stop);
}
}

View File

@ -1,254 +0,0 @@
/*
[The "BSD license"]
Copyright (c) 2005-2009 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.debug;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.ASTAdaptor;
import java.util.List;
/** An ASTAdaptor proxy that fires debugging events to a DebugEventListener
* delegate and uses the ASTAdaptor delegate to do the actual work. All
* AST events are triggered by this adaptor; no code gen changes are needed
* in generated rules. Debugging events are triggered *after* invoking
* tree adaptor routines.
*
* Trees created with actions in rewrite actions like "-> ^(ADD {foo} {bar})"
* cannot be tracked as they might not use the adaptor to create foo, bar.
* The debug listener has to deal with tree node IDs for which it did
* not see a createNode event. A single <unknown> node is sufficient even
* if it represents a whole tree.
*/
public class DebugTreeAdaptor implements ASTAdaptor {
protected DebugEventListener dbg;
protected ASTAdaptor adaptor;
public DebugTreeAdaptor(DebugEventListener dbg, ASTAdaptor adaptor) {
this.dbg = dbg;
this.adaptor = adaptor;
}
public Object create(Token payload) {
if ( payload.getTokenIndex() < 0 ) {
// could be token conjured up during error recovery
return create(payload.getType(), payload.getText());
}
Object node = adaptor.create(payload);
dbg.createNode(node, payload);
return node;
}
public List<Object> createElementList() {
return adaptor.createElementList();
}
public Object errorNode(TokenStream input, Token start, Token stop,
RecognitionException e)
{
Object node = adaptor.errorNode(input, start, stop, e);
if ( node!=null ) {
dbg.errorNode(node);
}
return node;
}
public Object dupTree(Object tree) {
Object t = adaptor.dupTree(tree);
// walk the tree and emit create and add child events
// to simulate what dupTree has done. dupTree does not call this debug
// adapter so I must simulate.
simulateTreeConstruction(t);
return t;
}
/** ^(A B C): emit create A, create B, add child, ...*/
protected void simulateTreeConstruction(Object t) {
dbg.createNode(t);
int n = adaptor.getChildCount(t);
for (int i=0; i<n; i++) {
Object child = adaptor.getChild(t, i);
simulateTreeConstruction(child);
dbg.addChild(t, child);
}
}
public Object dupNode(Object treeNode) {
Object d = adaptor.dupNode(treeNode);
dbg.createNode(d);
return d;
}
public Object nil() {
Object node = adaptor.nil();
dbg.nilNode(node);
return node;
}
public boolean isNil(Object tree) {
return adaptor.isNil(tree);
}
public void addChild(Object t, Object child) {
if ( t==null || child==null ) {
return;
}
adaptor.addChild(t,child);
dbg.addChild(t, child);
}
public Object becomeRoot(Object newRoot, Object oldRoot) {
Object n = adaptor.becomeRoot(newRoot, oldRoot);
dbg.becomeRoot(newRoot, oldRoot);
return n;
}
public Object rulePostProcessing(Object root) {
return adaptor.rulePostProcessing(root);
}
public void addChild(Object t, Token child) {
Object n = this.create(child);
this.addChild(t, n);
}
public Object becomeRoot(Token newRoot, Object oldRoot) {
Object n = this.create(newRoot);
adaptor.becomeRoot(n, oldRoot);
dbg.becomeRoot(newRoot, oldRoot);
return n;
}
public Object create(int tokenType, Token fromToken) {
Object node = adaptor.create(tokenType, fromToken);
dbg.createNode(node);
return node;
}
public Object create(int tokenType, Token fromToken, String text) {
Object node = adaptor.create(tokenType, fromToken, text);
dbg.createNode(node);
return node;
}
public Object create(int tokenType, String text) {
Object node = adaptor.create(tokenType, text);
dbg.createNode(node);
return node;
}
public int getType(Object t) {
return adaptor.getType(t);
}
public void setType(Object t, int type) {
adaptor.setType(t, type);
}
public String getText(Object t) {
return adaptor.getText(t);
}
public void setText(Object t, String text) {
adaptor.setText(t, text);
}
public Token getToken(Object t) {
return adaptor.getToken(t);
}
public void setTokenBoundaries(Object t, Token startToken, Token stopToken) {
adaptor.setTokenBoundaries(t, startToken, stopToken);
if ( t!=null && startToken!=null && stopToken!=null ) {
dbg.setTokenBoundaries(
t, startToken.getTokenIndex(),
stopToken.getTokenIndex());
}
}
public int getTokenStartIndex(Object t) {
return adaptor.getTokenStartIndex(t);
}
public int getTokenStopIndex(Object t) {
return adaptor.getTokenStopIndex(t);
}
public Object getChild(Object t, int i) {
return adaptor.getChild(t, i);
}
public void setChild(Object t, int i, Object child) {
adaptor.setChild(t, i, child);
}
public Object deleteChild(Object t, int i) {
return deleteChild(t, i);
}
public int getChildCount(Object t) {
return adaptor.getChildCount(t);
}
public int getUniqueID(Object node) {
return adaptor.getUniqueID(node);
}
public Object getParent(Object t) {
return adaptor.getParent(t);
}
public int getChildIndex(Object t) {
return adaptor.getChildIndex(t);
}
public void setParent(Object t, Object parent) {
adaptor.setParent(t, parent);
}
public void setChildIndex(Object t, int index) {
adaptor.setChildIndex(t, index);
}
public void replaceChildren(Object parent, int startChildIndex, int stopChildIndex, Object t) {
adaptor.replaceChildren(parent, startChildIndex, stopChildIndex, t);
}
// support
public DebugEventListener getDebugListener() {
return dbg;
}
public void setDebugListener(DebugEventListener dbg) {
this.dbg = dbg;
}
public ASTAdaptor getTreeAdaptor() {
return adaptor;
}
}

View File

@ -1,146 +0,0 @@
/*
[The "BSD license"]
Copyright (c) 2005-2009 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.debug;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.tree.*;
/** Debug any tree node stream. The constructor accepts the stream
* and a debug listener. As node stream calls come in, debug events
* are triggered.
*/
public class DebugTreeNodeStream implements ASTNodeStream {
protected DebugEventListener dbg;
protected ASTAdaptor adaptor;
protected ASTNodeStream input;
protected boolean initialStreamState = true;
/** Track the last mark() call result value for use in rewind(). */
protected int lastMarker;
public DebugTreeNodeStream(ASTNodeStream input,
DebugEventListener dbg)
{
this.input = input;
this.adaptor = input.getTreeAdaptor();
this.input.setUniqueNavigationNodes(true);
setDebugListener(dbg);
}
public void setDebugListener(DebugEventListener dbg) {
this.dbg = dbg;
}
public ASTAdaptor getTreeAdaptor() {
return adaptor;
}
public void consume() {
Object node = input.LT(1);
input.consume();
dbg.consumeNode(node);
}
public Object get(int i) {
return input.get(i);
}
public Object LT(int i) {
Object node = input.LT(i);
int ID = adaptor.getUniqueID(node);
String text = adaptor.getText(node);
int type = adaptor.getType(node);
dbg.LT(i, node);
return node;
}
public int LA(int i) {
Object node = input.LT(i);
int ID = adaptor.getUniqueID(node);
String text = adaptor.getText(node);
int type = adaptor.getType(node);
dbg.LT(i, node);
return type;
}
public int mark() {
lastMarker = input.mark();
dbg.mark(lastMarker);
return lastMarker;
}
public void release(int marker) {
dbg.release(marker);
input.release(marker);
}
public int index() {
return input.index();
}
public void seek(int index) {
// TODO: implement seek in dbg interface
// db.seek(index);
input.seek(index);
}
public int size() {
return input.size();
}
public void reset() { ; }
public Object getTreeSource() {
return input;
}
public String getSourceName() {
return getTokenStream().getSourceName();
}
public TokenStream getTokenStream() {
return input.getTokenStream();
}
/** It is normally this object that instructs the node stream to
* create unique nav nodes, but to satisfy interface, we have to
* define it. It might be better to ignore the parameter but
* there might be a use for it later, so I'll leave.
*/
public void setUniqueNavigationNodes(boolean uniqueNavigationNodes) {
input.setUniqueNavigationNodes(uniqueNavigationNodes);
}
public void replaceChildren(Object parent, int startChildIndex, int stopChildIndex, Object t) {
input.replaceChildren(parent, startChildIndex, stopChildIndex, t);
}
public String toString(Object start, Object stop) {
return input.toString(start,stop);
}
}

View File

@ -1,96 +0,0 @@
/*
[The "BSD license"]
Copyright (c) 2005-2009 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.debug;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.tree.*;
import java.io.IOException;
public class DebugTreeParser extends TreeParser {
/** Who to notify when events in the parser occur. */
protected DebugEventListener dbg = null;
/** Used to differentiate between fixed lookahead and cyclic DFA decisions
* while profiling.
*/
public boolean isCyclicDecision = false;
/** Create a normal parser except wrap the token stream in a debug
* proxy that fires consume events.
*/
public DebugTreeParser(ASTNodeStream input, DebugEventListener dbg) {
super(input instanceof DebugTreeNodeStream?input:new DebugTreeNodeStream(input,dbg));
setDebugListener(dbg);
}
public DebugTreeParser(ASTNodeStream input) {
super(input instanceof DebugTreeNodeStream?input:new DebugTreeNodeStream(input,null));
}
/** Provide a new debug event listener for this parser. Notify the
* input stream too that it should send events to this listener.
*/
public void setDebugListener(DebugEventListener dbg) {
if ( _input instanceof DebugTreeNodeStream ) {
((DebugTreeNodeStream) _input).setDebugListener(dbg);
}
this.dbg = dbg;
}
public DebugEventListener getDebugListener() {
return dbg;
}
public void reportError(IOException e) {
System.err.println(e);
e.printStackTrace(System.err);
}
public void reportError(RecognitionException e) {
dbg.recognitionException(e);
}
// protected Object getMissingSymbol(IntStream input,
// RecognitionException e,
// int expectedTokenType,
// IntervalSet follow)
// {
// Object o = super.getMissingSymbol(input, e, expectedTokenType, follow);
// dbg.consumeNode(o);
// return o;
// }
public void beginResync() {
dbg.beginResync();
}
public void endResync() {
dbg.endResync();
}
}

View File

@ -1,513 +0,0 @@
/*
[The "BSD license"]
Copyright (c) 2005-2009 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.debug;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.misc.Interval;
import org.antlr.v4.runtime.tree.BaseAST;
import java.io.*;
import java.net.*;
import java.util.StringTokenizer;
public class RemoteDebugEventSocketListener implements Runnable {
static final int MAX_EVENT_ELEMENTS = 8;
DebugEventListener listener;
String machine;
int port;
Socket channel = null;
PrintWriter out;
BufferedReader in;
String event;
/** Version of ANTLR (dictates events) */
public String version;
public String grammarFileName;
/** Track the last token index we saw during a consume. If same, then
* set a flag that we have a problem.
*/
int previousTokenIndex = -1;
boolean tokenIndexesInvalid = false;
public static class ProxyToken implements Token {
int index;
int type;
int channel;
int line;
int charPos;
String text;
public ProxyToken(int index) { this.index = index; }
public ProxyToken(int index, int type, int channel,
int line, int charPos, String text)
{
this.index = index;
this.type = type;
this.channel = channel;
this.line = line;
this.charPos = charPos;
this.text = text;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public int getType() {
return type;
}
public void setType(int ttype) {
this.type = ttype;
}
public int getLine() {
return line;
}
public void setLine(int line) {
this.line = line;
}
public int getCharPositionInLine() {
return charPos;
}
public void setCharPositionInLine(int pos) {
this.charPos = pos;
}
public int getChannel() {
return channel;
}
public void setChannel(int channel) {
this.channel = channel;
}
public int getTokenIndex() {
return index;
}
public void setTokenIndex(int index) {
this.index = index;
}
public TokenSource getTokenSource() {
return null;
}
public String toString() {
String channelStr = "";
if ( channel!= Token.DEFAULT_CHANNEL ) {
channelStr=",channel="+channel;
}
return "["+getText()+"/<"+type+">"+channelStr+","+line+":"+getCharPositionInLine()+",@"+index+"]";
}
}
public static class ProxyTree extends BaseAST {
public int ID;
public int type;
public int line = 0;
public int charPos = -1;
public int tokenIndex = -1;
public String text;
public ProxyTree(int ID, int type, int line, int charPos, int tokenIndex, String text) {
this.ID = ID;
this.type = type;
this.line = line;
this.charPos = charPos;
this.tokenIndex = tokenIndex;
this.text = text;
}
public ProxyTree(int ID) { this.ID = ID; }
public int getCharPositionInLine() {
return charPos;
}
public Token getPayload() {
return null;
}
public int getLine() {
return line;
}
public Interval getSourceInterval() {
return new Interval(tokenIndex, tokenIndex);
}
public int getType() { return type; }
public String getText() { return text; }
public String toString() {
return "fix this";
}
}
public RemoteDebugEventSocketListener(DebugEventListener listener,
String machine,
int port) throws IOException
{
this.listener = listener;
this.machine = machine;
this.port = port;
if( !openConnection() ) {
throw new ConnectException();
}
}
protected void eventHandler() {
try {
handshake();
event = in.readLine();
while ( event!=null ) {
dispatch(event);
ack();
event = in.readLine();
}
}
catch (Exception e) {
System.err.println(e);
e.printStackTrace(System.err);
}
finally {
closeConnection();
}
}
protected boolean openConnection() {
boolean success = false;
try {
channel = new Socket(machine, port);
channel.setTcpNoDelay(true);
OutputStream os = channel.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os, "UTF8");
out = new PrintWriter(new BufferedWriter(osw));
InputStream is = channel.getInputStream();
InputStreamReader isr = new InputStreamReader(is, "UTF8");
in = new BufferedReader(isr);
success = true;
} catch(Exception e) {
System.err.println(e);
}
return success;
}
protected void closeConnection() {
try {
in.close(); in = null;
out.close(); out = null;
channel.close(); channel=null;
}
catch (Exception e) {
System.err.println(e);
e.printStackTrace(System.err);
}
finally {
if ( in!=null ) {
try {in.close();} catch (IOException ioe) {
System.err.println(ioe);
}
}
if ( out!=null ) {
out.close();
}
if ( channel!=null ) {
try {channel.close();} catch (IOException ioe) {
System.err.println(ioe);
}
}
}
}
protected void handshake() throws IOException {
String antlrLine = in.readLine();
String[] antlrElements = getEventElements(antlrLine);
version = antlrElements[1];
String grammarLine = in.readLine();
String[] grammarElements = getEventElements(grammarLine);
grammarFileName = grammarElements[1];
ack();
listener.commence(); // inform listener after handshake
}
protected void ack() {
out.println("ack");
out.flush();
}
protected void dispatch(String line) {
//System.out.println("event: "+line);
String[] elements = getEventElements(line);
if ( elements==null || elements[0]==null ) {
System.err.println("unknown debug event: "+line);
return;
}
if ( elements[0].equals("enterRule") ) {
listener.enterRule(elements[1], elements[2]);
}
else if ( elements[0].equals("exitRule") ) {
listener.exitRule(elements[1], elements[2]);
}
else if ( elements[0].equals("enterAlt") ) {
listener.enterAlt(Integer.parseInt(elements[1]));
}
else if ( elements[0].equals("enterSubRule") ) {
listener.enterSubRule(Integer.parseInt(elements[1]));
}
else if ( elements[0].equals("exitSubRule") ) {
listener.exitSubRule(Integer.parseInt(elements[1]));
}
else if ( elements[0].equals("enterDecision") ) {
listener.enterDecision(Integer.parseInt(elements[1]), elements[2].equals("true"));
}
else if ( elements[0].equals("exitDecision") ) {
listener.exitDecision(Integer.parseInt(elements[1]));
}
else if ( elements[0].equals("location") ) {
listener.location(Integer.parseInt(elements[1]),
Integer.parseInt(elements[2]));
}
else if ( elements[0].equals("consumeToken") ) {
ProxyToken t = deserializeToken(elements, 1);
if ( t.getTokenIndex() == previousTokenIndex ) {
tokenIndexesInvalid = true;
}
previousTokenIndex = t.getTokenIndex();
listener.consumeToken(t);
}
else if ( elements[0].equals("consumeHiddenToken") ) {
ProxyToken t = deserializeToken(elements, 1);
if ( t.getTokenIndex() == previousTokenIndex ) {
tokenIndexesInvalid = true;
}
previousTokenIndex = t.getTokenIndex();
listener.consumeHiddenToken(t);
}
else if ( elements[0].equals("LT") ) {
Token t = deserializeToken(elements, 2);
listener.LT(Integer.parseInt(elements[1]), t);
}
else if ( elements[0].equals("exception") ) {
String excName = elements[1];
String indexS = elements[2];
String lineS = elements[3];
String posS = elements[4];
Class excClass = null;
try {
excClass = Class.forName(excName);
RecognitionException e =
(RecognitionException)excClass.newInstance();
e.index = Integer.parseInt(indexS);
e.line = Integer.parseInt(lineS);
e.charPositionInLine = Integer.parseInt(posS);
listener.recognitionException(e);
}
catch (ClassNotFoundException cnfe) {
System.err.println("can't find class "+cnfe);
cnfe.printStackTrace(System.err);
}
catch (InstantiationException ie) {
System.err.println("can't instantiate class "+ie);
ie.printStackTrace(System.err);
}
catch (IllegalAccessException iae) {
System.err.println("can't access class "+iae);
iae.printStackTrace(System.err);
}
}
else if ( elements[0].equals("beginResync") ) {
listener.beginResync();
}
else if ( elements[0].equals("endResync") ) {
listener.endResync();
}
else if ( elements[0].equals("terminate") ) {
listener.terminate();
}
else if ( elements[0].equals("semanticPredicate") ) {
Boolean result = Boolean.valueOf(elements[1]);
String predicateText = elements[2];
predicateText = unEscapeNewlines(predicateText);
listener.semanticPredicate(result.booleanValue(),
predicateText);
}
else if ( elements[0].equals("consumeNode") ) {
ProxyTree node = deserializeNode(elements, 1);
listener.consumeNode(node);
}
else if ( elements[0].equals("LN") ) {
int i = Integer.parseInt(elements[1]);
ProxyTree node = deserializeNode(elements, 2);
listener.LT(i, node);
}
else if ( elements[0].equals("createNodeFromTokenElements") ) {
int ID = Integer.parseInt(elements[1]);
int type = Integer.parseInt(elements[2]);
String text = elements[3];
text = unEscapeNewlines(text);
ProxyTree node = new ProxyTree(ID, type, -1, -1, -1, text);
listener.createNode(node);
}
else if ( elements[0].equals("createNode") ) {
int ID = Integer.parseInt(elements[1]);
int tokenIndex = Integer.parseInt(elements[2]);
// create dummy node/token filled with ID, tokenIndex
ProxyTree node = new ProxyTree(ID);
ProxyToken token = new ProxyToken(tokenIndex);
listener.createNode(node, token);
}
else if ( elements[0].equals("nilNode") ) {
int ID = Integer.parseInt(elements[1]);
ProxyTree node = new ProxyTree(ID);
listener.nilNode(node);
}
else if ( elements[0].equals("errorNode") ) {
// TODO: do we need a special tree here?
int ID = Integer.parseInt(elements[1]);
int type = Integer.parseInt(elements[2]);
String text = elements[3];
text = unEscapeNewlines(text);
ProxyTree node = new ProxyTree(ID, type, -1, -1, -1, text);
listener.errorNode(node);
}
else if ( elements[0].equals("becomeRoot") ) {
int newRootID = Integer.parseInt(elements[1]);
int oldRootID = Integer.parseInt(elements[2]);
ProxyTree newRoot = new ProxyTree(newRootID);
ProxyTree oldRoot = new ProxyTree(oldRootID);
listener.becomeRoot(newRoot, oldRoot);
}
else if ( elements[0].equals("addChild") ) {
int rootID = Integer.parseInt(elements[1]);
int childID = Integer.parseInt(elements[2]);
ProxyTree root = new ProxyTree(rootID);
ProxyTree child = new ProxyTree(childID);
listener.addChild(root, child);
}
else if ( elements[0].equals("setTokenBoundaries") ) {
int ID = Integer.parseInt(elements[1]);
ProxyTree node = new ProxyTree(ID);
listener.setTokenBoundaries(
node,
Integer.parseInt(elements[2]),
Integer.parseInt(elements[3]));
}
else {
System.err.println("unknown debug event: "+line);
}
}
protected ProxyTree deserializeNode(String[] elements, int offset) {
int ID = Integer.parseInt(elements[offset+0]);
int type = Integer.parseInt(elements[offset+1]);
int tokenLine = Integer.parseInt(elements[offset+2]);
int charPositionInLine = Integer.parseInt(elements[offset+3]);
int tokenIndex = Integer.parseInt(elements[offset+4]);
String text = elements[offset+5];
text = unEscapeNewlines(text);
return new ProxyTree(ID, type, tokenLine, charPositionInLine, tokenIndex, text);
}
protected ProxyToken deserializeToken(String[] elements,
int offset)
{
String indexS = elements[offset+0];
String typeS = elements[offset+1];
String channelS = elements[offset+2];
String lineS = elements[offset+3];
String posS = elements[offset+4];
String text = elements[offset+5];
text = unEscapeNewlines(text);
int index = Integer.parseInt(indexS);
ProxyToken t =
new ProxyToken(index,
Integer.parseInt(typeS),
Integer.parseInt(channelS),
Integer.parseInt(lineS),
Integer.parseInt(posS),
text);
return t;
}
/** Create a thread to listen to the remote running recognizer */
public void start() {
Thread t = new Thread(this);
t.start();
}
public void run() {
eventHandler();
}
// M i s c
public String[] getEventElements(String event) {
if ( event==null ) {
return null;
}
String[] elements = new String[MAX_EVENT_ELEMENTS];
String str = null; // a string element if present (must be last)
try {
int firstQuoteIndex = event.indexOf('"');
if ( firstQuoteIndex>=0 ) {
// treat specially; has a string argument like "a comment\n
// Note that the string is terminated by \n not end quote.
// Easier to parse that way.
String eventWithoutString = event.substring(0,firstQuoteIndex);
str = event.substring(firstQuoteIndex+1,event.length());
event = eventWithoutString;
}
StringTokenizer st = new StringTokenizer(event, "\t", false);
int i = 0;
while ( st.hasMoreTokens() ) {
if ( i>=MAX_EVENT_ELEMENTS ) {
// ErrorManager.internalError("event has more than "+MAX_EVENT_ELEMENTS+" args: "+event);
return elements;
}
elements[i] = st.nextToken();
i++;
}
if ( str!=null ) {
elements[i] = str;
}
}
catch (Exception e) {
e.printStackTrace(System.err);
}
return elements;
}
protected String unEscapeNewlines(String txt) {
// this unescape is slow but easy to understand
txt = txt.replaceAll("%0A","\n"); // unescape \n
txt = txt.replaceAll("%0D","\r"); // unescape \r
txt = txt.replaceAll("%25","%"); // undo escaped escape chars
return txt;
}
public boolean tokenIndexesAreInvalid() {
return false;
//return tokenIndexesInvalid;
}
}

View File

@ -1,96 +0,0 @@
/*
[The "BSD license"]
Copyright (c) 2005-2009 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.debug;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.ASTAdaptor;
/** Print out (most of) the events... Useful for debugging, testing... */
public class TraceDebugEventListener extends BlankDebugEventListener {
ASTAdaptor adaptor;
public TraceDebugEventListener(ASTAdaptor adaptor) {
this.adaptor = adaptor;
}
public void enterRule(String ruleName) { System.out.println("enterRule "+ruleName); }
public void exitRule(String ruleName) { System.out.println("exitRule "+ruleName); }
public void enterSubRule(int decisionNumber) { System.out.println("enterSubRule"); }
public void exitSubRule(int decisionNumber) { System.out.println("exitSubRule"); }
public void location(int line, int pos) {System.out.println("location "+line+":"+pos);}
// Tree parsing stuff
public void consumeNode(Object t) {
int ID = adaptor.getUniqueID(t);
String text = adaptor.getText(t);
int type = adaptor.getType(t);
System.out.println("consumeNode "+ID+" "+text+" "+type);
}
public void LT(int i, Object t) {
int ID = adaptor.getUniqueID(t);
String text = adaptor.getText(t);
int type = adaptor.getType(t);
System.out.println("LT "+i+" "+ID+" "+text+" "+type);
}
// AST stuff
public void nilNode(Object t) {System.out.println("nilNode "+adaptor.getUniqueID(t));}
public void createNode(Object t) {
int ID = adaptor.getUniqueID(t);
String text = adaptor.getText(t);
int type = adaptor.getType(t);
System.out.println("create "+ID+": "+text+", "+type);
}
public void createNode(Object node, Token token) {
int ID = adaptor.getUniqueID(node);
String text = adaptor.getText(node);
int tokenIndex = token.getTokenIndex();
System.out.println("create "+ID+": "+tokenIndex);
}
public void becomeRoot(Object newRoot, Object oldRoot) {
System.out.println("becomeRoot "+adaptor.getUniqueID(newRoot)+", "+
adaptor.getUniqueID(oldRoot));
}
public void addChild(Object root, Object child) {
System.out.println("addChild "+adaptor.getUniqueID(root)+", "+
adaptor.getUniqueID(child));
}
public void setTokenBoundaries(Object t, int tokenStartIndex, int tokenStopIndex) {
System.out.println("setTokenBoundaries "+adaptor.getUniqueID(t)+", "+
tokenStartIndex+", "+tokenStopIndex);
}
}

View File

@ -1,67 +0,0 @@
/*
[The "BSD license"]
Copyright (c) 2005-2009 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.debug;
import org.antlr.v4.runtime.IntStream;
import org.antlr.v4.runtime.TokenStream;
/** The default tracer mimics the traceParser behavior of ANTLR 2.x.
* This listens for debugging events from the parser and implies
* that you cannot debug and trace at the same time.
*/
public class Tracer extends BlankDebugEventListener {
public IntStream input;
protected int level = 0;
public Tracer(IntStream input) {
this.input = input;
}
@Override
public void enterRule(String grammarFileName, String ruleName) {
for (int i=1; i<=level; i++) {System.out.print(" ");}
System.out.println("> "+ruleName+" lookahead(1)="+getInputSymbol(1));
level++;
}
@Override
public void exitRule(String grammarFileName, String ruleName) {
level--;
for (int i=1; i<=level; i++) {System.out.print(" ");}
System.out.println("< "+ruleName+" lookahead(1)="+getInputSymbol(1));
}
protected Object getInputSymbol(int k) {
if ( input instanceof TokenStream) {
return ((TokenStream)input).LT(k);
}
return new Character((char)input.LA(k));
}
}

View File

@ -99,10 +99,10 @@ public class CommonErrorNode extends CommonAST {
", resync="+getText()+">";
}
else if ( trappedException instanceof MismatchedTokenException ) {
return "<mismatched token: "+trappedException.token+", resync="+getText()+">";
return "<mismatched token: "+trappedException.offendingToken +", resync="+getText()+">";
}
else if ( trappedException instanceof NoViableAltException ) {
return "<unexpected: "+trappedException.token+
return "<unexpected: "+trappedException.offendingToken +
", resync="+getText()+">";
}
return "<error: "+getText()+">";

View File

@ -148,8 +148,11 @@ public class TreeParser extends BaseRecognizer {
* the input tree not the user.
*/
public String getErrorHeader(RecognitionException e) {
// todo: might not have token; use node?
int line = e.offendingToken.getLine();
int charPositionInLine = e.offendingToken.getCharPositionInLine();
return getGrammarFileName()+": node from "+
(e.approximateLineInfo?"after ":"")+"line "+e.line+":"+e.charPositionInLine;
(e.approximateLineInfo?"after ":"")+"line "+line+":"+charPositionInLine;
}
/** Tree parsers parse nodes they usually have a token object as
@ -158,10 +161,10 @@ public class TreeParser extends BaseRecognizer {
public String getErrorMessage(RecognitionException e, String[] tokenNames) {
if ( this instanceof TreeParser ) {
ASTAdaptor adaptor = ((ASTNodeStream)e.input).getTreeAdaptor();
e.token = adaptor.getToken(e.node);
if ( e.token==null ) { // could be an UP/DOWN node
e.token = new CommonToken(adaptor.getType(e.node),
adaptor.getText(e.node));
e.offendingToken = adaptor.getToken(e.offendingNode);
if ( e.offendingToken ==null ) { // could be an UP/DOWN node
e.offendingToken = new CommonToken(adaptor.getType(e.offendingNode),
adaptor.getText(e.offendingNode));
}
}
return super.getErrorMessage(e);

View File

@ -86,8 +86,10 @@ public <file.ASTLabelType> match(int ttype) throws RecognitionException {
Parser_(parser, funcs, atn, sempredFuncs, ctor, extras) ::= <<
@SuppressWarnings({"all", "warnings", "unchecked", "unused"})
public class <parser.name> extends <parser.superclass> {
<if(parser.tokens)>
public static final int
<parser.tokens:{k | <k>=<parser.tokens.(k)>}; separator=", ", wrap, anchor>;
<endif>
public static final String[] tokenNames = {
"\<INVALID>", "\<INVALID>", "\<INVALID>",
<parser.tokenNames:{k | "<k>"}; separator=", ", wrap, anchor>

View File

@ -68,8 +68,8 @@ public class TestATNInterpreter extends BaseTest {
checkMatchedAlt(lg, g, "ac", 1);
}
catch (NoViableAltException re) {
errorIndex = re.index;
errorTokenType = re.token.getType();
errorIndex = re.offendingTokenIndex;
errorTokenType = re.offendingToken.getType();
}
assertEquals(1, errorIndex);
assertEquals(errorTokenType, 5);
@ -94,8 +94,8 @@ public class TestATNInterpreter extends BaseTest {
checkMatchedAlt(lg, g, "abd", 1);
}
catch (NoViableAltException re) {
errorIndex = re.index;
errorTokenType = re.token.getType();
errorIndex = re.offendingTokenIndex;
errorTokenType = re.offendingToken.getType();
}
assertEquals(2, errorIndex);
assertEquals(errorTokenType, 6);
@ -117,8 +117,8 @@ public class TestATNInterpreter extends BaseTest {
checkMatchedAlt(lg, g, "abd", 1);
}
catch (NoViableAltException re) {
errorIndex = re.index;
errorTokenType = re.token.getType();
errorIndex = re.offendingTokenIndex;
errorTokenType = re.offendingToken.getType();
}
assertEquals(2, errorIndex);
assertEquals(errorTokenType, 6);
@ -186,8 +186,8 @@ public class TestATNInterpreter extends BaseTest {
checkMatchedAlt(lg, g, "abd", 1);
}
catch (NoViableAltException re) {
errorIndex = re.index;
errorTokenType = re.token.getType();
errorIndex = re.offendingTokenIndex;
errorTokenType = re.offendingToken.getType();
}
assertEquals(2, errorIndex);
assertEquals(6, errorTokenType);

View File

@ -0,0 +1,96 @@
/*
* [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.test;
import org.junit.Test;
/** test runtime parse errors */
public class TestParseErrors extends BaseTest {
@Test public void testLL2() throws Exception {
String grammar =
"grammar T;\n" +
"a : 'a' 'b'" +
" | 'a' 'c'" +
";\n" +
"q : 'e' ;\n" +
"WS : ' ' ;\n";
String found = execParser("T.g", grammar, "TParser", "TLexer", "a", "ae", false);
String expecting = "line 1:1 no viable alternative at input 'e'\n";
String result = stderrDuringParse;
assertEquals(expecting, result);
}
@Test public void testLL3() throws Exception {
String grammar =
"grammar T;\n" +
"a : 'a' 'b'* 'c'" +
" | 'a' 'b' 'd'" +
" ;\n" +
"q : 'e' ;\n";
System.out.println(grammar);
String found = execParser("T.g", grammar, "TParser", "TLexer", "a", "abe", false);
String expecting = "line 1:2 no viable alternative at input 'e'\n";
String result = stderrDuringParse;
assertEquals(expecting, result);
}
@Test public void testLLStar() throws Exception {
String grammar =
"grammar T;\n" +
"a : 'a'+ 'b'" +
" | 'a'+ 'c'" +
";\n" +
"q : 'e' ;\n";
String found = execParser("T.g", grammar, "TParser", "TLexer", "a", "aaae", false);
String expecting = "line 1:3 no viable alternative at input 'e'\n";
String result = stderrDuringParse;
assertEquals(expecting, result);
}
@Test public void testLL1ErrorInfo() throws Exception {
String grammar =
"grammar T;\n" +
"start : animal (AND acClass)? service EOF;\n" +
"animal : (DOG | CAT );\n" +
"service : (HARDWARE | SOFTWARE) ;\n" +
"AND : 'and';\n" +
"DOG : 'dog';\n" +
"CAT : 'cat';\n" +
"HARDWARE: 'hardware';\n" +
"SOFTWARE: 'software';\n" +
"WS : ' ' {skip();} ;" +
"acClass\n" +
"@init\n" +
"{ System.out.println(computeContextSensitiveRuleFOLLOW().toString(tokenNames)); }\n" +
" : ;\n";
String result = execParser("T.g", grammar, "TParser", "TLexer", "start", "dog and software", false);
String expecting = "{HARDWARE,SOFTWARE}\n";
assertEquals(expecting, result);
}
}