00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 package org.antlr.runtime.debug;
00029
00030 import org.antlr.runtime.RecognitionException;
00031 import org.antlr.runtime.Token;
00032 import org.antlr.runtime.CharStream;
00033 import org.antlr.runtime.tree.BaseTree;
00034 import org.antlr.runtime.tree.Tree;
00035
00036 import java.io.*;
00037 import java.net.ConnectException;
00038 import java.net.Socket;
00039 import java.util.StringTokenizer;
00040
00041 public class RemoteDebugEventSocketListener implements Runnable {
00042 static final int MAX_EVENT_ELEMENTS = 8;
00043 DebugEventListener listener;
00044 String machine;
00045 int port;
00046 Socket channel = null;
00047 PrintWriter out;
00048 BufferedReader in;
00049 String event;
00051 public String version;
00052 public String grammarFileName;
00056 int previousTokenIndex = -1;
00057 boolean tokenIndexesInvalid = false;
00058
00059 public static class ProxyToken implements Token {
00060 int index;
00061 int type;
00062 int channel;
00063 int line;
00064 int charPos;
00065 String text;
00066 public ProxyToken(int index) { this.index = index; }
00067 public ProxyToken(int index, int type, int channel,
00068 int line, int charPos, String text)
00069 {
00070 this.index = index;
00071 this.type = type;
00072 this.channel = channel;
00073 this.line = line;
00074 this.charPos = charPos;
00075 this.text = text;
00076 }
00077 public String getText() {
00078 return text;
00079 }
00080 public void setText(String text) {
00081 this.text = text;
00082 }
00083 public int getType() {
00084 return type;
00085 }
00086 public void setType(int ttype) {
00087 this.type = ttype;
00088 }
00089 public int getLine() {
00090 return line;
00091 }
00092 public void setLine(int line) {
00093 this.line = line;
00094 }
00095 public int getCharPositionInLine() {
00096 return charPos;
00097 }
00098 public void setCharPositionInLine(int pos) {
00099 this.charPos = pos;
00100 }
00101 public int getChannel() {
00102 return channel;
00103 }
00104 public void setChannel(int channel) {
00105 this.channel = channel;
00106 }
00107 public int getTokenIndex() {
00108 return index;
00109 }
00110 public void setTokenIndex(int index) {
00111 this.index = index;
00112 }
00113 public CharStream getInputStream() {
00114 return null;
00115 }
00116 public void setInputStream(CharStream input) {
00117 }
00118 public String toString() {
00119 String channelStr = "";
00120 if ( channel!=Token.DEFAULT_CHANNEL ) {
00121 channelStr=",channel="+channel;
00122 }
00123 return "["+getText()+"/<"+type+">"+channelStr+","+line+":"+getCharPositionInLine()+",@"+index+"]";
00124 }
00125 }
00126
00127 public static class ProxyTree extends BaseTree {
00128 public int ID;
00129 public int type;
00130 public int line = 0;
00131 public int charPos = -1;
00132 public int tokenIndex = -1;
00133 public String text;
00134
00135 public ProxyTree(int ID, int type, int line, int charPos, int tokenIndex, String text) {
00136 this.ID = ID;
00137 this.type = type;
00138 this.line = line;
00139 this.charPos = charPos;
00140 this.tokenIndex = tokenIndex;
00141 this.text = text;
00142 }
00143
00144 public ProxyTree(int ID) { this.ID = ID; }
00145
00146 public int getTokenStartIndex() { return tokenIndex; }
00147 public void setTokenStartIndex(int index) { }
00148 public int getTokenStopIndex() { return 0; }
00149 public void setTokenStopIndex(int index) { }
00150 public Tree dupNode() { return null; }
00151 public int getType() { return type; }
00152 public String getText() { return text; }
00153 public String toString() {
00154 return "fix this";
00155 }
00156 }
00157
00158 public RemoteDebugEventSocketListener(DebugEventListener listener,
00159 String machine,
00160 int port) throws IOException
00161 {
00162 this.listener = listener;
00163 this.machine = machine;
00164 this.port = port;
00165
00166 if( !openConnection() ) {
00167 throw new ConnectException();
00168 }
00169 }
00170
00171 protected void eventHandler() {
00172 try {
00173 handshake();
00174 event = in.readLine();
00175 while ( event!=null ) {
00176 dispatch(event);
00177 ack();
00178 event = in.readLine();
00179 }
00180 }
00181 catch (Exception e) {
00182 System.err.println(e);
00183 e.printStackTrace(System.err);
00184 }
00185 finally {
00186 closeConnection();
00187 }
00188 }
00189
00190 protected boolean openConnection() {
00191 boolean success = false;
00192 try {
00193 channel = new Socket(machine, port);
00194 channel.setTcpNoDelay(true);
00195 OutputStream os = channel.getOutputStream();
00196 OutputStreamWriter osw = new OutputStreamWriter(os, "UTF8");
00197 out = new PrintWriter(new BufferedWriter(osw));
00198 InputStream is = channel.getInputStream();
00199 InputStreamReader isr = new InputStreamReader(is, "UTF8");
00200 in = new BufferedReader(isr);
00201 success = true;
00202 } catch(Exception e) {
00203 System.err.println(e);
00204 }
00205 return success;
00206 }
00207
00208 protected void closeConnection() {
00209 try {
00210 in.close(); in = null;
00211 out.close(); out = null;
00212 channel.close(); channel=null;
00213 }
00214 catch (Exception e) {
00215 System.err.println(e);
00216 e.printStackTrace(System.err);
00217 }
00218 finally {
00219 if ( in!=null ) {
00220 try {in.close();} catch (IOException ioe) {
00221 System.err.println(ioe);
00222 }
00223 }
00224 if ( out!=null ) {
00225 out.close();
00226 }
00227 if ( channel!=null ) {
00228 try {channel.close();} catch (IOException ioe) {
00229 System.err.println(ioe);
00230 }
00231 }
00232 }
00233
00234 }
00235
00236 protected void handshake() throws IOException {
00237 String antlrLine = in.readLine();
00238 String[] antlrElements = getEventElements(antlrLine);
00239 version = antlrElements[1];
00240 String grammarLine = in.readLine();
00241 String[] grammarElements = getEventElements(grammarLine);
00242 grammarFileName = grammarElements[1];
00243 ack();
00244 listener.commence();
00245 }
00246
00247 protected void ack() {
00248 out.println("ack");
00249 out.flush();
00250 }
00251
00252 protected void dispatch(String line) {
00253
00254 String[] elements = getEventElements(line);
00255 if ( elements==null || elements[0]==null ) {
00256 System.err.println("unknown debug event: "+line);
00257 return;
00258 }
00259 if ( elements[0].equals("enterRule") ) {
00260 listener.enterRule(elements[1], elements[2]);
00261 }
00262 else if ( elements[0].equals("exitRule") ) {
00263 listener.exitRule(elements[1], elements[2]);
00264 }
00265 else if ( elements[0].equals("enterAlt") ) {
00266 listener.enterAlt(Integer.parseInt(elements[1]));
00267 }
00268 else if ( elements[0].equals("enterSubRule") ) {
00269 listener.enterSubRule(Integer.parseInt(elements[1]));
00270 }
00271 else if ( elements[0].equals("exitSubRule") ) {
00272 listener.exitSubRule(Integer.parseInt(elements[1]));
00273 }
00274 else if ( elements[0].equals("enterDecision") ) {
00275 listener.enterDecision(Integer.parseInt(elements[1]), elements[2].equals("true"));
00276 }
00277 else if ( elements[0].equals("exitDecision") ) {
00278 listener.exitDecision(Integer.parseInt(elements[1]));
00279 }
00280 else if ( elements[0].equals("location") ) {
00281 listener.location(Integer.parseInt(elements[1]),
00282 Integer.parseInt(elements[2]));
00283 }
00284 else if ( elements[0].equals("consumeToken") ) {
00285 ProxyToken t = deserializeToken(elements, 1);
00286 if ( t.getTokenIndex() == previousTokenIndex ) {
00287 tokenIndexesInvalid = true;
00288 }
00289 previousTokenIndex = t.getTokenIndex();
00290 listener.consumeToken(t);
00291 }
00292 else if ( elements[0].equals("consumeHiddenToken") ) {
00293 ProxyToken t = deserializeToken(elements, 1);
00294 if ( t.getTokenIndex() == previousTokenIndex ) {
00295 tokenIndexesInvalid = true;
00296 }
00297 previousTokenIndex = t.getTokenIndex();
00298 listener.consumeHiddenToken(t);
00299 }
00300 else if ( elements[0].equals("LT") ) {
00301 Token t = deserializeToken(elements, 2);
00302 listener.LT(Integer.parseInt(elements[1]), t);
00303 }
00304 else if ( elements[0].equals("mark") ) {
00305 listener.mark(Integer.parseInt(elements[1]));
00306 }
00307 else if ( elements[0].equals("rewind") ) {
00308 if ( elements[1]!=null ) {
00309 listener.rewind(Integer.parseInt(elements[1]));
00310 }
00311 else {
00312 listener.rewind();
00313 }
00314 }
00315 else if ( elements[0].equals("beginBacktrack") ) {
00316 listener.beginBacktrack(Integer.parseInt(elements[1]));
00317 }
00318 else if ( elements[0].equals("endBacktrack") ) {
00319 int level = Integer.parseInt(elements[1]);
00320 int successI = Integer.parseInt(elements[2]);
00321 listener.endBacktrack(level, successI==DebugEventListener.TRUE);
00322 }
00323 else if ( elements[0].equals("exception") ) {
00324 String excName = elements[1];
00325 String indexS = elements[2];
00326 String lineS = elements[3];
00327 String posS = elements[4];
00328 Class excClass = null;
00329 try {
00330 excClass = Class.forName(excName);
00331 RecognitionException e =
00332 (RecognitionException)excClass.newInstance();
00333 e.index = Integer.parseInt(indexS);
00334 e.line = Integer.parseInt(lineS);
00335 e.charPositionInLine = Integer.parseInt(posS);
00336 listener.recognitionException(e);
00337 }
00338 catch (ClassNotFoundException cnfe) {
00339 System.err.println("can't find class "+cnfe);
00340 cnfe.printStackTrace(System.err);
00341 }
00342 catch (InstantiationException ie) {
00343 System.err.println("can't instantiate class "+ie);
00344 ie.printStackTrace(System.err);
00345 }
00346 catch (IllegalAccessException iae) {
00347 System.err.println("can't access class "+iae);
00348 iae.printStackTrace(System.err);
00349 }
00350 }
00351 else if ( elements[0].equals("beginResync") ) {
00352 listener.beginResync();
00353 }
00354 else if ( elements[0].equals("endResync") ) {
00355 listener.endResync();
00356 }
00357 else if ( elements[0].equals("terminate") ) {
00358 listener.terminate();
00359 }
00360 else if ( elements[0].equals("semanticPredicate") ) {
00361 Boolean result = Boolean.valueOf(elements[1]);
00362 String predicateText = elements[2];
00363 predicateText = unEscapeNewlines(predicateText);
00364 listener.semanticPredicate(result.booleanValue(),
00365 predicateText);
00366 }
00367 else if ( elements[0].equals("consumeNode") ) {
00368 ProxyTree node = deserializeNode(elements, 1);
00369 listener.consumeNode(node);
00370 }
00371 else if ( elements[0].equals("LN") ) {
00372 int i = Integer.parseInt(elements[1]);
00373 ProxyTree node = deserializeNode(elements, 2);
00374 listener.LT(i, node);
00375 }
00376 else if ( elements[0].equals("createNodeFromTokenElements") ) {
00377 int ID = Integer.parseInt(elements[1]);
00378 int type = Integer.parseInt(elements[2]);
00379 String text = elements[3];
00380 text = unEscapeNewlines(text);
00381 ProxyTree node = new ProxyTree(ID, type, -1, -1, -1, text);
00382 listener.createNode(node);
00383 }
00384 else if ( elements[0].equals("createNode") ) {
00385 int ID = Integer.parseInt(elements[1]);
00386 int tokenIndex = Integer.parseInt(elements[2]);
00387
00388 ProxyTree node = new ProxyTree(ID);
00389 ProxyToken token = new ProxyToken(tokenIndex);
00390 listener.createNode(node, token);
00391 }
00392 else if ( elements[0].equals("nilNode") ) {
00393 int ID = Integer.parseInt(elements[1]);
00394 ProxyTree node = new ProxyTree(ID);
00395 listener.nilNode(node);
00396 }
00397 else if ( elements[0].equals("errorNode") ) {
00398
00399 int ID = Integer.parseInt(elements[1]);
00400 int type = Integer.parseInt(elements[2]);
00401 String text = elements[3];
00402 text = unEscapeNewlines(text);
00403 ProxyTree node = new ProxyTree(ID, type, -1, -1, -1, text);
00404 listener.errorNode(node);
00405 }
00406 else if ( elements[0].equals("becomeRoot") ) {
00407 int newRootID = Integer.parseInt(elements[1]);
00408 int oldRootID = Integer.parseInt(elements[2]);
00409 ProxyTree newRoot = new ProxyTree(newRootID);
00410 ProxyTree oldRoot = new ProxyTree(oldRootID);
00411 listener.becomeRoot(newRoot, oldRoot);
00412 }
00413 else if ( elements[0].equals("addChild") ) {
00414 int rootID = Integer.parseInt(elements[1]);
00415 int childID = Integer.parseInt(elements[2]);
00416 ProxyTree root = new ProxyTree(rootID);
00417 ProxyTree child = new ProxyTree(childID);
00418 listener.addChild(root, child);
00419 }
00420 else if ( elements[0].equals("setTokenBoundaries") ) {
00421 int ID = Integer.parseInt(elements[1]);
00422 ProxyTree node = new ProxyTree(ID);
00423 listener.setTokenBoundaries(
00424 node,
00425 Integer.parseInt(elements[2]),
00426 Integer.parseInt(elements[3]));
00427 }
00428 else {
00429 System.err.println("unknown debug event: "+line);
00430 }
00431 }
00432
00433 protected ProxyTree deserializeNode(String[] elements, int offset) {
00434 int ID = Integer.parseInt(elements[offset+0]);
00435 int type = Integer.parseInt(elements[offset+1]);
00436 int tokenLine = Integer.parseInt(elements[offset+2]);
00437 int charPositionInLine = Integer.parseInt(elements[offset+3]);
00438 int tokenIndex = Integer.parseInt(elements[offset+4]);
00439 String text = elements[offset+5];
00440 text = unEscapeNewlines(text);
00441 return new ProxyTree(ID, type, tokenLine, charPositionInLine, tokenIndex, text);
00442 }
00443
00444 protected ProxyToken deserializeToken(String[] elements,
00445 int offset)
00446 {
00447 String indexS = elements[offset+0];
00448 String typeS = elements[offset+1];
00449 String channelS = elements[offset+2];
00450 String lineS = elements[offset+3];
00451 String posS = elements[offset+4];
00452 String text = elements[offset+5];
00453 text = unEscapeNewlines(text);
00454 int index = Integer.parseInt(indexS);
00455 ProxyToken t =
00456 new ProxyToken(index,
00457 Integer.parseInt(typeS),
00458 Integer.parseInt(channelS),
00459 Integer.parseInt(lineS),
00460 Integer.parseInt(posS),
00461 text);
00462 return t;
00463 }
00464
00466 public void start() {
00467 Thread t = new Thread(this);
00468 t.start();
00469 }
00470
00471 public void run() {
00472 eventHandler();
00473 }
00474
00475
00476
00477 public String[] getEventElements(String event) {
00478 if ( event==null ) {
00479 return null;
00480 }
00481 String[] elements = new String[MAX_EVENT_ELEMENTS];
00482 String str = null;
00483 try {
00484 int firstQuoteIndex = event.indexOf('"');
00485 if ( firstQuoteIndex>=0 ) {
00486
00487
00488
00489 String eventWithoutString = event.substring(0,firstQuoteIndex);
00490 str = event.substring(firstQuoteIndex+1,event.length());
00491 event = eventWithoutString;
00492 }
00493 StringTokenizer st = new StringTokenizer(event, "\t", false);
00494 int i = 0;
00495 while ( st.hasMoreTokens() ) {
00496 if ( i>=MAX_EVENT_ELEMENTS ) {
00497
00498 return elements;
00499 }
00500 elements[i] = st.nextToken();
00501 i++;
00502 }
00503 if ( str!=null ) {
00504 elements[i] = str;
00505 }
00506 }
00507 catch (Exception e) {
00508 e.printStackTrace(System.err);
00509 }
00510 return elements;
00511 }
00512
00513 protected String unEscapeNewlines(String txt) {
00514
00515 txt = txt.replaceAll("%0A","\n");
00516 txt = txt.replaceAll("%0D","\r");
00517 txt = txt.replaceAll("%25","%");
00518 return txt;
00519 }
00520
00521 public boolean tokenIndexesAreInvalid() {
00522 return false;
00523
00524 }
00525
00526 }
00527