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
33namespace Antlr.Runtime.Tree {
34    using Console = System.Console;
35
36    public class TreeRewriter<TTree> : TreeParser {
37        protected ITokenStream originalTokenStream;
38        protected ITreeAdaptor originalAdaptor;
39
40        System.Func<IAstRuleReturnScope<TTree>> topdown_func;
41        System.Func<IAstRuleReturnScope<TTree>> bottomup_func;
42
43        public TreeRewriter(ITreeNodeStream input)
44            : this(input, new RecognizerSharedState()) {
45        }
46        public TreeRewriter(ITreeNodeStream input, RecognizerSharedState state)
47            : base(input, state) {
48            originalAdaptor = input.TreeAdaptor;
49            originalTokenStream = input.TokenStream;
50            topdown_func = () => Topdown();
51            bottomup_func = () => Bottomup();
52        }
53
54        public virtual object ApplyOnce(object t, System.Func<IAstRuleReturnScope<TTree>> whichRule) {
55            if (t == null)
56                return null;
57
58            try {
59                // share TreeParser object but not parsing-related state
60                state = new RecognizerSharedState();
61                input = new CommonTreeNodeStream(originalAdaptor, t);
62                ((CommonTreeNodeStream)input).TokenStream = originalTokenStream;
63                BacktrackingLevel = 1;
64                IAstRuleReturnScope<TTree> r = whichRule();
65                BacktrackingLevel = 0;
66                if (Failed)
67                    return t;
68
69                if (typeof(CommonTree).IsAssignableFrom(typeof(TTree))) {
70                    if (r != null && !t.Equals(r.Tree) && r.Tree != null) {
71                        // show any transformations
72                        Console.Out.WriteLine(((CommonTree)t).ToStringTree() + " -> " +
73                                           ((CommonTree)(object)r.Tree).ToStringTree());
74                    }
75                }
76
77                if (r != null && r.Tree != null)
78                    return r.Tree;
79                else
80                    return t;
81            } catch (RecognitionException) {
82            }
83            return t;
84        }
85
86        public virtual object ApplyRepeatedly(object t, System.Func<IAstRuleReturnScope<TTree>> whichRule) {
87            bool treeChanged = true;
88            while (treeChanged) {
89                object u = ApplyOnce(t, whichRule);
90                treeChanged = !t.Equals(u);
91                t = u;
92            }
93            return t;
94        }
95
96        public virtual object Downup(object t) {
97            TreeVisitor v = new TreeVisitor(new CommonTreeAdaptor());
98            t = v.Visit(t, (o) => ApplyOnce(o, topdown_func), (o) => ApplyRepeatedly(o, bottomup_func));
99            return t;
100        }
101
102        // methods the downup strategy uses to do the up and down rules.
103        // to override, just define tree grammar rule topdown and turn on
104        // filter=true.
105        public virtual IAstRuleReturnScope<TTree> Topdown() {
106            return null;
107        }
108
109        public virtual IAstRuleReturnScope<TTree> Bottomup() {
110            return null;
111        }
112    }
113}
114