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