• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Tree
34 {
35     using Antlr.Runtime.Misc;
36 
37     using Console = System.Console;
38 
39     public class TreeRewriter : TreeParser
40     {
41         protected bool showTransformations;
42 
43         protected ITokenStream originalTokenStream;
44         protected ITreeAdaptor originalAdaptor;
45 
46         Func<IAstRuleReturnScope> topdown_func;
47         Func<IAstRuleReturnScope> bottomup_func;
48 
TreeRewriter( ITreeNodeStream input )49         public TreeRewriter( ITreeNodeStream input )
50             : this( input, new RecognizerSharedState() )
51         {
52         }
TreeRewriter( ITreeNodeStream input, RecognizerSharedState state )53         public TreeRewriter( ITreeNodeStream input, RecognizerSharedState state )
54             : base( input, state )
55         {
56             originalAdaptor = input.TreeAdaptor;
57             originalTokenStream = input.TokenStream;
58             topdown_func = () => Topdown();
59             bottomup_func = () => Bottomup();
60         }
61 
ApplyOnce( object t, Func<IAstRuleReturnScope> whichRule )62         public virtual object ApplyOnce( object t, Func<IAstRuleReturnScope> whichRule )
63         {
64             if ( t == null )
65                 return null;
66 
67             try
68             {
69                 // share TreeParser object but not parsing-related state
70                 SetState(new RecognizerSharedState());
71                 SetTreeNodeStream(new CommonTreeNodeStream(originalAdaptor, t));
72                 ( (CommonTreeNodeStream)input ).TokenStream = originalTokenStream;
73                 BacktrackingLevel = 1;
74                 IAstRuleReturnScope r = whichRule();
75                 BacktrackingLevel = 0;
76                 if ( Failed )
77                     return t;
78 
79                 if (showTransformations && r != null && !t.Equals(r.Tree) && r.Tree != null)
80                     ReportTransformation(t, r.Tree);
81 
82                 if ( r != null && r.Tree != null )
83                     return r.Tree;
84                 else
85                     return t;
86             }
87             catch ( RecognitionException )
88             {
89             }
90 
91             return t;
92         }
93 
ApplyRepeatedly( object t, Func<IAstRuleReturnScope> whichRule )94         public virtual object ApplyRepeatedly( object t, Func<IAstRuleReturnScope> whichRule )
95         {
96             bool treeChanged = true;
97             while ( treeChanged )
98             {
99                 object u = ApplyOnce( t, whichRule );
100                 treeChanged = !t.Equals( u );
101                 t = u;
102             }
103             return t;
104         }
105 
Downup( object t )106         public virtual object Downup( object t )
107         {
108             return Downup( t, false );
109         }
110 
Downup( object t, bool showTransformations )111         public virtual object Downup( object t, bool showTransformations )
112         {
113             this.showTransformations = showTransformations;
114             TreeVisitor v = new TreeVisitor( new CommonTreeAdaptor() );
115             t = v.Visit( t, ( o ) => ApplyOnce( o, topdown_func ), ( o ) => ApplyRepeatedly( o, bottomup_func ) );
116             return t;
117         }
118 
119         // methods the downup strategy uses to do the up and down rules.
120         // to override, just define tree grammar rule topdown and turn on
121         // filter=true.
Topdown()122         protected virtual IAstRuleReturnScope Topdown()
123         {
124             return null;
125         }
126 
Bottomup()127         protected virtual IAstRuleReturnScope Bottomup()
128         {
129             return null;
130         }
131 
132         /** Override this if you need transformation tracing to go somewhere
133          *  other than stdout or if you're not using ITree-derived trees.
134          */
ReportTransformation(object oldTree, object newTree)135         protected virtual void ReportTransformation(object oldTree, object newTree)
136         {
137             ITree old = oldTree as ITree;
138             ITree @new = newTree as ITree;
139             string oldMessage = old != null ? old.ToStringTree() : "??";
140             string newMessage = @new != null ? @new.ToStringTree() : "??";
141             Console.WriteLine("{0} -> {1}", oldMessage, newMessage);
142         }
143     }
144 }
145