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 String[] elements = getEventElements(line);
00254 if ( elements==null || elements[0]==null ) {
00255 System.err.println("unknown debug event: "+line);
00256 return;
00257 }
00258 if ( elements[0].equals("enterRule") ) {
00259 listener.enterRule(elements[1], elements[2]);
00260 }
00261 else if ( elements[0].equals("exitRule") ) {
00262 listener.exitRule(elements[1], elements[2]);
00263 }
00264 else if ( elements[0].equals("enterAlt") ) {
00265 listener.enterAlt(Integer.parseInt(elements[1]));
00266 }
00267 else if ( elements[0].equals("enterSubRule") ) {
00268 listener.enterSubRule(Integer.parseInt(elements[1]));
00269 }
00270 else if ( elements[0].equals("exitSubRule") ) {
00271 listener.exitSubRule(Integer.parseInt(elements[1]));
00272 }
00273 else if ( elements[0].equals("enterDecision") ) {
00274 listener.enterDecision(Integer.parseInt(elements[1]));
00275 }
00276 else if ( elements[0].equals("exitDecision") ) {
00277 listener.exitDecision(Integer.parseInt(elements[1]));
00278 }
00279 else if ( elements[0].equals("location") ) {
00280 listener.location(Integer.parseInt(elements[1]),
00281 Integer.parseInt(elements[2]));
00282 }
00283 else if ( elements[0].equals("consumeToken") ) {
00284 ProxyToken t = deserializeToken(elements, 1);
00285 if ( t.getTokenIndex() == previousTokenIndex ) {
00286 tokenIndexesInvalid = true;
00287 }
00288 previousTokenIndex = t.getTokenIndex();
00289 listener.consumeToken(t);
00290 }
00291 else if ( elements[0].equals("consumeHiddenToken") ) {
00292 ProxyToken t = deserializeToken(elements, 1);
00293 if ( t.getTokenIndex() == previousTokenIndex ) {
00294 tokenIndexesInvalid = true;
00295 }
00296 previousTokenIndex = t.getTokenIndex();
00297 listener.consumeHiddenToken(t);
00298 }
00299 else if ( elements[0].equals("LT") ) {
00300 Token t = deserializeToken(elements, 2);
00301 listener.LT(Integer.parseInt(elements[1]), t);
00302 }
00303 else if ( elements[0].equals("mark") ) {
00304 listener.mark(Integer.parseInt(elements[1]));
00305 }
00306 else if ( elements[0].equals("rewind") ) {
00307 if ( elements[1]!=null ) {
00308 listener.rewind(Integer.parseInt(elements[1]));
00309 }
00310 else {
00311 listener.rewind();
00312 }
00313 }
00314 else if ( elements[0].equals("beginBacktrack") ) {
00315 listener.beginBacktrack(Integer.parseInt(elements[1]));
00316 }
00317 else if ( elements[0].equals("endBacktrack") ) {
00318 int level = Integer.parseInt(elements[1]);
00319 int successI = Integer.parseInt(elements[2]);
00320 listener.endBacktrack(level, successI==DebugEventListener.TRUE);
00321 }
00322 else if ( elements[0].equals("exception") ) {
00323 String excName = elements[1];
00324 String indexS = elements[2];
00325 String lineS = elements[3];
00326 String posS = elements[4];
00327 Class excClass = null;
00328 try {
00329 excClass = Class.forName(excName);
00330 RecognitionException e =
00331 (RecognitionException)excClass.newInstance();
00332 e.index = Integer.parseInt(indexS);
00333 e.line = Integer.parseInt(lineS);
00334 e.charPositionInLine = Integer.parseInt(posS);
00335 listener.recognitionException(e);
00336 }
00337 catch (ClassNotFoundException cnfe) {
00338 System.err.println("can't find class "+cnfe);
00339 cnfe.printStackTrace(System.err);
00340 }
00341 catch (InstantiationException ie) {
00342 System.err.println("can't instantiate class "+ie);
00343 ie.printStackTrace(System.err);
00344 }
00345 catch (IllegalAccessException iae) {
00346 System.err.println("can't access class "+iae);
00347 iae.printStackTrace(System.err);
00348 }
00349 }
00350 else if ( elements[0].equals("beginResync") ) {
00351 listener.beginResync();
00352 }
00353 else if ( elements[0].equals("endResync") ) {
00354 listener.endResync();
00355 }
00356 else if ( elements[0].equals("terminate") ) {
00357 listener.terminate();
00358 }
00359 else if ( elements[0].equals("semanticPredicate") ) {
00360 Boolean result = Boolean.valueOf(elements[1]);
00361 String predicateText = elements[2];
00362 predicateText = unEscapeNewlines(predicateText);
00363 listener.semanticPredicate(result.booleanValue(),
00364 predicateText);
00365 }
00366 else if ( elements[0].equals("consumeNode") ) {
00367 ProxyTree node = deserializeNode(elements, 1);
00368 listener.consumeNode(node);
00369 }
00370 else if ( elements[0].equals("LN") ) {
00371 int i = Integer.parseInt(elements[1]);
00372 ProxyTree node = deserializeNode(elements, 2);
00373 listener.LT(i, node);
00374 }
00375 else if ( elements[0].equals("createNodeFromTokenElements") ) {
00376 int ID = Integer.parseInt(elements[1]);
00377 int type = Integer.parseInt(elements[2]);
00378 String text = elements[3];
00379 text = unEscapeNewlines(text);
00380 ProxyTree node = new ProxyTree(ID, type, -1, -1, -1, text);
00381 listener.createNode(node);
00382 }
00383 else if ( elements[0].equals("createNode") ) {
00384 int ID = Integer.parseInt(elements[1]);
00385 int tokenIndex = Integer.parseInt(elements[2]);
00386
00387 ProxyTree node = new ProxyTree(ID);
00388 ProxyToken token = new ProxyToken(tokenIndex);
00389 listener.createNode(node, token);
00390 }
00391 else if ( elements[0].equals("nilNode") ) {
00392 int ID = Integer.parseInt(elements[1]);
00393 ProxyTree node = new ProxyTree(ID);
00394 listener.nilNode(node);
00395 }
00396 else if ( elements[0].equals("errorNode") ) {
00397
00398 int ID = Integer.parseInt(elements[1]);
00399 int type = Integer.parseInt(elements[2]);
00400 String text = elements[3];
00401 text = unEscapeNewlines(text);
00402 ProxyTree node = new ProxyTree(ID, type, -1, -1, -1, text);
00403 listener.errorNode(node);
00404 }
00405 else if ( elements[0].equals("becomeRoot") ) {
00406 int newRootID = Integer.parseInt(elements[1]);
00407 int oldRootID = Integer.parseInt(elements[2]);
00408 ProxyTree newRoot = new ProxyTree(newRootID);
00409 ProxyTree oldRoot = new ProxyTree(oldRootID);
00410 listener.becomeRoot(newRoot, oldRoot);
00411 }
00412 else if ( elements[0].equals("addChild") ) {
00413 int rootID = Integer.parseInt(elements[1]);
00414 int childID = Integer.parseInt(elements[2]);
00415 ProxyTree root = new ProxyTree(rootID);
00416 ProxyTree child = new ProxyTree(childID);
00417 listener.addChild(root, child);
00418 }
00419 else if ( elements[0].equals("setTokenBoundaries") ) {
00420 int ID = Integer.parseInt(elements[1]);
00421 ProxyTree node = new ProxyTree(ID);
00422 listener.setTokenBoundaries(
00423 node,
00424 Integer.parseInt(elements[2]),
00425 Integer.parseInt(elements[3]));
00426 }
00427 else {
00428 System.err.println("unknown debug event: "+line);
00429 }
00430 }
00431
00432 protected ProxyTree deserializeNode(String[] elements, int offset) {
00433 int ID = Integer.parseInt(elements[offset+0]);
00434 int type = Integer.parseInt(elements[offset+1]);
00435 int tokenLine = Integer.parseInt(elements[offset+2]);
00436 int charPositionInLine = Integer.parseInt(elements[offset+3]);
00437 int tokenIndex = Integer.parseInt(elements[offset+4]);
00438 String text = elements[offset+5];
00439 text = unEscapeNewlines(text);
00440 return new ProxyTree(ID, type, tokenLine, charPositionInLine, tokenIndex, text);
00441 }
00442
00443 protected ProxyToken deserializeToken(String[] elements,
00444 int offset)
00445 {
00446 String indexS = elements[offset+0];
00447 String typeS = elements[offset+1];
00448 String channelS = elements[offset+2];
00449 String lineS = elements[offset+3];
00450 String posS = elements[offset+4];
00451 String text = elements[offset+5];
00452 text = unEscapeNewlines(text);
00453 int index = Integer.parseInt(indexS);
00454 ProxyToken t =
00455 new ProxyToken(index,
00456 Integer.parseInt(typeS),
00457 Integer.parseInt(channelS),
00458 Integer.parseInt(lineS),
00459 Integer.parseInt(posS),
00460 text);
00461 return t;
00462 }
00463
00465 public void start() {
00466 Thread t = new Thread(this);
00467 t.start();
00468 }
00469
00470 public void run() {
00471 eventHandler();
00472 }
00473
00474
00475
00476 public String[] getEventElements(String event) {
00477 if ( event==null ) {
00478 return null;
00479 }
00480 String[] elements = new String[MAX_EVENT_ELEMENTS];
00481 String str = null;
00482 try {
00483 int firstQuoteIndex = event.indexOf('"');
00484 if ( firstQuoteIndex>=0 ) {
00485
00486
00487
00488 String eventWithoutString = event.substring(0,firstQuoteIndex);
00489 str = event.substring(firstQuoteIndex+1,event.length());
00490 event = eventWithoutString;
00491 }
00492 StringTokenizer st = new StringTokenizer(event, " \t", false);
00493 int i = 0;
00494 while ( st.hasMoreTokens() ) {
00495 if ( i>=MAX_EVENT_ELEMENTS ) {
00496
00497 return elements;
00498 }
00499 elements[i] = st.nextToken();
00500 i++;
00501 }
00502 if ( str!=null ) {
00503 elements[i] = str;
00504 }
00505 }
00506 catch (Exception e) {
00507 e.printStackTrace(System.err);
00508 }
00509 return elements;
00510 }
00511
00512 protected String unEscapeNewlines(String txt) {
00513
00514 txt = txt.replaceAll("%0A","\n");
00515 txt = txt.replaceAll("%0D","\r");
00516 txt = txt.replaceAll("%25","%");
00517 return txt;
00518 }
00519
00520 public boolean tokenIndexesAreInvalid() {
00521 return false;
00522
00523 }
00524
00525 }
00526