1 /*
2  * [The "BSD licence"]
3  * Copyright (c) 2005-2008 Terence Parr
4  * All rights reserved.
5  *
6  * Conversion to C#:
7  * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 namespace Antlr.Runtime.Debug
34 {
35     using System;
36     using Antlr.Runtime.JavaExtensions;
37 
38     using IOException = System.IO.IOException;
39     using ITreeAdaptor = Antlr.Runtime.Tree.ITreeAdaptor;
40     using Socket = System.Net.Sockets.Socket;
41     using StringBuilder = System.Text.StringBuilder;
42     using TcpListener = System.Net.Sockets.TcpListener;
43 
44     /** <summary>
45      *  A proxy debug event listener that forwards events over a socket to
46      *  a debugger (or any other listener) using a simple text-based protocol;
47      *  one event per line.  ANTLRWorks listens on server socket with a
48      *  RemoteDebugEventSocketListener instance.  These two objects must therefore
49      *  be kept in sync.  New events must be handled on both sides of socket.
50      *  </summary>
51      */
52     public class DebugEventSocketProxy : BlankDebugEventListener
53     {
54         public const int DefaultDebuggerPort = 49100;
55         protected int port = DefaultDebuggerPort;
56         protected TcpListener serverSocket;
57         protected Socket socket;
58         protected string grammarFileName;
59         //protected PrintWriter @out;
60         //protected BufferedReader @in;
61 
62         /** <summary>Who am i debugging?</summary> */
63         protected BaseRecognizer recognizer;
64 
65         /** <summary>
66          *  Almost certainly the recognizer will have adaptor set, but
67          *  we don't know how to cast it (Parser or TreeParser) to get
68          *  the adaptor field.  Must be set with a constructor. :(
69          *  </summary>
70          */
71         protected ITreeAdaptor adaptor;
72 
DebugEventSocketProxy( BaseRecognizer recognizer, ITreeAdaptor adaptor )73         public DebugEventSocketProxy( BaseRecognizer recognizer, ITreeAdaptor adaptor ) :
74             this( recognizer, DefaultDebuggerPort, adaptor )
75         {
76         }
77 
DebugEventSocketProxy( BaseRecognizer recognizer, int port, ITreeAdaptor adaptor )78         public DebugEventSocketProxy( BaseRecognizer recognizer, int port, ITreeAdaptor adaptor )
79         {
80             this.grammarFileName = recognizer.GrammarFileName;
81             this.adaptor = adaptor;
82             this.port = port;
83         }
84 
85         #region Properties
86         public virtual ITreeAdaptor TreeAdaptor
87         {
88             get
89             {
90                 return adaptor;
91             }
92             set
93             {
94                 adaptor = value;
95             }
96         }
97         #endregion
98 
Handshake()99         public virtual void Handshake()
100         {
101             if ( serverSocket == null )
102             {
103                 System.Net.IPHostEntry hostInfo = System.Net.Dns.GetHostEntry( "localhost" );
104                 System.Net.IPAddress ipAddress = hostInfo.AddressList[0];
105                 serverSocket = new TcpListener( ipAddress, port );
106                 socket = serverSocket.AcceptSocket();
107                 socket.NoDelay = true;
108 
109                 System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
110                 socket.Send( encoding.GetBytes( "ANTLR " + DebugEventListenerConstants.ProtocolVersion + "\n" ) );
111                 socket.Send( encoding.GetBytes( "grammar \"" + grammarFileName + "\n" ) );
112                 Ack();
113 
114                 //serverSocket = new ServerSocket( port );
115                 //socket = serverSocket.accept();
116                 //socket.setTcpNoDelay( true );
117                 //OutputStream os = socket.getOutputStream();
118                 //OutputStreamWriter osw = new OutputStreamWriter( os, "UTF8" );
119                 //@out = new PrintWriter( new BufferedWriter( osw ) );
120                 //InputStream @is = socket.getInputStream();
121                 //InputStreamReader isr = new InputStreamReader( @is, "UTF8" );
122                 //@in = new BufferedReader( isr );
123                 //@out.println( "ANTLR " + DebugEventListenerConstants.PROTOCOL_VERSION );
124                 //@out.println( "grammar \"" + grammarFileName );
125                 //@out.flush();
126                 //ack();
127             }
128         }
129 
Commence()130         public override void Commence()
131         {
132             // don't bother sending event; listener will trigger upon connection
133         }
134 
Terminate()135         public override void Terminate()
136         {
137             Transmit( "terminate" );
138             //@out.close();
139             try
140             {
141                 socket.Close();
142             }
143             catch ( IOException ioe )
144             {
145                 ExceptionExtensions.PrintStackTrace( ioe, Console.Error );
146             }
147         }
148 
Ack()149         protected virtual void Ack()
150         {
151             try
152             {
153                 throw new NotImplementedException();
154                 //@in.readLine();
155             }
156             catch ( IOException ioe )
157             {
158                 ExceptionExtensions.PrintStackTrace( ioe, Console.Error );
159             }
160         }
161 
Transmit( string @event )162         protected virtual void Transmit( string @event )
163         {
164             socket.Send( new System.Text.UTF8Encoding().GetBytes( @event + "\n" ) );
165             //@out.println( @event );
166             //@out.flush();
167             Ack();
168         }
169 
EnterRule( string grammarFileName, string ruleName )170         public override void EnterRule( string grammarFileName, string ruleName )
171         {
172             Transmit( "enterRule\t" + grammarFileName + "\t" + ruleName );
173         }
174 
EnterAlt( int alt )175         public override void EnterAlt( int alt )
176         {
177             Transmit( "enterAlt\t" + alt );
178         }
179 
ExitRule( string grammarFileName, string ruleName )180         public override void ExitRule( string grammarFileName, string ruleName )
181         {
182             Transmit( "exitRule\t" + grammarFileName + "\t" + ruleName );
183         }
184 
EnterSubRule( int decisionNumber )185         public override void EnterSubRule( int decisionNumber )
186         {
187             Transmit( "enterSubRule\t" + decisionNumber );
188         }
189 
ExitSubRule( int decisionNumber )190         public override void ExitSubRule( int decisionNumber )
191         {
192             Transmit( "exitSubRule\t" + decisionNumber );
193         }
194 
EnterDecision(int decisionNumber, bool couldBacktrack)195         public override void EnterDecision(int decisionNumber, bool couldBacktrack)
196         {
197             Transmit( "enterDecision\t" + decisionNumber );
198         }
199 
ExitDecision( int decisionNumber )200         public override void ExitDecision( int decisionNumber )
201         {
202             Transmit( "exitDecision\t" + decisionNumber );
203         }
204 
ConsumeToken( IToken t )205         public override void ConsumeToken( IToken t )
206         {
207             string buf = SerializeToken( t );
208             Transmit( "consumeToken\t" + buf );
209         }
210 
ConsumeHiddenToken( IToken t )211         public override void ConsumeHiddenToken( IToken t )
212         {
213             string buf = SerializeToken( t );
214             Transmit( "consumeHiddenToken\t" + buf );
215         }
216 
LT( int i, IToken t )217         public override void LT( int i, IToken t )
218         {
219             if ( t != null )
220                 Transmit( "LT\t" + i + "\t" + SerializeToken( t ) );
221         }
222 
Mark( int i )223         public override void Mark( int i )
224         {
225             Transmit( "mark\t" + i );
226         }
227 
Rewind( int i )228         public override void Rewind( int i )
229         {
230             Transmit( "rewind\t" + i );
231         }
232 
Rewind()233         public override void Rewind()
234         {
235             Transmit( "rewind" );
236         }
237 
BeginBacktrack( int level )238         public override void BeginBacktrack( int level )
239         {
240             Transmit( "beginBacktrack\t" + level );
241         }
242 
EndBacktrack( int level, bool successful )243         public override void EndBacktrack( int level, bool successful )
244         {
245             Transmit( "endBacktrack\t" + level + "\t" + ( successful ? DebugEventListenerConstants.True : DebugEventListenerConstants.False ) );
246         }
247 
Location( int line, int pos )248         public override void Location( int line, int pos )
249         {
250             Transmit( "location\t" + line + "\t" + pos );
251         }
252 
RecognitionException( RecognitionException e )253         public override void RecognitionException( RecognitionException e )
254         {
255             StringBuilder buf = new StringBuilder( 50 );
256             buf.Append( "exception\t" );
257             buf.Append( e.GetType().Name );
258             // dump only the data common to all exceptions for now
259             buf.Append( "\t" );
260             buf.Append( e.Index );
261             buf.Append( "\t" );
262             buf.Append( e.Line );
263             buf.Append( "\t" );
264             buf.Append( e.CharPositionInLine );
265             Transmit( buf.ToString() );
266         }
267 
BeginResync()268         public override void BeginResync()
269         {
270             Transmit( "beginResync" );
271         }
272 
EndResync()273         public override void EndResync()
274         {
275             Transmit( "endResync" );
276         }
277 
SemanticPredicate( bool result, string predicate )278         public override void SemanticPredicate( bool result, string predicate )
279         {
280             StringBuilder buf = new StringBuilder( 50 );
281             buf.Append( "semanticPredicate\t" );
282             buf.Append( result );
283             SerializeText( buf, predicate );
284             Transmit( buf.ToString() );
285         }
286 
287         #region AST Parsing Events
288 
ConsumeNode( object t )289         public override void ConsumeNode( object t )
290         {
291             StringBuilder buf = new StringBuilder( 50 );
292             buf.Append( "consumeNode" );
293             SerializeNode( buf, t );
294             Transmit( buf.ToString() );
295         }
296 
LT( int i, object t )297         public override void LT( int i, object t )
298         {
299             int ID = adaptor.GetUniqueID( t );
300             string text = adaptor.GetText( t );
301             int type = adaptor.GetType( t );
302             StringBuilder buf = new StringBuilder( 50 );
303             buf.Append( "LN\t" ); // lookahead node; distinguish from LT in protocol
304             buf.Append( i );
305             SerializeNode( buf, t );
306             Transmit( buf.ToString() );
307         }
308 
SerializeNode( StringBuilder buf, object t )309         protected virtual void SerializeNode( StringBuilder buf, object t )
310         {
311             int ID = adaptor.GetUniqueID( t );
312             string text = adaptor.GetText( t );
313             int type = adaptor.GetType( t );
314             buf.Append( "\t" );
315             buf.Append( ID );
316             buf.Append( "\t" );
317             buf.Append( type );
318             IToken token = adaptor.GetToken( t );
319             int line = -1;
320             int pos = -1;
321             if ( token != null )
322             {
323                 line = token.Line;
324                 pos = token.CharPositionInLine;
325             }
326             buf.Append( "\t" );
327             buf.Append( line );
328             buf.Append( "\t" );
329             buf.Append( pos );
330             int tokenIndex = adaptor.GetTokenStartIndex( t );
331             buf.Append( "\t" );
332             buf.Append( tokenIndex );
333             SerializeText( buf, text );
334         }
335 
336         #endregion
337 
338 
339         #region AST Events
340 
NilNode( object t )341         public override void NilNode( object t )
342         {
343             int ID = adaptor.GetUniqueID( t );
344             Transmit( "nilNode\t" + ID );
345         }
346 
ErrorNode( object t )347         public override void ErrorNode( object t )
348         {
349             int ID = adaptor.GetUniqueID( t );
350             string text = t.ToString();
351             StringBuilder buf = new StringBuilder( 50 );
352             buf.Append( "errorNode\t" );
353             buf.Append( ID );
354             buf.Append( "\t" );
355             buf.Append( TokenTypes.Invalid );
356             SerializeText( buf, text );
357             Transmit( buf.ToString() );
358         }
359 
CreateNode( object t )360         public override void CreateNode( object t )
361         {
362             int ID = adaptor.GetUniqueID( t );
363             string text = adaptor.GetText( t );
364             int type = adaptor.GetType( t );
365             StringBuilder buf = new StringBuilder( 50 );
366             buf.Append( "createNodeFromTokenElements\t" );
367             buf.Append( ID );
368             buf.Append( "\t" );
369             buf.Append( type );
370             SerializeText( buf, text );
371             Transmit( buf.ToString() );
372         }
373 
CreateNode( object node, IToken token )374         public override void CreateNode( object node, IToken token )
375         {
376             int ID = adaptor.GetUniqueID( node );
377             int tokenIndex = token.TokenIndex;
378             Transmit( "createNode\t" + ID + "\t" + tokenIndex );
379         }
380 
BecomeRoot( object newRoot, object oldRoot )381         public override void BecomeRoot( object newRoot, object oldRoot )
382         {
383             int newRootID = adaptor.GetUniqueID( newRoot );
384             int oldRootID = adaptor.GetUniqueID( oldRoot );
385             Transmit( "becomeRoot\t" + newRootID + "\t" + oldRootID );
386         }
387 
AddChild( object root, object child )388         public override void AddChild( object root, object child )
389         {
390             int rootID = adaptor.GetUniqueID( root );
391             int childID = adaptor.GetUniqueID( child );
392             Transmit( "addChild\t" + rootID + "\t" + childID );
393         }
394 
SetTokenBoundaries( object t, int tokenStartIndex, int tokenStopIndex )395         public override void SetTokenBoundaries( object t, int tokenStartIndex, int tokenStopIndex )
396         {
397             int ID = adaptor.GetUniqueID( t );
398             Transmit( "setTokenBoundaries\t" + ID + "\t" + tokenStartIndex + "\t" + tokenStopIndex );
399         }
400 
401         #endregion
402 
403 
404         #region Support
405 
SerializeToken( IToken t )406         protected virtual string SerializeToken( IToken t )
407         {
408             StringBuilder buf = new StringBuilder( 50 );
409             buf.Append( t.TokenIndex );
410             buf.Append( '\t' );
411             buf.Append( t.Type );
412             buf.Append( '\t' );
413             buf.Append( t.Channel );
414             buf.Append( '\t' );
415             buf.Append( t.Line );
416             buf.Append( '\t' );
417             buf.Append( t.CharPositionInLine );
418             SerializeText( buf, t.Text );
419             return buf.ToString();
420         }
421 
SerializeText( StringBuilder buf, string text )422         protected virtual void SerializeText( StringBuilder buf, string text )
423         {
424             buf.Append( "\t\"" );
425             if ( text == null )
426             {
427                 text = "";
428             }
429             // escape \n and \r all text for token appears to exist on one line
430             // this escape is slow but easy to understand
431             text = EscapeNewlines( text );
432             buf.Append( text );
433         }
434 
EscapeNewlines( string txt )435         protected virtual string EscapeNewlines( string txt )
436         {
437             txt = txt.Replace( "%", "%25" );   // escape all escape char ;)
438             txt = txt.Replace( "\n", "%0A" );  // escape \n
439             txt = txt.Replace( "\r", "%0D" );  // escape \r
440             return txt;
441         }
442 
443         #endregion
444     }
445 }
446