1 /*
2  * Copyright (c) 2012-2019 The ANTLR Project. All rights reserved.
3  * Use of this file is governed by the BSD 3-clause license that
4  * can be found in the LICENSE.txt file in the project root.
5  */
6 
7 module antlr.v4.runtime.tree.AbstractParseTreeVisitor;
8 
9 import antlr.v4.runtime.tree.ParseTreeVisitor;
10 import antlr.v4.runtime.tree.ParseTree;
11 import antlr.v4.runtime.tree.RuleNode;
12 import antlr.v4.runtime.tree.TerminalNode;
13 import antlr.v4.runtime.tree.ErrorNode;
14 import std.variant : Variant;
15 
16 /**
17  * TODO add class description
18  */
19 abstract class AbstractParseTreeVisitor : ParseTreeVisitor
20 {
21 
22     /**
23      * @uml
24      * {@inheritDoc}
25      *
26      *  <p>The default implementation calls {@link ParseTree#accept} on the
27      *  specified tree.</p>
28      */
29     public Variant visit(ParseTree tree)
30     {
31         return tree.accept(this);
32     }
33 
34     /**
35      * @uml
36      * {@inheritDoc}
37      *
38      * <p>The default implementation initializes the aggregate result to
39      * {@link #defaultResult defaultResult()}. Before visiting each child, it
40      * calls {@link #shouldVisitNextChild shouldVisitNextChild}; if the result
41      * is {@code false} no more children are visited and the current aggregate
42      * result is returned. After visiting a child, the aggregate result is
43      * updated by calling {@link #aggregateResult aggregateResult} with the
44      * previous aggregate result and the result of visiting the child.</p>
45      *
46      * <p>The default implementation is not safe for use in visitors that modify
47      * the tree structure. Visitors that modify the tree should override this
48      * method to behave properly in respect to the specific algorithm in use.</p>
49      * @override
50      */
51     public override Variant visitChildren(RuleNode node)
52     {
53         Variant result = defaultResult();
54         int n = node.getChildCount();
55         for (int i=0; i<n; i++) {
56             if (!shouldVisitNextChild(node, result)) {
57                 break;
58             }
59 
60             ParseTree c = node.getChild(i);
61             Variant childResult = c.accept(this);
62             result = aggregateResult(result, childResult);
63         }
64 
65         return result;
66     }
67 
68     /**
69      * @uml
70      * {@inheritDoc}
71      *
72      * <p>The default implementation returns the result of
73      * {@link #defaultResult defaultResult}.</p>
74      * @override
75      */
76     public override Variant visitTerminal(TerminalNode node)
77     {
78         return defaultResult();
79     }
80 
81     /**
82      * @uml
83      * {@inheritDoc}
84      *
85      * <p>The default implementation returns the result of
86      * {@link #defaultResult defaultResult}.</p>
87      * @override
88      */
89     public override Variant visitErrorNode(ErrorNode node)
90     {
91         return defaultResult();
92     }
93 
94     /**
95      * @uml
96      * Gets the default value returned by visitor methods. This value is
97      * returned by the default implementations of
98      * {@link #visitTerminal visitTerminal}, {@link #visitErrorNode visitErrorNode}.
99      * The default implementation of {@link #visitChildren visitChildren}
100      * initializes its aggregate result to this value.
101      *
102      * <p>The base implementation returns {@code null}.</p>
103      *
104      *  @return The default value returned by visitor methods.
105      */
106     private Variant defaultResult()
107     {
108         return Variant(null);
109     }
110 
111     /**
112      * @uml
113      * Aggregates the results of visiting multiple children of a node. After
114      * either all children are visited or {@link #shouldVisitNextChild} returns
115      * {@code false}, the aggregate value is returned as the result of
116      * {@link #visitChildren}.
117      *
118      * <p>The default implementation returns {@code nextResult}, meaning
119      * {@link #visitChildren} will return the result of the last child visited
120      * (or return the initial value if the node has no children).</p>
121      *
122      *  @param aggregate The previous aggregate value. In the default
123      * implementation, the aggregate value is initialized to
124      *  {@link #defaultResult}, which is passed as the {@code aggregate} argument
125      * to this method after the first child node is visited.
126      *  @param nextResult The result of the immediately preceeding call to visit
127      * a child node.
128      *
129      *  @return The updated aggregate result.
130      */
131     private Variant aggregateResult(Variant aggregate, Variant nextResult)
132     {
133         return nextResult;
134     }
135 
136     /**
137      * @uml
138      * This method is called after visiting each child in
139      * {@link #visitChildren}. This method is first called before the first
140      * child is visited; at that point {@code currentResult} will be the initial
141      * value (in the default implementation, the initial value is returned by a
142      * call to {@link #defaultResult}. This method is not called after the last
143      * child is visited.
144      *
145      * <p>The default implementation always returns {@code true}, indicating that
146      * {@code visitChildren} should only return after all children are visited.
147      * One reason to override this method is to provide a "short circuit"
148      * evaluation option for situations where the result of visiting a single
149      * child has the potential to determine the result of the visit operation as
150      * a whole.</p>
151      *
152      *  @param node The {@link RuleNode} whose children are currently being
153      * visited.
154      *  @param currentResult The current aggregate result of the children visited
155      * to the current point.
156      *
157      *  @return {@code true} to continue visiting children. Otherwise return
158      *  {@code false} to stop visiting children and immediately return the
159      *  current aggregate result from {@link #visitChildren}.
160      */
161     private bool shouldVisitNextChild(RuleNode node, Variant currentResult)
162     {
163         return true;
164     }
165 
166 }