CommonTreeAdaptor.js revision 324c4644fee44b9898524c09511bd33c3f12e2df
1/** A TreeAdaptor that works with any Tree implementation.  It provides
2 *  really just factory methods; all the work is done by BaseTreeAdaptor.
3 *  If you would like to have different tokens created than ClassicToken
4 *  objects, you need to override this and then set the parser tree adaptor to
5 *  use your subclass.
6 *
7 *  To get your parser to build nodes of a different type, override
8 *  create(Token).
9 */
10org.antlr.runtime.tree.CommonTreeAdaptor = function() {};
11
12org.antlr.lang.extend(org.antlr.runtime.tree.CommonTreeAdaptor,
13                  org.antlr.runtime.tree.BaseTreeAdaptor, {
14    /** Duplicate a node.  This is part of the factory;
15     *    override if you want another kind of node to be built.
16     *
17     *  I could use reflection to prevent having to override this
18     *  but reflection is slow.
19     */
20    dupNode: function(t) {
21        if ( !org.antlr.lang.isValue(t) ) {
22            return null;
23        }
24        return t.dupNode();
25    },
26
27    create: function(payload) {
28        if (arguments.length>1) {
29            return org.antlr.runtime.tree.CommonTreeAdaptor.superclass.create.apply(this, arguments);
30        }
31        return new org.antlr.runtime.tree.CommonTree(payload);
32    },
33
34    /** Tell me how to create a token for use with imaginary token nodes.
35     *  For example, there is probably no input symbol associated with imaginary
36     *  token DECL, but you need to create it as a payload or whatever for
37     *  the DECL node as in ^(DECL type ID).
38     *
39     *  If you care what the token payload objects' type is, you should
40     *  override this method and any other createToken variant.
41     *
42     * Tell me how to create a token for use with imaginary token nodes.
43     *  For example, there is probably no input symbol associated with imaginary
44     *  token DECL, but you need to create it as a payload or whatever for
45     *  the DECL node as in ^(DECL type ID).
46     *
47     *  This is a variant of createToken where the new token is derived from
48     *  an actual real input token.  Typically this is for converting '{'
49     *  tokens to BLOCK etc...  You'll see
50     *
51     *    r : lc='{' ID+ '}' -> ^(BLOCK[$lc] ID+) ;
52     *
53     *  If you care what the token payload objects' type is, you should
54     *  override this method and any other createToken variant.
55     */
56    createToken: function(fromToken) {
57        if (arguments.length===2) {
58            return new org.antlr.runtime.CommonToken(arguments[0], arguments[1]);
59        } else {
60            return new org.antlr.runtime.CommonToken(arguments[0]);
61        }
62    },
63
64    /** Track start/stop token for subtree root created for a rule.
65     *  Only works with Tree nodes.  For rules that match nothing,
66     *  seems like this will yield start=i and stop=i-1 in a nil node.
67     *  Might be useful info so I'll not force to be i..i.
68     */
69    setTokenBoundaries: function(t, startToken, stopToken) {
70        if ( !org.antlr.lang.isValue(t) ) {
71            return;
72        }
73        var start = 0,
74            stop = 0;
75        if ( org.antlr.lang.isValue(startToken) ) {
76            if (startToken.getTokenIndex) {
77                start = startToken.getTokenIndex();
78            } else if (startToken.getStartIndex) {
79                start = startToken.getStartIndex();
80            } else {
81                start = startToken.getTokenStartIndex();
82            }
83        }
84        if ( org.antlr.lang.isValue(stopToken) ) {
85            if (stop.getTokenIndex) {
86                stop = stopToken.getTokenIndex();
87            } else if (stopToken.getStopIndex) {
88                stop = stopToken.getStopIndex();
89            } else {
90                stop = stopToken.getTokenStopIndex();
91            }
92        }
93        t.setTokenStartIndex(start);
94        t.setTokenStopIndex(stop);
95    },
96
97    getTokenStartIndex: function(t) {
98        if (!t) {
99            return -1;
100        }
101        return t.getTokenStartIndex();
102    },
103
104    getTokenStopIndex: function(t) {
105        if (!t) {
106            return -1;
107        }
108        return t.getTokenStopIndex();
109    },
110
111    getText: function(t) {
112        if (!t) {
113            return null;
114        }
115        return t.getText();
116    },
117
118    getType: function(t) {
119        if (!t) {
120            return org.antlr.runtime.Token.INVALID_TOKEN_TYPE;
121        }
122        return t.getType();
123    },
124
125    /** What is the Token associated with this node?  If
126     *  you are not using CommonTree, then you must
127     *  override this in your own adaptor.
128     */
129    getToken: function(t) {
130        if ( t instanceof org.antlr.runtime.tree.CommonTree ) {
131            return t.getToken();
132        }
133        return null; // no idea what to do
134    },
135
136    getChild: function(t, i) {
137        if (!t) {
138            return null;
139        }
140        return t.getChild(i);
141    },
142
143    getChildCount: function(t) {
144        if (!t) {
145            return 0;
146        }
147        return t.getChildCount();
148    },
149
150    getParent: function(t) {
151        return t.getParent();
152    },
153
154    setParent: function(t, parent) {
155        t.setParent(parent);
156    },
157
158    getChildIndex: function(t) {
159        return t.getChildIndex();
160    },
161
162    setChildIndex: function(t, index) {
163        t.setChildIndex(index);
164    },
165
166    replaceChildren: function(parent, startChildIndex, stopChildIndex, t) {
167        if ( parent ) {
168            parent.replaceChildren(startChildIndex, stopChildIndex, t);
169        }
170    }
171});
172