13447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein/*
23447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein [The "BSD license"]
33447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein Copyright (c) 2005-2009 Terence Parr
43447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein All rights reserved.
53447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
63447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein Redistribution and use in source and binary forms, with or without
73447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein modification, are permitted provided that the following conditions
83447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein are met:
93447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein 1. Redistributions of source code must retain the above copyright
103447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein     notice, this list of conditions and the following disclaimer.
113447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein 2. Redistributions in binary form must reproduce the above copyright
123447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein     notice, this list of conditions and the following disclaimer in the
133447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein     documentation and/or other materials provided with the distribution.
143447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein 3. The name of the author may not be used to endorse or promote products
153447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein     derived from this software without specific prior written permission.
163447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
173447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
183447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
193447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
203447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
213447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
223447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
263447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein */
283447a5916aa62f44de24cc441fc9987116ddff52Andrew Sappersteinpackage org.antlr.runtime.debug;
293447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
303447a5916aa62f44de24cc441fc9987116ddff52Andrew Sappersteinimport org.antlr.runtime.RecognitionException;
313447a5916aa62f44de24cc441fc9987116ddff52Andrew Sappersteinimport org.antlr.runtime.Token;
323447a5916aa62f44de24cc441fc9987116ddff52Andrew Sappersteinimport org.antlr.runtime.CharStream;
333447a5916aa62f44de24cc441fc9987116ddff52Andrew Sappersteinimport org.antlr.runtime.tree.BaseTree;
343447a5916aa62f44de24cc441fc9987116ddff52Andrew Sappersteinimport org.antlr.runtime.tree.Tree;
353447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
363447a5916aa62f44de24cc441fc9987116ddff52Andrew Sappersteinimport java.io.*;
373447a5916aa62f44de24cc441fc9987116ddff52Andrew Sappersteinimport java.net.ConnectException;
383447a5916aa62f44de24cc441fc9987116ddff52Andrew Sappersteinimport java.net.Socket;
393447a5916aa62f44de24cc441fc9987116ddff52Andrew Sappersteinimport java.util.StringTokenizer;
403447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
413447a5916aa62f44de24cc441fc9987116ddff52Andrew Sappersteinpublic class RemoteDebugEventSocketListener implements Runnable {
423447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	static final int MAX_EVENT_ELEMENTS = 8;
433447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	DebugEventListener listener;
443447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	String machine;
453447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	int port;
463447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	Socket channel = null;
473447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	PrintWriter out;
483447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	BufferedReader in;
493447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	String event;
503447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	/** Version of ANTLR (dictates events) */
513447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	public String version;
523447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	public String grammarFileName;
533447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	/** Track the last token index we saw during a consume.  If same, then
543447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	 *  set a flag that we have a problem.
553447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	 */
563447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	int previousTokenIndex = -1;
573447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	boolean tokenIndexesInvalid = false;
583447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
593447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	public static class ProxyToken implements Token {
603447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		int index;
613447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		int type;
623447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		int channel;
633447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		int line;
643447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		int charPos;
653447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		String text;
663447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public ProxyToken(int index) { this.index = index; }
673447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public ProxyToken(int index, int type, int channel,
683447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein						  int line, int charPos, String text)
693447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		{
703447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			this.index = index;
713447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			this.type = type;
723447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			this.channel = channel;
733447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			this.line = line;
743447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			this.charPos = charPos;
753447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			this.text = text;
763447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
773447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public String getText() {
783447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			return text;
793447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
803447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public void setText(String text) {
813447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			this.text = text;
823447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
833447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public int getType() {
843447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			return type;
853447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
863447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public void setType(int ttype) {
873447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			this.type = ttype;
883447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
893447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public int getLine() {
903447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			return line;
913447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
923447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public void setLine(int line) {
933447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			this.line = line;
943447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
953447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public int getCharPositionInLine() {
963447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			return charPos;
973447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
983447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public void setCharPositionInLine(int pos) {
993447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			this.charPos = pos;
1003447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
1013447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public int getChannel() {
1023447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			return channel;
1033447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
1043447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public void setChannel(int channel) {
1053447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			this.channel = channel;
1063447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
1073447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public int getTokenIndex() {
1083447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			return index;
1093447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
1103447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public void setTokenIndex(int index) {
1113447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			this.index = index;
1123447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
1133447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public CharStream getInputStream() {
1143447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			return null;
1153447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
1163447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public void setInputStream(CharStream input) {
1173447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
1183447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public String toString() {
1193447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			String channelStr = "";
1203447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			if ( channel!=Token.DEFAULT_CHANNEL ) {
1213447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				channelStr=",channel="+channel;
1223447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			}
1233447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			return "["+getText()+"/<"+type+">"+channelStr+","+line+":"+getCharPositionInLine()+",@"+index+"]";
1243447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
1253447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	}
1263447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
1273447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	public static class ProxyTree extends BaseTree {
1283447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public int ID;
1293447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public int type;
1303447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public int line = 0;
1313447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public int charPos = -1;
1323447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public int tokenIndex = -1;
1333447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public String text;
1343447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
1353447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public ProxyTree(int ID, int type, int line, int charPos, int tokenIndex, String text) {
1363447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			this.ID = ID;
1373447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			this.type = type;
1383447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			this.line = line;
1393447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			this.charPos = charPos;
1403447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			this.tokenIndex = tokenIndex;
1413447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			this.text = text;
1423447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
1433447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
1443447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public ProxyTree(int ID) { this.ID = ID; }
1453447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
1463447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public int getTokenStartIndex() { return tokenIndex; }
1473447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public void setTokenStartIndex(int index) {	}
1483447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public int getTokenStopIndex() { return 0; }
1493447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public void setTokenStopIndex(int index) { }
1503447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public Tree dupNode() {	return null; }
1513447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public int getType() { return type; }
1523447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public String getText() { return text; }
1533447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		public String toString() {
1543447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			return "fix this";
1553447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
1563447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	}
1573447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
1583447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	public RemoteDebugEventSocketListener(DebugEventListener listener,
1593447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein										  String machine,
1603447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein										  int port) throws IOException
1613447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	{
1623447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		this.listener = listener;
1633447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		this.machine = machine;
1643447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		this.port = port;
1653447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
1663447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein        if( !openConnection() ) {
1673447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein            throw new ConnectException();
1683447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein        }
1693447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	}
1703447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
1713447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	protected void eventHandler() {
1723447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		try {
1733447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			handshake();
1743447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			event = in.readLine();
1753447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			while ( event!=null ) {
1763447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				dispatch(event);
1773447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				ack();
1783447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				event = in.readLine();
1793447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			}
1803447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
1813447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		catch (Exception e) {
1823447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			System.err.println(e);
1833447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			e.printStackTrace(System.err);
1843447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
1853447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		finally {
1863447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein            closeConnection();
1873447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
1883447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	}
1893447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
1903447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein    protected boolean openConnection() {
1913447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein        boolean success = false;
1923447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein        try {
1933447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein            channel = new Socket(machine, port);
1943447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein            channel.setTcpNoDelay(true);
1953447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			OutputStream os = channel.getOutputStream();
1963447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			OutputStreamWriter osw = new OutputStreamWriter(os, "UTF8");
1973447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			out = new PrintWriter(new BufferedWriter(osw));
1983447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			InputStream is = channel.getInputStream();
1993447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			InputStreamReader isr = new InputStreamReader(is, "UTF8");
2003447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			in = new BufferedReader(isr);
2013447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein            success = true;
2023447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein        } catch(Exception e) {
2033447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein            System.err.println(e);
2043447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein        }
2053447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein        return success;
2063447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein    }
2073447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
2083447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein    protected void closeConnection() {
2093447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein        try {
2103447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein            in.close(); in = null;
2113447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein            out.close(); out = null;
2123447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein            channel.close(); channel=null;
2133447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein        }
2143447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein        catch (Exception e) {
2153447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein            System.err.println(e);
2163447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein            e.printStackTrace(System.err);
2173447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein        }
2183447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein        finally {
2193447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein            if ( in!=null ) {
2203447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein                try {in.close();} catch (IOException ioe) {
2213447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein                    System.err.println(ioe);
2223447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein                }
2233447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein            }
2243447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein            if ( out!=null ) {
2253447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein                out.close();
2263447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein            }
2273447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein            if ( channel!=null ) {
2283447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein                try {channel.close();} catch (IOException ioe) {
2293447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein                    System.err.println(ioe);
2303447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein                }
2313447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein            }
2323447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein        }
2333447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
2343447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein    }
2353447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
2363447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	protected void handshake() throws IOException {
2373447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		String antlrLine = in.readLine();
2383447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		String[] antlrElements = getEventElements(antlrLine);
2393447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		version = antlrElements[1];
2403447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		String grammarLine = in.readLine();
2413447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		String[] grammarElements = getEventElements(grammarLine);
2423447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		grammarFileName = grammarElements[1];
2433447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		ack();
2443447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		listener.commence(); // inform listener after handshake
2453447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	}
2463447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
2473447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	protected void ack() {
2483447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein        out.println("ack");
2493447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		out.flush();
2503447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	}
2513447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
2523447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	protected void dispatch(String line) {
2533447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein        //System.out.println("event: "+line);
2543447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein        String[] elements = getEventElements(line);
2553447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		if ( elements==null || elements[0]==null ) {
2563447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			System.err.println("unknown debug event: "+line);
2573447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			return;
2583447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
2593447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		if ( elements[0].equals("enterRule") ) {
2603447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.enterRule(elements[1], elements[2]);
2613447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
2623447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("exitRule") ) {
2633447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.exitRule(elements[1], elements[2]);
2643447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
2653447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("enterAlt") ) {
2663447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.enterAlt(Integer.parseInt(elements[1]));
2673447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
2683447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("enterSubRule") ) {
2693447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.enterSubRule(Integer.parseInt(elements[1]));
2703447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
2713447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("exitSubRule") ) {
2723447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.exitSubRule(Integer.parseInt(elements[1]));
2733447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
2743447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("enterDecision") ) {
2753447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.enterDecision(Integer.parseInt(elements[1]), elements[2].equals("true"));
2763447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
2773447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("exitDecision") ) {
2783447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.exitDecision(Integer.parseInt(elements[1]));
2793447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
2803447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("location") ) {
2813447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.location(Integer.parseInt(elements[1]),
2823447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein							  Integer.parseInt(elements[2]));
2833447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
2843447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("consumeToken") ) {
2853447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			ProxyToken t = deserializeToken(elements, 1);
2863447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			if ( t.getTokenIndex() == previousTokenIndex ) {
2873447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				tokenIndexesInvalid = true;
2883447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			}
2893447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			previousTokenIndex = t.getTokenIndex();
2903447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.consumeToken(t);
2913447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
2923447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("consumeHiddenToken") ) {
2933447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			ProxyToken t = deserializeToken(elements, 1);
2943447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			if ( t.getTokenIndex() == previousTokenIndex ) {
2953447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				tokenIndexesInvalid = true;
2963447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			}
2973447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			previousTokenIndex = t.getTokenIndex();
2983447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.consumeHiddenToken(t);
2993447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
3003447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("LT") ) {
3013447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			Token t = deserializeToken(elements, 2);
3023447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.LT(Integer.parseInt(elements[1]), t);
3033447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
3043447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("mark") ) {
3053447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.mark(Integer.parseInt(elements[1]));
3063447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
3073447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("rewind") ) {
3083447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			if ( elements[1]!=null ) {
3093447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				listener.rewind(Integer.parseInt(elements[1]));
3103447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			}
3113447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			else {
3123447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				listener.rewind();
3133447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			}
3143447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
3153447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("beginBacktrack") ) {
3163447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.beginBacktrack(Integer.parseInt(elements[1]));
3173447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
3183447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("endBacktrack") ) {
3193447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			int level = Integer.parseInt(elements[1]);
3203447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			int successI = Integer.parseInt(elements[2]);
3213447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.endBacktrack(level, successI==DebugEventListener.TRUE);
3223447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
3233447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("exception") ) {
3243447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			String excName = elements[1];
3253447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			String indexS = elements[2];
3263447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			String lineS = elements[3];
3273447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			String posS = elements[4];
3283447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			Class excClass = null;
3293447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			try {
3303447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				excClass = Class.forName(excName);
3313447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				RecognitionException e =
3323447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein					(RecognitionException)excClass.newInstance();
3333447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				e.index = Integer.parseInt(indexS);
3343447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				e.line = Integer.parseInt(lineS);
3353447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				e.charPositionInLine = Integer.parseInt(posS);
3363447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				listener.recognitionException(e);
3373447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			}
3383447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			catch (ClassNotFoundException cnfe) {
3393447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				System.err.println("can't find class "+cnfe);
3403447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				cnfe.printStackTrace(System.err);
3413447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			}
3423447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			catch (InstantiationException ie) {
3433447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				System.err.println("can't instantiate class "+ie);
3443447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				ie.printStackTrace(System.err);
3453447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			}
3463447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			catch (IllegalAccessException iae) {
3473447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				System.err.println("can't access class "+iae);
3483447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				iae.printStackTrace(System.err);
3493447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			}
3503447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
3513447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("beginResync") ) {
3523447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.beginResync();
3533447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
3543447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("endResync") ) {
3553447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.endResync();
3563447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
3573447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("terminate") ) {
3583447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.terminate();
3593447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
3603447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("semanticPredicate") ) {
3613447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			Boolean result = Boolean.valueOf(elements[1]);
3623447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			String predicateText = elements[2];
3633447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			predicateText = unEscapeNewlines(predicateText);
3643447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.semanticPredicate(result.booleanValue(),
3653447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein									   predicateText);
3663447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
3673447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("consumeNode") ) {
3683447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			ProxyTree node = deserializeNode(elements, 1);
3693447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.consumeNode(node);
3703447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
3713447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("LN") ) {
3723447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			int i = Integer.parseInt(elements[1]);
3733447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			ProxyTree node = deserializeNode(elements, 2);
3743447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.LT(i, node);
3753447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
3763447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("createNodeFromTokenElements") ) {
3773447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			int ID = Integer.parseInt(elements[1]);
3783447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			int type = Integer.parseInt(elements[2]);
3793447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			String text = elements[3];
3803447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			text = unEscapeNewlines(text);
3813447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			ProxyTree node = new ProxyTree(ID, type, -1, -1, -1, text);
3823447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.createNode(node);
3833447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
3843447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("createNode") ) {
3853447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			int ID = Integer.parseInt(elements[1]);
3863447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			int tokenIndex = Integer.parseInt(elements[2]);
3873447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			// create dummy node/token filled with ID, tokenIndex
3883447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			ProxyTree node = new ProxyTree(ID);
3893447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			ProxyToken token = new ProxyToken(tokenIndex);
3903447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.createNode(node, token);
3913447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
3923447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("nilNode") ) {
3933447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			int ID = Integer.parseInt(elements[1]);
3943447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			ProxyTree node = new ProxyTree(ID);
3953447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.nilNode(node);
3963447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
3973447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("errorNode") ) {
3983447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			// TODO: do we need a special tree here?
3993447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			int ID = Integer.parseInt(elements[1]);
4003447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			int type = Integer.parseInt(elements[2]);
4013447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			String text = elements[3];
4023447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			text = unEscapeNewlines(text);
4033447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			ProxyTree node = new ProxyTree(ID, type, -1, -1, -1, text);
4043447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.errorNode(node);
4053447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
4063447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("becomeRoot") ) {
4073447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			int newRootID = Integer.parseInt(elements[1]);
4083447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			int oldRootID = Integer.parseInt(elements[2]);
4093447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			ProxyTree newRoot = new ProxyTree(newRootID);
4103447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			ProxyTree oldRoot = new ProxyTree(oldRootID);
4113447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.becomeRoot(newRoot, oldRoot);
4123447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
4133447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("addChild") ) {
4143447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			int rootID = Integer.parseInt(elements[1]);
4153447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			int childID = Integer.parseInt(elements[2]);
4163447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			ProxyTree root = new ProxyTree(rootID);
4173447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			ProxyTree child = new ProxyTree(childID);
4183447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.addChild(root, child);
4193447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
4203447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else if ( elements[0].equals("setTokenBoundaries") ) {
4213447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			int ID = Integer.parseInt(elements[1]);
4223447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			ProxyTree node = new ProxyTree(ID);
4233447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			listener.setTokenBoundaries(
4243447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				node,
4253447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				Integer.parseInt(elements[2]),
4263447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				Integer.parseInt(elements[3]));
4273447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
4283447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		else {
4293447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			System.err.println("unknown debug event: "+line);
4303447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
4313447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	}
4323447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
4333447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	protected ProxyTree deserializeNode(String[] elements, int offset) {
4343447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		int ID = Integer.parseInt(elements[offset+0]);
4353447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		int type = Integer.parseInt(elements[offset+1]);
4363447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		int tokenLine = Integer.parseInt(elements[offset+2]);
4373447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		int charPositionInLine = Integer.parseInt(elements[offset+3]);
4383447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		int tokenIndex = Integer.parseInt(elements[offset+4]);
4393447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		String text = elements[offset+5];
4403447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		text = unEscapeNewlines(text);
4413447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		return new ProxyTree(ID, type, tokenLine, charPositionInLine, tokenIndex, text);
4423447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	}
4433447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
4443447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	protected ProxyToken deserializeToken(String[] elements,
4453447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein										  int offset)
4463447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	{
4473447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		String indexS = elements[offset+0];
4483447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		String typeS = elements[offset+1];
4493447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		String channelS = elements[offset+2];
4503447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		String lineS = elements[offset+3];
4513447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		String posS = elements[offset+4];
4523447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		String text = elements[offset+5];
4533447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		text = unEscapeNewlines(text);
4543447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		int index = Integer.parseInt(indexS);
4553447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		ProxyToken t =
4563447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			new ProxyToken(index,
4573447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein						   Integer.parseInt(typeS),
4583447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein						   Integer.parseInt(channelS),
4593447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein						   Integer.parseInt(lineS),
4603447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein						   Integer.parseInt(posS),
4613447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein						   text);
4623447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		return t;
4633447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	}
4643447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
4653447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	/** Create a thread to listen to the remote running recognizer */
4663447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	public void start() {
4673447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		Thread t = new Thread(this);
4683447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		t.start();
4693447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	}
4703447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
4713447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	public void run() {
4723447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		eventHandler();
4733447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	}
4743447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
4753447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	// M i s c
4763447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
4773447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	public String[] getEventElements(String event) {
4783447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		if ( event==null ) {
4793447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			return null;
4803447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
4813447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		String[] elements = new String[MAX_EVENT_ELEMENTS];
4823447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		String str = null; // a string element if present (must be last)
4833447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		try {
4843447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			int firstQuoteIndex = event.indexOf('"');
4853447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			if ( firstQuoteIndex>=0 ) {
4863447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				// treat specially; has a string argument like "a comment\n
4873447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				// Note that the string is terminated by \n not end quote.
4883447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				// Easier to parse that way.
4893447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				String eventWithoutString = event.substring(0,firstQuoteIndex);
4903447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				str = event.substring(firstQuoteIndex+1,event.length());
4913447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				event = eventWithoutString;
4923447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			}
4933447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			StringTokenizer st = new StringTokenizer(event, "\t", false);
4943447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			int i = 0;
4953447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			while ( st.hasMoreTokens() ) {
4963447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				if ( i>=MAX_EVENT_ELEMENTS ) {
4973447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein					// ErrorManager.internalError("event has more than "+MAX_EVENT_ELEMENTS+" args: "+event);
4983447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein					return elements;
4993447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				}
5003447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				elements[i] = st.nextToken();
5013447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				i++;
5023447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			}
5033447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			if ( str!=null ) {
5043447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein				elements[i] = str;
5053447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			}
5063447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
5073447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		catch (Exception e) {
5083447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein			e.printStackTrace(System.err);
5093447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		}
5103447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		return elements;
5113447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	}
5123447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
5133447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	protected String unEscapeNewlines(String txt) {
5143447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		// this unescape is slow but easy to understand
5153447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		txt = txt.replaceAll("%0A","\n");  // unescape \n
5163447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		txt = txt.replaceAll("%0D","\r");  // unescape \r
5173447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		txt = txt.replaceAll("%25","%");   // undo escaped escape chars
5183447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		return txt;
5193447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	}
5203447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
5213447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	public boolean tokenIndexesAreInvalid() {
5223447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		return false;
5233447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein		//return tokenIndexesInvalid;
5243447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein	}
5253447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
5263447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein}
5273447a5916aa62f44de24cc441fc9987116ddff52Andrew Sapperstein
528