1/*
2 * [The "BSD licence"]
3 * Copyright (c) 2005-2008 Terence Parr
4 * All rights reserved.
5 *
6 * Conversion to C#:
7 * Copyright (c) 2008-2009 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    /** <summary>
36     *  A TreeAdaptor that works with any Tree implementation.  It provides
37     *  really just factory methods; all the work is done by BaseTreeAdaptor.
38     *  If you would like to have different tokens created than ClassicToken
39     *  objects, you need to override this and then set the parser tree adaptor to
40     *  use your subclass.
41     *  </summary>
42     *
43     *  <remarks>
44     *  To get your parser to build nodes of a different type, override
45     *  create(Token), errorNode(), and to be safe, YourTreeClass.dupNode().
46     *  dupNode is called to duplicate nodes during rewrite operations.
47     *  </remarks>
48     */
49    public class CommonTreeAdaptor : BaseTreeAdaptor {
50        /** <summary>
51         *  Duplicate a node.  This is part of the factory;
52         *  override if you want another kind of node to be built.
53         *  </summary>
54         *
55         *  <remarks>
56         *  I could use reflection to prevent having to override this
57         *  but reflection is slow.
58         *  </remarks>
59         */
60        public override object DupNode(object t) {
61            if (t == null)
62                return null;
63
64            return ((ITree)t).DupNode();
65        }
66
67        public override object Create(IToken payload) {
68            return new CommonTree(payload);
69        }
70
71        /** <summary>
72         *  Tell me how to create a token for use with imaginary token nodes.
73         *  For example, there is probably no input symbol associated with imaginary
74         *  token DECL, but you need to create it as a payload or whatever for
75         *  the DECL node as in ^(DECL type ID).
76         *  </summary>
77         *
78         *  <remarks>
79         *  If you care what the token payload objects' type is, you should
80         *  override this method and any other createToken variant.
81         *  </remarks>
82         */
83        public override IToken CreateToken(int tokenType, string text) {
84            return new CommonToken(tokenType, text);
85        }
86
87        /** <summary>
88         *  Tell me how to create a token for use with imaginary token nodes.
89         *  For example, there is probably no input symbol associated with imaginary
90         *  token DECL, but you need to create it as a payload or whatever for
91         *  the DECL node as in ^(DECL type ID).
92         *  </summary>
93         *
94         *  <remarks>
95         *  This is a variant of createToken where the new token is derived from
96         *  an actual real input token.  Typically this is for converting '{'
97         *  tokens to BLOCK etc...  You'll see
98         *
99         *    r : lc='{' ID+ '}' -> ^(BLOCK[$lc] ID+) ;
100         *
101         *  If you care what the token payload objects' type is, you should
102         *  override this method and any other createToken variant.
103         *  </remarks>
104         */
105        public override IToken CreateToken(IToken fromToken) {
106            return new CommonToken(fromToken);
107        }
108
109        /** <summary>
110         *  Track start/stop token for subtree root created for a rule.
111         *  Only works with Tree nodes.  For rules that match nothing,
112         *  seems like this will yield start=i and stop=i-1 in a nil node.
113         *  Might be useful info so I'll not force to be i..i.
114         *  </summary>
115         */
116        public override void SetTokenBoundaries(object t, IToken startToken, IToken stopToken) {
117            if (t == null)
118                return;
119
120            int start = 0;
121            int stop = 0;
122
123            if (startToken != null)
124                start = startToken.TokenIndex;
125
126            if (stopToken != null)
127                stop = stopToken.TokenIndex;
128
129            ((ITree)t).TokenStartIndex = start;
130            ((ITree)t).TokenStopIndex = stop;
131        }
132
133        public override int GetTokenStartIndex(object t) {
134            if (t == null)
135                return -1;
136
137            return ((ITree)t).TokenStartIndex;
138        }
139
140        public override int GetTokenStopIndex(object t) {
141            if (t == null)
142                return -1;
143
144            return ((ITree)t).TokenStopIndex;
145        }
146
147        public override string GetText(object t) {
148            if (t == null)
149                return null;
150
151            return ((ITree)t).Text;
152        }
153
154        public override int GetType(object t) {
155            if (t == null)
156                return TokenTypes.Invalid;
157
158            return ((ITree)t).Type;
159        }
160
161        /** <summary>
162         *  What is the Token associated with this node?  If
163         *  you are not using CommonTree, then you must
164         *  override this in your own adaptor.
165         *  </summary>
166         */
167        public override IToken GetToken(object t) {
168            if (t is CommonTree) {
169                return ((CommonTree)t).Token;
170            }
171            return null; // no idea what to do
172        }
173
174        public override object GetChild(object t, int i) {
175            if (t == null)
176                return null;
177
178            return ((ITree)t).GetChild(i);
179        }
180
181        public override int GetChildCount(object t) {
182            if (t == null)
183                return 0;
184
185            return ((ITree)t).ChildCount;
186        }
187
188        public override object GetParent(object t) {
189            if (t == null)
190                return null;
191
192            return ((ITree)t).Parent;
193        }
194
195        public override void SetParent(object t, object parent) {
196            if (t != null)
197                ((ITree)t).Parent = (ITree)parent;
198        }
199
200        public override int GetChildIndex(object t) {
201            if (t == null)
202                return 0;
203
204            return ((ITree)t).ChildIndex;
205        }
206
207        public override void SetChildIndex(object t, int index) {
208            if (t != null)
209                ((ITree)t).ChildIndex = index;
210        }
211
212        public override void ReplaceChildren(object parent, int startChildIndex, int stopChildIndex, object t) {
213            if (parent != null) {
214                ((ITree)parent).ReplaceChildren(startChildIndex, stopChildIndex, t);
215            }
216        }
217    }
218}
219