1 /*
2  * [The "BSD license"]
3  *  Copyright (c) 2012 Terence Parr
4  *  Copyright (c) 2012 Sam Harwell
5  *  All rights reserved.
6  *
7  *  Redistribution and use in source and binary forms, with or without
8  *  modification, are permitted provided that the following conditions
9  *  are met:
10  *
11  *  1. Redistributions of source code must retain the above copyright
12  *     notice, this list of conditions and the following disclaimer.
13  *  2. Redistributions in binary form must reproduce the above copyright
14  *     notice, this list of conditions and the following disclaimer in the
15  *     documentation and/or other materials provided with the distribution.
16  *  3. The name of the author may not be used to endorse or promote products
17  *     derived from this software without specific prior written permission.
18  *
19  *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 module antlr.v4.runtime.tree.AbstractParseTreeVisitor;
32 
33 import antlr.v4.runtime.tree.ParseTreeVisitor;
34 
35 /**
36  * TODO add class description
37  */
38 abstract class AbstractParseTreeVisitor(T) : ParseTreeVisitor!T
39 {
40 
41     /**
42      * @uml
43      * {@inheritDoc}
44      *
45      *  <p>The default implementation calls {@link ParseTree#accept} on the
46      *  specified tree.</p>
47      */
48     public T visit(ParseTree tree)
49     {
50         return tree.accept(this);
51     }
52 
53     /**
54      * @uml
55      * {@inheritDoc}
56      *
57      * <p>The default implementation initializes the aggregate result to
58      * {@link #defaultResult defaultResult()}. Before visiting each child, it
59      * calls {@link #shouldVisitNextChild shouldVisitNextChild}; if the result
60      * is {@code false} no more children are visited and the current aggregate
61      * result is returned. After visiting a child, the aggregate result is
62      * updated by calling {@link #aggregateResult aggregateResult} with the
63      * previous aggregate result and the result of visiting the child.</p>
64      *
65      * <p>The default implementation is not safe for use in visitors that modify
66      * the tree structure. Visitors that modify the tree should override this
67      * method to behave properly in respect to the specific algorithm in use.</p>
68      * @override
69      */
70     public override T visitChildren(RuleNode node)
71     {
72         T result = defaultResult();
73         int n = node.getChildCount();
74         for (int i=0; i<n; i++) {
75             if (!shouldVisitNextChild(node, result)) {
76                 break;
77             }
78 
79             ParseTree c = node.getChild(i);
80             T childResult = c.accept(this);
81             result = aggregateResult(result, childResult);
82         }
83 
84         return result;
85     }
86 
87     /**
88      * @uml
89      * {@inheritDoc}
90      *
91      * <p>The default implementation returns the result of
92      * {@link #defaultResult defaultResult}.</p>
93      * @override
94      */
95     public override T visitTerminal(TerminalNode node)
96     {
97         return defaultResult();
98     }
99 
100     /**
101      * @uml
102      * {@inheritDoc}
103      *
104      * <p>The default implementation returns the result of
105      * {@link #defaultResult defaultResult}.</p>
106      * @override
107      */
108     public override T visitErrorNode(ErrorNode node)
109     {
110         return defaultResult();
111     }
112 
113     /**
114      * @uml
115      * Gets the default value returned by visitor methods. This value is
116      * returned by the default implementations of
117      * {@link #visitTerminal visitTerminal}, {@link #visitErrorNode visitErrorNode}.
118      * The default implementation of {@link #visitChildren visitChildren}
119      * initializes its aggregate result to this value.
120      *
121      * <p>The base implementation returns {@code null}.</p>
122      *
123      *  @return The default value returned by visitor methods.
124      */
125     private T defaultResult()
126     {
127         return null;
128     }
129 
130     /**
131      * @uml
132      * Aggregates the results of visiting multiple children of a node. After
133      * either all children are visited or {@link #shouldVisitNextChild} returns
134      * {@code false}, the aggregate value is returned as the result of
135      * {@link #visitChildren}.
136      *
137      * <p>The default implementation returns {@code nextResult}, meaning
138      * {@link #visitChildren} will return the result of the last child visited
139      * (or return the initial value if the node has no children).</p>
140      *
141      *  @param aggregate The previous aggregate value. In the default
142      * implementation, the aggregate value is initialized to
143      *  {@link #defaultResult}, which is passed as the {@code aggregate} argument
144      * to this method after the first child node is visited.
145      *  @param nextResult The result of the immediately preceeding call to visit
146      * a child node.
147      *
148      *  @return The updated aggregate result.
149      */
150     private T aggregateResult(T aggregate, T nextResult)
151     {
152     }
153 
154     /**
155      * @uml
156      * This method is called after visiting each child in
157      * {@link #visitChildren}. This method is first called before the first
158      * child is visited; at that point {@code currentResult} will be the initial
159      * value (in the default implementation, the initial value is returned by a
160      * call to {@link #defaultResult}. This method is not called after the last
161      * child is visited.
162      *
163      * <p>The default implementation always returns {@code true}, indicating that
164      * {@code visitChildren} should only return after all children are visited.
165      * One reason to override this method is to provide a "short circuit"
166      * evaluation option for situations where the result of visiting a single
167      * child has the potential to determine the result of the visit operation as
168      * a whole.</p>
169      *
170      *  @param node The {@link RuleNode} whose children are currently being
171      * visited.
172      *  @param currentResult The current aggregate result of the children visited
173      * to the current point.
174      *
175      *  @return {@code true} to continue visiting children. Otherwise return
176      *  {@code false} to stop visiting children and immediately return the
177      *  current aggregate result from {@link #visitChildren}.
178      */
179     private bool shouldVisitNextChild(RuleNode node, T currentResult)
180     {
181     }
182 
183 }