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.Collections.Generic; 36 using ParseTree = Antlr.Runtime.Tree.ParseTree; 37 38 /** <summary> 39 * This parser listener tracks rule entry/exit and token matches 40 * to build a simple parse tree using ParseTree nodes. 41 * </summary> 42 */ 43 public class ParseTreeBuilder : BlankDebugEventListener 44 { 45 public const string EPSILON_PAYLOAD = "<epsilon>"; 46 47 Stack<ParseTree> callStack = new Stack<ParseTree>(); 48 List<IToken> hiddenTokens = new List<IToken>(); 49 int backtracking = 0; 50 ParseTreeBuilder( string grammarName )51 public ParseTreeBuilder( string grammarName ) 52 { 53 ParseTree root = Create( "<grammar " + grammarName + ">" ); 54 callStack.Push( root ); 55 } 56 57 public virtual ParseTree Tree 58 { 59 get 60 { 61 ParseTree[] stack = callStack.ToArray(); 62 return stack[stack.Length - 1]; 63 } 64 } 65 66 /** <summary> 67 * What kind of node to create. You might want to override 68 * so I factored out creation here. 69 * </summary> 70 */ Create( object payload )71 public virtual ParseTree Create( object payload ) 72 { 73 return new ParseTree( payload ); 74 } 75 EpsilonNode()76 public virtual ParseTree EpsilonNode() 77 { 78 return Create( EPSILON_PAYLOAD ); 79 } 80 81 /** <summary>Backtracking or cyclic DFA, don't want to add nodes to tree</summary> */ EnterDecision( int d, bool couldBacktrack )82 public override void EnterDecision( int d, bool couldBacktrack ) 83 { 84 backtracking++; 85 } ExitDecision( int i )86 public override void ExitDecision( int i ) 87 { 88 backtracking--; 89 } 90 EnterRule( string filename, string ruleName )91 public override void EnterRule( string filename, string ruleName ) 92 { 93 if ( backtracking > 0 ) 94 return; 95 ParseTree parentRuleNode = callStack.Peek(); 96 ParseTree ruleNode = Create( ruleName ); 97 parentRuleNode.AddChild( ruleNode ); 98 callStack.Push( ruleNode ); 99 } 100 ExitRule( string filename, string ruleName )101 public override void ExitRule( string filename, string ruleName ) 102 { 103 if ( backtracking > 0 ) 104 return; 105 ParseTree ruleNode = callStack.Peek(); 106 if ( ruleNode.ChildCount == 0 ) 107 { 108 ruleNode.AddChild( EpsilonNode() ); 109 } 110 callStack.Pop(); 111 } 112 ConsumeToken( IToken token )113 public override void ConsumeToken( IToken token ) 114 { 115 if ( backtracking > 0 ) 116 return; 117 ParseTree ruleNode = callStack.Peek(); 118 ParseTree elementNode = Create( token ); 119 elementNode.hiddenTokens = this.hiddenTokens; 120 this.hiddenTokens = new List<IToken>(); 121 ruleNode.AddChild( elementNode ); 122 } 123 ConsumeHiddenToken( IToken token )124 public override void ConsumeHiddenToken( IToken token ) 125 { 126 if ( backtracking > 0 ) 127 return; 128 hiddenTokens.Add( token ); 129 } 130 RecognitionException( RecognitionException e )131 public override void RecognitionException( RecognitionException e ) 132 { 133 if ( backtracking > 0 ) 134 return; 135 ParseTree ruleNode = callStack.Peek(); 136 ParseTree errorNode = Create( e ); 137 ruleNode.AddChild( errorNode ); 138 } 139 } 140 } 141