1/** A TreeAdaptor that works with any Tree implementation. */ 2org.antlr.runtime.tree.BaseTreeAdaptor = function() { 3 this.uniqueNodeID = 1; 4}; 5org.antlr.runtime.tree.TreeAdaptor = function() {}; 6 7org.antlr.lang.extend(org.antlr.runtime.tree.BaseTreeAdaptor, 8 org.antlr.runtime.tree.TreeAdaptor, 9{ 10 nil: function() { 11 return this.create(null); 12 }, 13 14 /** create tree node that holds the start and stop tokens associated 15 * with an error. 16 * 17 * If you specify your own kind of tree nodes, you will likely have to 18 * override this method. CommonTree returns Token.INVALID_TOKEN_TYPE 19 * if no token payload but you might have to set token type for diff 20 * node type. 21 */ 22 errorNode: function(input, start, stop, e) { 23 var t = new org.antlr.runtime.tree.CommonErrorNode(input, start, stop, e); 24 return t; 25 }, 26 27 isNil: function(tree) { 28 return tree.isNil(); 29 }, 30 31 /** This is generic in the sense that it will work with any kind of 32 * tree (not just Tree interface). It invokes the adaptor routines 33 * not the tree node routines to do the construction. 34 */ 35 dupTree: function(t, parent) { 36 if (arguments.length===1) { 37 parent = null; 38 } 39 if ( !t ) { 40 return null; 41 } 42 var newTree = this.dupNode(t); 43 // ensure new subtree root has parent/child index set 44 this.setChildIndex(newTree, this.getChildIndex(t)); // same index in new tree 45 this.setParent(newTree, parent); 46 var n = this.getChildCount(t), 47 i, child, newSubTree; 48 for (i = 0; i < n; i++) { 49 child = this.getChild(t, i); 50 newSubTree = this.dupTree(child, t); 51 this.addChild(newTree, newSubTree); 52 } 53 return newTree; 54 }, 55 56 /** Add a child to the tree t. If child is a flat tree (a list), make all 57 * in list children of t. Warning: if t has no children, but child does 58 * and child isNil then you can decide it is ok to move children to t via 59 * t.children = child.children; i.e., without copying the array. Just 60 * make sure that this is consistent with have the user will build 61 * ASTs. 62 */ 63 addChild: function(t, child) { 64 if ( t && org.antlr.lang.isValue(child) ) { 65 t.addChild(child); 66 } 67 }, 68 69 /** If oldRoot is a nil root, just copy or move the children to newRoot. 70 * If not a nil root, make oldRoot a child of newRoot. 71 * 72 * old=^(nil a b c), new=r yields ^(r a b c) 73 * old=^(a b c), new=r yields ^(r ^(a b c)) 74 * 75 * If newRoot is a nil-rooted single child tree, use the single 76 * child as the new root node. 77 * 78 * old=^(nil a b c), new=^(nil r) yields ^(r a b c) 79 * old=^(a b c), new=^(nil r) yields ^(r ^(a b c)) 80 * 81 * If oldRoot was null, it's ok, just return newRoot (even if isNil). 82 * 83 * old=null, new=r yields r 84 * old=null, new=^(nil r) yields ^(nil r) 85 * 86 * Return newRoot. Throw an exception if newRoot is not a 87 * simple node or nil root with a single child node--it must be a root 88 * node. If newRoot is ^(nil x) return x as newRoot. 89 * 90 * Be advised that it's ok for newRoot to point at oldRoot's 91 * children; i.e., you don't have to copy the list. We are 92 * constructing these nodes so we should have this control for 93 * efficiency. 94 */ 95 becomeRoot: function(newRoot, oldRoot) { 96 if (newRoot instanceof org.antlr.runtime.Token || !newRoot) { 97 newRoot = this.create(newRoot); 98 } 99 100 var newRootTree = newRoot, 101 oldRootTree = oldRoot; 102 if ( !oldRoot ) { 103 return newRoot; 104 } 105 // handle ^(nil real-node) 106 if ( newRootTree.isNil() ) { 107 var nc = newRootTree.getChildCount(); 108 if (nc===1) { 109 newRootTree = newRootTree.getChild(0); 110 } else if ( nc>1 ) { 111 // TODO: make tree run time exceptions hierarchy 112 throw new Error("more than one node as root (TODO: make exception hierarchy)"); 113 } 114 } 115 // add oldRoot to newRoot; addChild takes care of case where oldRoot 116 // is a flat list (i.e., nil-rooted tree). All children of oldRoot 117 // are added to newRoot. 118 newRootTree.addChild(oldRootTree); 119 return newRootTree; 120 }, 121 122 /** Transform ^(nil x) to x */ 123 rulePostProcessing: function(root) { 124 var r = root; 125 if ( r && r.isNil() ) { 126 if ( r.getChildCount()===0 ) { 127 r = null; 128 } 129 else if ( r.getChildCount()===1 ) { 130 r = r.getChild(0); 131 // whoever invokes rule will set parent and child index 132 r.setParent(null); 133 r.setChildIndex(-1); 134 } 135 } 136 return r; 137 }, 138 139 create: function(tokenType, fromToken) { 140 var text, t; 141 if (arguments.length===2) { 142 if (org.antlr.lang.isString(arguments[1])) { 143 text = arguments[1]; 144 fromToken = this.createToken(tokenType, text); 145 t = this.create(fromToken); 146 return t; 147 } else { 148 fromToken = this.createToken(fromToken); 149 fromToken.setType(tokenType); 150 t = this.create(fromToken); 151 return t; 152 } 153 } else if (arguments.length===3) { 154 text = arguments[2]; 155 fromToken = this.createToken(fromToken); 156 fromToken.setType(tokenType); 157 fromToken.setText(text); 158 t = this.create(fromToken); 159 return t; 160 } 161 }, 162 163 getType: function(t) { 164 t.getType(); 165 return 0; 166 }, 167 168 setType: function(t, type) { 169 throw new Error("don't know enough about Tree node"); 170 }, 171 172 getText: function(t) { 173 return t.getText(); 174 }, 175 176 setText: function(t, text) { 177 throw new Error("don't know enough about Tree node"); 178 }, 179 180 getChild: function(t, i) { 181 return t.getChild(i); 182 }, 183 184 setChild: function(t, i, child) { 185 t.setChild(i, child); 186 }, 187 188 deleteChild: function(t, i) { 189 return t.deleteChild(i); 190 }, 191 192 getChildCount: function(t) { 193 return t.getChildCount(); 194 }, 195 196 getUniqueID: function(node) { 197 if ( !this.treeToUniqueIDMap ) { 198 this.treeToUniqueIDMap = {}; 199 } 200 var prevID = this.treeToUniqueIDMap[node]; 201 if ( org.antlr.lang.isValue(prevID) ) { 202 return prevID; 203 } 204 var ID = this.uniqueNodeID; 205 this.treeToUniqueIDMap[node] = ID; 206 this.uniqueNodeID++; 207 return ID; 208 // GC makes these nonunique: 209 // return System.identityHashCode(node); 210 } 211}); 212