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