1<?php
2
3/**
4 * Hoa
5 *
6 *
7 * @license
8 *
9 * New BSD License
10 *
11 * Copyright © 2007-2017, Hoa community. All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions are met:
15 *     * Redistributions of source code must retain the above copyright
16 *       notice, this list of conditions and the following disclaimer.
17 *     * Redistributions in binary form must reproduce the above copyright
18 *       notice, this list of conditions and the following disclaimer in the
19 *       documentation and/or other materials provided with the distribution.
20 *     * Neither the name of the Hoa nor the names of its contributors may be
21 *       used to endorse or promote products derived from this software without
22 *       specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37namespace Hoa\Compiler\Llk;
38
39use Hoa\Visitor;
40
41/**
42 * Class \Hoa\Compiler\Llk\TreeNode.
43 *
44 * Provide a generic node for the AST produced by LL(k) parser.
45 *
46 * @copyright  Copyright © 2007-2017 Hoa community
47 * @license    New BSD License
48 */
49class TreeNode implements Visitor\Element
50{
51    /**
52     * ID (should be something like #ruleName or token).
53     *
54     * @var string
55     */
56    protected $_id       = null;
57
58    /**
59     * Value of the node (non-null for token nodes).
60     *
61     * @var array
62     */
63    protected $_value    = null;
64
65    /**
66     * Children.
67     *
68     * @var array
69     */
70    protected $_children = null;
71
72    /**
73     * Parent.
74     *
75     * @var \Hoa\Compiler\Llk\TreeNode
76     */
77    protected $_parent   = null;
78
79    /**
80     * Attached data.
81     *
82     * @var array
83     */
84    protected $_data     = [];
85
86
87
88    /**
89     * Constructor.
90     *
91     * @param   string                      $id          ID.
92     * @param   array                       $value       Value.
93     * @param   array                       $children    Children.
94     * @param   \Hoa\Compiler\Llk\TreeNode  $parent    Parent.
95     */
96    public function __construct(
97        $id,
98        array $value    = null,
99        array $children = [],
100        self  $parent   = null
101    ) {
102        $this->setId($id);
103
104        if (!empty($value)) {
105            $this->setValue($value);
106        }
107
108        $this->setChildren($children);
109
110        if (null !== $parent) {
111            $this->setParent($parent);
112        }
113
114        return;
115    }
116
117    /**
118     * Set ID.
119     *
120     * @param   string  $id    ID.
121     * @return  string
122     */
123    public function setId($id)
124    {
125        $old       = $this->_id;
126        $this->_id = $id;
127
128        return $old;
129    }
130
131    /**
132     * Get ID.
133     *
134     * @return  string
135     */
136    public function getId()
137    {
138        return $this->_id;
139    }
140
141    /**
142     * Set value.
143     *
144     * @param   array  $value    Value (token & value).
145     * @return  array
146     */
147    public function setValue(array $value)
148    {
149        $old          = $this->_value;
150        $this->_value = $value;
151
152        return $old;
153    }
154
155    /**
156     * Get value.
157     *
158     * @return  array
159     */
160    public function getValue()
161    {
162        return $this->_value;
163    }
164
165    /**
166     * Get value token.
167     *
168     * @return  string
169     */
170    public function getValueToken()
171    {
172        return
173            isset($this->_value['token'])
174                ? $this->_value['token']
175                : null;
176    }
177
178    /**
179     * Get value value.
180     *
181     * @return  string
182     */
183    public function getValueValue()
184    {
185        return
186            isset($this->_value['value'])
187                ? $this->_value['value']
188                : null;
189    }
190
191    /**
192     * Check if the node represents a token or not.
193     *
194     * @return  bool
195     */
196    public function isToken()
197    {
198        return !empty($this->_value);
199    }
200
201    /**
202     * Prepend a child.
203     *
204     * @param   \Hoa\Compiler\Llk\TreeNode  $child    Child.
205     * @return  \Hoa\Compiler\Llk\TreeNode
206     */
207    public function prependChild(TreeNode $child)
208    {
209        array_unshift($this->_children, $child);
210
211        return $this;
212    }
213
214    /**
215     * Append a child.
216     *
217     * @param   \Hoa\Compiler\Llk\TreeNode  $child    Child.
218     * @return  \Hoa\Compiler\Llk\TreeNode
219     */
220    public function appendChild(TreeNode $child)
221    {
222        $this->_children[] = $child;
223
224        return $this;
225    }
226
227    /**
228     * Set children.
229     *
230     * @param   array  $children    Children.
231     * @return  array
232     */
233    public function setChildren(array $children)
234    {
235        $old             = $this->_children;
236        $this->_children = $children;
237
238        return $old;
239    }
240
241    /**
242     * Get child.
243     *
244     * @param   int  $i    Index.
245     * @return  \Hoa\Compiler\Llk\TreeNode
246     */
247    public function getChild($i)
248    {
249        return
250            true === $this->childExists($i)
251                ? $this->_children[$i]
252                : null;
253    }
254
255    /**
256     * Get children.
257     *
258     * @return  array
259     */
260    public function getChildren()
261    {
262        return $this->_children;
263    }
264
265    /**
266     * Get number of children.
267     *
268     * @return  int
269     */
270    public function getChildrenNumber()
271    {
272        return count($this->_children);
273    }
274
275    /**
276     * Check if a child exists.
277     *
278     * @param   int  $i    Index.
279     * @return  bool
280     */
281    public function childExists($i)
282    {
283        return array_key_exists($i, $this->_children);
284    }
285
286    /**
287     * Set parent.
288     *
289     * @param   \Hoa\Compiler\Llk\TreeNode  $parent    Parent.
290     * @return  \Hoa\Compiler\Llk\TreeNode
291     */
292    public function setParent(TreeNode $parent)
293    {
294        $old           = $this->_parent;
295        $this->_parent = $parent;
296
297        return $old;
298    }
299
300    /**
301     * Get parent.
302     *
303     * @return  \Hoa\Compiler\Llk\TreeNode
304     */
305    public function getParent()
306    {
307        return $this->_parent;
308    }
309
310    /**
311     * Get data.
312     *
313     * @return  array
314     */
315    public function &getData()
316    {
317        return $this->_data;
318    }
319
320    /**
321     * Accept a visitor.
322     *
323     * @param   \Hoa\Visitor\Visit  $visitor    Visitor.
324     * @param   mixed               &$handle    Handle (reference).
325     * @param   mixed               $eldnah     Handle (no reference).
326     * @return  mixed
327     */
328    public function accept(
329        Visitor\Visit $visitor,
330        &$handle = null,
331        $eldnah  = null
332    ) {
333        return $visitor->visit($this, $handle, $eldnah);
334    }
335
336    /**
337     * Remove circular reference to the parent (help the garbage collector).
338     *
339     * @return  void
340     */
341    public function __destruct()
342    {
343        unset($this->_parent);
344
345        return;
346    }
347}
348