Home | History | Annotate | Download | only in Antlr.Runtime.Debug
      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 
     49         public ParseTreeBuilder(string grammarName) {
     50             ParseTree root = Create("<grammar " + grammarName + ">");
     51             callStack.Push(root);
     52         }
     53 
     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          */
     65         public virtual ParseTree Create(object payload) {
     66             return new ParseTree(payload);
     67         }
     68 
     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> */
     74         public override void EnterDecision(int d, bool couldBacktrack) {
     75             backtracking++;
     76         }
     77         public override void ExitDecision(int i) {
     78             backtracking--;
     79         }
     80 
     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 
     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 
    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 
    110         public override void ConsumeHiddenToken(IToken token) {
    111             if (backtracking > 0)
    112                 return;
    113             hiddenTokens.Add(token);
    114         }
    115 
    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