1/*
2 * [The "BSD licence"]
3 * Copyright (c) 2011 Terence Parr
4 * All rights reserved.
5 *
6 * Conversion to C#:
7 * Copyright (c) 2011 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{
35    using ArgumentNullException = System.ArgumentNullException;
36
37    /** <summary>
38     *  A tree node that is wrapper for a Token object.  After 3.0 release
39     *  while building tree rewrite stuff, it became clear that computing
40     *  parent and child index is very difficult and cumbersome.  Better to
41     *  spend the space in every tree node.  If you don't want these extra
42     *  fields, it's easy to cut them out in your own BaseTree subclass.
43     *  </summary>
44     */
45    [System.Serializable]
46    public class CommonTree : BaseTree
47    {
48        /** <summary>A single token is the payload</summary> */
49        private IToken _token;
50
51        /** <summary>
52         *  What token indexes bracket all tokens associated with this node
53         *  and below?
54         *  </summary>
55         */
56        protected int startIndex = -1;
57        protected int stopIndex = -1;
58
59        /** <summary>Who is the parent node of this node; if null, implies node is root</summary> */
60        CommonTree parent;
61
62        /** <summary>What index is this node in the child list? Range: 0..n-1</summary> */
63        int childIndex = -1;
64
65        public CommonTree()
66        {
67        }
68
69        public CommonTree( CommonTree node )
70            : base( node )
71        {
72            if (node == null)
73                throw new ArgumentNullException("node");
74
75            this.Token = node.Token;
76            this.startIndex = node.startIndex;
77            this.stopIndex = node.stopIndex;
78        }
79
80        public CommonTree( IToken t )
81        {
82            this.Token = t;
83        }
84
85        #region Properties
86
87        public override int CharPositionInLine
88        {
89            get
90            {
91                if ( Token == null || Token.CharPositionInLine == -1 )
92                {
93                    if ( ChildCount > 0 )
94                        return Children[0].CharPositionInLine;
95
96                    return 0;
97                }
98                return Token.CharPositionInLine;
99            }
100
101            set
102            {
103                base.CharPositionInLine = value;
104            }
105        }
106
107        public override int ChildIndex
108        {
109            get
110            {
111                return childIndex;
112            }
113
114            set
115            {
116                childIndex = value;
117            }
118        }
119
120        public override bool IsNil
121        {
122            get
123            {
124                return Token == null;
125            }
126        }
127
128        public override int Line
129        {
130            get
131            {
132                if ( Token == null || Token.Line == 0 )
133                {
134                    if ( ChildCount > 0 )
135                        return Children[0].Line;
136
137                    return 0;
138                }
139
140                return Token.Line;
141            }
142
143            set
144            {
145                base.Line = value;
146            }
147        }
148
149        public override ITree Parent
150        {
151            get
152            {
153                return parent;
154            }
155
156            set
157            {
158                parent = (CommonTree)value;
159            }
160        }
161
162        public override string Text
163        {
164            get
165            {
166                if ( Token == null )
167                    return null;
168
169                return Token.Text;
170            }
171
172            set
173            {
174            }
175        }
176
177        public IToken Token
178        {
179            get
180            {
181                return _token;
182            }
183
184            set
185            {
186                _token = value;
187            }
188        }
189
190        public override int TokenStartIndex
191        {
192            get
193            {
194                if ( startIndex == -1 && Token != null )
195                    return Token.TokenIndex;
196
197                return startIndex;
198            }
199
200            set
201            {
202                startIndex = value;
203            }
204        }
205
206        public override int TokenStopIndex
207        {
208            get
209            {
210                if ( stopIndex == -1 && Token != null )
211                {
212                    return Token.TokenIndex;
213                }
214                return stopIndex;
215            }
216
217            set
218            {
219                stopIndex = value;
220            }
221        }
222
223        public override int Type
224        {
225            get
226            {
227                if ( Token == null )
228                    return TokenTypes.Invalid;
229
230                return Token.Type;
231            }
232
233            set
234            {
235            }
236        }
237
238        #endregion
239
240        public override ITree DupNode()
241        {
242            return new CommonTree( this );
243        }
244
245        /** <summary>
246         *  For every node in this subtree, make sure it's start/stop token's
247         *  are set.  Walk depth first, visit bottom up.  Only updates nodes
248         *  with at least one token index &lt; 0.
249         *  </summary>
250         */
251        public virtual void SetUnknownTokenBoundaries()
252        {
253            if ( Children == null )
254            {
255                if ( startIndex < 0 || stopIndex < 0 )
256                    startIndex = stopIndex = Token.TokenIndex;
257
258                return;
259            }
260
261            foreach (ITree childTree in Children)
262            {
263                CommonTree commonTree = childTree as CommonTree;
264                if (commonTree == null)
265                    continue;
266
267                commonTree.SetUnknownTokenBoundaries();
268            }
269
270            if ( startIndex >= 0 && stopIndex >= 0 )
271                return; // already set
272
273            if ( Children.Count > 0 )
274            {
275                ITree firstChild = Children[0];
276                ITree lastChild = Children[Children.Count - 1];
277                startIndex = firstChild.TokenStartIndex;
278                stopIndex = lastChild.TokenStopIndex;
279            }
280        }
281
282        public override string ToString()
283        {
284            if (IsNil)
285                return "nil";
286
287            if (Type == TokenTypes.Invalid)
288                return "<errornode>";
289
290            if (Token == null)
291                return string.Empty;
292
293            return Token.Text;
294        }
295    }
296}
297