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