aboutsummaryrefslogtreecommitdiff
path: root/antlr-3.4/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/RemoteDebugEventSocketListener.cs
diff options
context:
space:
mode:
Diffstat (limited to 'antlr-3.4/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/RemoteDebugEventSocketListener.cs')
-rw-r--r--antlr-3.4/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/RemoteDebugEventSocketListener.cs744
1 files changed, 744 insertions, 0 deletions
diff --git a/antlr-3.4/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/RemoteDebugEventSocketListener.cs b/antlr-3.4/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/RemoteDebugEventSocketListener.cs
new file mode 100644
index 0000000..e390065
--- /dev/null
+++ b/antlr-3.4/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/RemoteDebugEventSocketListener.cs
@@ -0,0 +1,744 @@
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2005-2008 Terence Parr
+ * All rights reserved.
+ *
+ * Conversion to C#:
+ * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
+ * 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.
+ */
+
+namespace Antlr.Runtime.Debug
+{
+ using Antlr.Runtime.JavaExtensions;
+
+ using Array = System.Array;
+ using BaseTree = Antlr.Runtime.Tree.BaseTree;
+ using Console = System.Console;
+ using Exception = System.Exception;
+ using IOException = System.IO.IOException;
+ using ITree = Antlr.Runtime.Tree.ITree;
+ using Math = System.Math;
+ using Socket = System.Net.Sockets.Socket;
+ using SocketException = System.Net.Sockets.SocketException;
+ using TextReader = System.IO.TextReader;
+ using TextWriter = System.IO.TextWriter;
+
+ public class RemoteDebugEventSocketListener
+ {
+ const int MAX_EVENT_ELEMENTS = 8;
+ IDebugEventListener listener;
+ string machine;
+ int port;
+ Socket channel = null;
+ TextWriter @out;
+ TextReader @in;
+ string @event;
+ /** <summary>Version of ANTLR (dictates events)</summary> */
+ public string version;
+ public string grammarFileName;
+ /** <summary>
+ * Track the last token index we saw during a consume. If same, then
+ * set a flag that we have a problem.
+ * </summary>
+ */
+ int previousTokenIndex = -1;
+ bool tokenIndexesInvalid = false;
+
+ public class ProxyToken : IToken
+ {
+ 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;
+ }
+
+ #region IToken Members
+ public string Text
+ {
+ get
+ {
+ return text;
+ }
+ set
+ {
+ text = value;
+ }
+ }
+
+ public int Type
+ {
+ get
+ {
+ return type;
+ }
+ set
+ {
+ type = value;
+ }
+ }
+
+ public int Line
+ {
+ get
+ {
+ return line;
+ }
+ set
+ {
+ line = value;
+ }
+ }
+
+ public int CharPositionInLine
+ {
+ get
+ {
+ return charPos;
+ }
+ set
+ {
+ charPos = value;
+ }
+ }
+
+ public int Channel
+ {
+ get
+ {
+ return channel;
+ }
+ set
+ {
+ channel = value;
+ }
+ }
+
+ public int StartIndex
+ {
+ get
+ {
+ return -1;
+ }
+ set
+ {
+ }
+ }
+
+ public int StopIndex
+ {
+ get
+ {
+ return -1;
+ }
+ set
+ {
+ }
+ }
+
+ public int TokenIndex
+ {
+ get
+ {
+ return index;
+ }
+ set
+ {
+ index = value;
+ }
+ }
+
+ public ICharStream InputStream
+ {
+ get
+ {
+ return null;
+ }
+ set
+ {
+ }
+ }
+
+ #endregion
+
+ public override string ToString()
+ {
+ string channelStr = "";
+ if ( channel != TokenChannels.Default )
+ {
+ channelStr = ",channel=" + channel;
+ }
+ return "[" + Text + "/<" + type + ">" + channelStr + "," + line + ":" + CharPositionInLine + ",@" + index + "]";
+ }
+ }
+
+ public class ProxyTree : BaseTree
+ {
+ public int ID;
+ int type;
+ int line = 0;
+ public int charPos = -1;
+ public int tokenIndex = -1;
+ 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;
+ }
+
+ #region Properties
+ public override string Text
+ {
+ get
+ {
+ return text;
+ }
+ set
+ {
+ }
+ }
+ public override int TokenStartIndex
+ {
+ get
+ {
+ return tokenIndex;
+ }
+ set
+ {
+ }
+ }
+ public override int TokenStopIndex
+ {
+ get
+ {
+ return 0;
+ }
+ set
+ {
+ }
+ }
+ public override int Type
+ {
+ get
+ {
+ return type;
+ }
+ set
+ {
+ }
+ }
+ #endregion
+
+ public override ITree DupNode()
+ {
+ return null;
+ }
+
+ public override string ToString()
+ {
+ return "fix this";
+ }
+ }
+
+ public RemoteDebugEventSocketListener( IDebugEventListener listener,
+ string machine,
+ int port )
+ {
+ this.listener = listener;
+ this.machine = machine;
+ this.port = port;
+
+ if ( !OpenConnection() )
+ {
+ throw new SocketException();
+ }
+ }
+
+ protected virtual void EventHandler()
+ {
+ try
+ {
+ Handshake();
+ @event = @in.ReadLine();
+ while ( @event != null )
+ {
+ Dispatch( @event );
+ Ack();
+ @event = @in.ReadLine();
+ }
+ }
+ catch ( Exception e )
+ {
+ Console.Error.WriteLine( e );
+ ExceptionExtensions.PrintStackTrace( e, Console.Error );
+ }
+ finally
+ {
+ CloseConnection();
+ }
+ }
+
+ protected virtual bool OpenConnection()
+ {
+ bool success = false;
+ try
+ {
+ throw new System.NotImplementedException();
+ //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 )
+ {
+ Console.Error.WriteLine( e );
+ }
+ return success;
+ }
+
+ protected virtual void CloseConnection()
+ {
+ try
+ {
+ @in.Close();
+ @in = null;
+ @out.Close();
+ @out = null;
+ channel.Close();
+ channel = null;
+ }
+ catch ( Exception e )
+ {
+ Console.Error.WriteLine( e );
+ ExceptionExtensions.PrintStackTrace( e, Console.Error );
+ }
+ finally
+ {
+ if ( @in != null )
+ {
+ try
+ {
+ @in.Close();
+ }
+ catch ( IOException ioe )
+ {
+ Console.Error.WriteLine( ioe );
+ }
+ }
+ if ( @out != null )
+ {
+ @out.Close();
+ }
+ if ( channel != null )
+ {
+ try
+ {
+ channel.Close();
+ }
+ catch ( IOException ioe )
+ {
+ Console.Error.WriteLine( ioe );
+ }
+ }
+ }
+
+ }
+
+ protected virtual void Handshake()
+ {
+ 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 virtual void Ack()
+ {
+ @out.WriteLine( "ack" );
+ @out.Flush();
+ }
+
+ protected virtual void Dispatch( string line )
+ {
+ //JSystem.@out.println( "event: " + line );
+ string[] elements = GetEventElements( line );
+ if ( elements == null || elements[0] == null )
+ {
+ Console.Error.WriteLine( "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( int.Parse( elements[1] ) );
+ }
+ else if ( elements[0].Equals( "enterSubRule" ) )
+ {
+ listener.EnterSubRule( int.Parse( elements[1] ) );
+ }
+ else if ( elements[0].Equals( "exitSubRule" ) )
+ {
+ listener.ExitSubRule( int.Parse( elements[1] ) );
+ }
+ else if ( elements[0].Equals( "enterDecision" ) )
+ {
+ listener.EnterDecision(int.Parse(elements[1]), elements[2].Equals("true"));
+ }
+ else if ( elements[0].Equals( "exitDecision" ) )
+ {
+ listener.ExitDecision( int.Parse( elements[1] ) );
+ }
+ else if ( elements[0].Equals( "location" ) )
+ {
+ listener.Location( int.Parse( elements[1] ),
+ int.Parse( elements[2] ) );
+ }
+ else if ( elements[0].Equals( "consumeToken" ) )
+ {
+ ProxyToken t = DeserializeToken( elements, 1 );
+ if ( t.TokenIndex == previousTokenIndex )
+ {
+ tokenIndexesInvalid = true;
+ }
+ previousTokenIndex = t.TokenIndex;
+ listener.ConsumeToken( t );
+ }
+ else if ( elements[0].Equals( "consumeHiddenToken" ) )
+ {
+ ProxyToken t = DeserializeToken( elements, 1 );
+ if ( t.TokenIndex == previousTokenIndex )
+ {
+ tokenIndexesInvalid = true;
+ }
+ previousTokenIndex = t.TokenIndex;
+ listener.ConsumeHiddenToken( t );
+ }
+ else if ( elements[0].Equals( "LT" ) )
+ {
+ IToken t = DeserializeToken( elements, 2 );
+ listener.LT( int.Parse( elements[1] ), t );
+ }
+ else if ( elements[0].Equals( "mark" ) )
+ {
+ listener.Mark( int.Parse( elements[1] ) );
+ }
+ else if ( elements[0].Equals( "rewind" ) )
+ {
+ if ( elements[1] != null )
+ {
+ listener.Rewind( int.Parse( elements[1] ) );
+ }
+ else
+ {
+ listener.Rewind();
+ }
+ }
+ else if ( elements[0].Equals( "beginBacktrack" ) )
+ {
+ listener.BeginBacktrack( int.Parse( elements[1] ) );
+ }
+ else if ( elements[0].Equals( "endBacktrack" ) )
+ {
+ int level = int.Parse( elements[1] );
+ int successI = int.Parse( elements[2] );
+ listener.EndBacktrack( level, successI == DebugEventListenerConstants.True );
+ }
+ else if ( elements[0].Equals( "exception" ) )
+ {
+#if true
+ throw new System.NotImplementedException();
+#else
+ 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 = int.Parse( indexS );
+ e.line = int.Parse( lineS );
+ e.charPositionInLine = int.Parse( posS );
+ listener.recognitionException( e );
+ }
+ catch ( ClassNotFoundException cnfe )
+ {
+ Console.Error.println( "can't find class " + cnfe );
+ cnfe.printStackTrace( Console.Error );
+ }
+ catch ( InstantiationException ie )
+ {
+ Console.Error.println( "can't instantiate class " + ie );
+ ie.printStackTrace( Console.Error );
+ }
+ catch ( IllegalAccessException iae )
+ {
+ Console.Error.println( "can't access class " + iae );
+ iae.printStackTrace( Console.Error );
+ }
+#endif
+ }
+ 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" ) )
+ {
+ bool result = bool.Parse( elements[1] );
+ string predicateText = elements[2];
+ predicateText = UnEscapeNewlines( predicateText );
+ listener.SemanticPredicate( result,
+ predicateText );
+ }
+ else if ( elements[0].Equals( "consumeNode" ) )
+ {
+ ProxyTree node = DeserializeNode( elements, 1 );
+ listener.ConsumeNode( node );
+ }
+ else if ( elements[0].Equals( "LN" ) )
+ {
+ int i = int.Parse( elements[1] );
+ ProxyTree node = DeserializeNode( elements, 2 );
+ listener.LT( i, node );
+ }
+ else if ( elements[0].Equals( "createNodeFromTokenElements" ) )
+ {
+ int ID = int.Parse( elements[1] );
+ int type = int.Parse( 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 = int.Parse( elements[1] );
+ int tokenIndex = int.Parse( 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 = int.Parse( 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 = int.Parse( elements[1] );
+ int type = int.Parse( 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 = int.Parse( elements[1] );
+ int oldRootID = int.Parse( elements[2] );
+ ProxyTree newRoot = new ProxyTree( newRootID );
+ ProxyTree oldRoot = new ProxyTree( oldRootID );
+ listener.BecomeRoot( newRoot, oldRoot );
+ }
+ else if ( elements[0].Equals( "addChild" ) )
+ {
+ int rootID = int.Parse( elements[1] );
+ int childID = int.Parse( elements[2] );
+ ProxyTree root = new ProxyTree( rootID );
+ ProxyTree child = new ProxyTree( childID );
+ listener.AddChild( root, child );
+ }
+ else if ( elements[0].Equals( "setTokenBoundaries" ) )
+ {
+ int ID = int.Parse( elements[1] );
+ ProxyTree node = new ProxyTree( ID );
+ listener.SetTokenBoundaries(
+ node,
+ int.Parse( elements[2] ),
+ int.Parse( elements[3] ) );
+ }
+ else
+ {
+ Console.Error.WriteLine( "unknown debug event: " + line );
+ }
+ }
+
+ protected virtual ProxyTree DeserializeNode( string[] elements, int offset )
+ {
+ int ID = int.Parse( elements[offset + 0] );
+ int type = int.Parse( elements[offset + 1] );
+ int tokenLine = int.Parse( elements[offset + 2] );
+ int charPositionInLine = int.Parse( elements[offset + 3] );
+ int tokenIndex = int.Parse( elements[offset + 4] );
+ string text = elements[offset + 5];
+ text = UnEscapeNewlines( text );
+ return new ProxyTree( ID, type, tokenLine, charPositionInLine, tokenIndex, text );
+ }
+
+ protected virtual 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 = int.Parse( indexS );
+ ProxyToken t =
+ new ProxyToken( index,
+ int.Parse( typeS ),
+ int.Parse( channelS ),
+ int.Parse( lineS ),
+ int.Parse( posS ),
+ text );
+ return t;
+ }
+
+ /** <summary>Create a thread to listen to the remote running recognizer</summary> */
+ public virtual void Start()
+ {
+ System.Threading.Thread t = new System.Threading.Thread( Run );
+ t.Start();
+ }
+
+ public virtual void Run()
+ {
+ EventHandler();
+ }
+
+ #region Misc
+
+ public virtual 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 = eventWithoutString;
+ }
+
+ string[] tokens = @event.Split('\t');
+ Array.Copy(tokens, elements, Math.Min(tokens.Length, MAX_EVENT_ELEMENTS));
+ if (tokens.Length >= MAX_EVENT_ELEMENTS)
+ return elements;
+
+ if ( str != null )
+ {
+ elements[tokens.Length] = str;
+ }
+ }
+ catch ( Exception e )
+ {
+ ExceptionExtensions.PrintStackTrace( e, Console.Error );
+ }
+ return elements;
+ }
+
+ protected virtual string UnEscapeNewlines( string txt )
+ {
+ // this unescape is slow but easy to understand
+ txt = txt.Replace( "%0A", "\n" ); // unescape \n
+ txt = txt.Replace( "%0D", "\r" ); // unescape \r
+ txt = txt.Replace( "%25", "%" ); // undo escaped escape chars
+ return txt;
+ }
+
+ public virtual bool TokenIndexesAreInvalid()
+ {
+ return tokenIndexesInvalid;
+ }
+
+ #endregion
+
+ }
+}