package org.antlr.runtime.debug;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.Token;
import org.antlr.runtime.BaseRecognizer;
import org.antlr.runtime.tree.TreeAdaptor;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class DebugEventSocketProxy extends BlankDebugEventListener {
public static final int DEFAULT_DEBUGGER_PORT = 49100;
protected int port = DEFAULT_DEBUGGER_PORT;
protected ServerSocket serverSocket;
protected Socket socket;
protected String grammarFileName;
protected PrintWriter out;
protected BufferedReader in;
protected BaseRecognizer recognizer;
protected TreeAdaptor adaptor;
public DebugEventSocketProxy(BaseRecognizer recognizer, TreeAdaptor adaptor) {
this(recognizer, DEFAULT_DEBUGGER_PORT, adaptor);
}
public DebugEventSocketProxy(BaseRecognizer recognizer, int port, TreeAdaptor 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();
}
}
@Override
public void commence() {
}
@Override
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();
}
@Override
public void enterRule(String grammarFileName, String ruleName) {
transmit("enterRule\t"+grammarFileName+"\t"+ruleName);
}
@Override
public void enterAlt(int alt) {
transmit("enterAlt\t"+alt);
}
@Override
public void exitRule(String grammarFileName, String ruleName) {
transmit("exitRule\t"+grammarFileName+"\t"+ruleName);
}
@Override
public void enterSubRule(int decisionNumber) {
transmit("enterSubRule\t"+decisionNumber);
}
@Override
public void exitSubRule(int decisionNumber) {
transmit("exitSubRule\t"+decisionNumber);
}
@Override
public void enterDecision(int decisionNumber, boolean couldBacktrack) {
transmit("enterDecision\t"+decisionNumber+"\t"+couldBacktrack);
}
@Override
public void exitDecision(int decisionNumber) {
transmit("exitDecision\t"+decisionNumber);
}
@Override
public void consumeToken(Token t) {
String buf = serializeToken(t);
transmit("consumeToken\t"+buf);
}
@Override
public void consumeHiddenToken(Token t) {
String buf = serializeToken(t);
transmit("consumeHiddenToken\t"+buf);
}
@Override
public void LT(int i, Token t) {
if(t != null)
transmit("LT\t"+i+"\t"+serializeToken(t));
}
@Override
public void mark(int i) {
transmit("mark\t"+i);
}
@Override
public void rewind(int i) {
transmit("rewind\t"+i);
}
@Override
public void rewind() {
transmit("rewind");
}
@Override
public void beginBacktrack(int level) {
transmit("beginBacktrack\t"+level);
}
@Override
public void endBacktrack(int level, boolean successful) {
transmit("endBacktrack\t"+level+"\t"+(successful?TRUE:FALSE));
}
@Override
public void location(int line, int pos) {
transmit("location\t"+line+"\t"+pos);
}
@Override
public void recognitionException(RecognitionException e) {
StringBuilder buf = new StringBuilder(50);
buf.append("exception\t");
buf.append(e.getClass().getName());
buf.append("\t");
buf.append(e.index);
buf.append("\t");
buf.append(e.line);
buf.append("\t");
buf.append(e.charPositionInLine);
transmit(buf.toString());
}
@Override
public void beginResync() {
transmit("beginResync");
}
@Override
public void endResync() {
transmit("endResync");
}
@Override
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());
}
@Override
public void consumeNode(Object t) {
StringBuffer buf = new StringBuffer(50);
buf.append("consumeNode");
serializeNode(buf, t);
transmit(buf.toString());
}
@Override
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");
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);
}
@Override
public void nilNode(Object t) {
int ID = adaptor.getUniqueID(t);
transmit("nilNode\t"+ID);
}
@Override
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_TOKEN_TYPE);
serializeText(buf, text);
transmit(buf.toString());
}
@Override
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());
}
@Override
public void createNode(Object node, Token token) {
int ID = adaptor.getUniqueID(node);
int tokenIndex = token.getTokenIndex();
transmit("createNode\t"+ID+"\t"+tokenIndex);
}
@Override
public void becomeRoot(Object newRoot, Object oldRoot) {
int newRootID = adaptor.getUniqueID(newRoot);
int oldRootID = adaptor.getUniqueID(oldRoot);
transmit("becomeRoot\t"+newRootID+"\t"+oldRootID);
}
@Override
public void addChild(Object root, Object child) {
int rootID = adaptor.getUniqueID(root);
int childID = adaptor.getUniqueID(child);
transmit("addChild\t"+rootID+"\t"+childID);
}
@Override
public void setTokenBoundaries(Object t, int tokenStartIndex, int tokenStopIndex) {
int ID = adaptor.getUniqueID(t);
transmit("setTokenBoundaries\t"+ID+"\t"+tokenStartIndex+"\t"+tokenStopIndex);
}
public void setTreeAdaptor(TreeAdaptor adaptor) { this.adaptor = adaptor; }
public TreeAdaptor 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 = "";
}
text = escapeNewlines(text);
buf.append(text);
}
protected String escapeNewlines(String txt) {
txt = txt.replaceAll("%","%25");
txt = txt.replaceAll("\n","%0A");
txt = txt.replaceAll("\r","%0D");
return txt;
}
}