1 /* 2 [The "BSD license"] 3 Copyright (c) 2005-2006 Terence Parr 4 All rights reserved. 5 6 Redistribution and use in source and binary forms, with or without 7 modification, are permitted provided that the following conditions 8 are met: 9 1. Redistributions of source code must retain the above copyright 10 notice, this list of conditions and the following disclaimer. 11 2. Redistributions in binary form must reproduce the above copyright 12 notice, this list of conditions and the following disclaimer in the 13 documentation and/or other materials provided with the distribution. 14 3. The name of the author may not be used to endorse or promote products 15 derived from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** Templates for building ASTs during tree parsing. 30 * 31 * Deal with many combinations. Dimensions are: 32 * Auto build or rewrite 33 * no label, label, list label (label/no-label handled together) 34 * child, root 35 * token, set, rule, wildcard 36 * 37 * Each combination has its own template except that label/no label 38 * is combined into tokenRef, ruleRef, ... 39 */ 40 group ASTTreeParser; 41 42 /** Add a variable to track last element matched */ 43 ruleDeclarations() ::= << 44 <super.ruleDeclarations()> 45 var _first_0:<ASTLabelType> = null; 46 var _last:<ASTLabelType> = null;<\n> 47 >> 48 49 /** What to emit when there is no rewrite rule. For auto build 50 * mode, does nothing. 51 */ 52 noRewrite(rewriteBlockLevel, treeLevel) ::= << 53 <if(backtracking)>if ( <actions.(actionScope).synpredgate> ) {<endif> 54 <if(rewriteMode)> 55 retval.tree = <ASTLabelType>(_first_0); 56 if ( adaptor.getParent(retval.tree)!=null && adaptor.isNil( adaptor.getParent(retval.tree) ) ) 57 retval.tree = <ASTLabelType>(adaptor.getParent(retval.tree)); 58 <endif> 59 <if(backtracking)>}<endif> 60 >> 61 62 /** match ^(root children) in tree parser; override here to 63 * add tree construction actions. 64 */ 65 tree(root, actionsAfterRoot, children, nullableChildList, 66 enclosingTreeLevel, treeLevel) ::= << 67 _last = <ASTLabelType>(input.LT(1)); 68 { 69 var _save_last_<treeLevel>:<ASTLabelType> = _last; 70 var _first_<treeLevel>:<ASTLabelType> = null; 71 <if(!rewriteMode)> 72 var root_<treeLevel>:<ASTLabelType> = <ASTLabelType>(adaptor.nil()); 73 <endif> 74 <root:element()> 75 <if(rewriteMode)> 76 <if(backtracking)>if ( <actions.(actionScope).synpredgate> )<endif> 77 <if(root.el.rule)> 78 if ( _first_<enclosingTreeLevel>==null ) _first_<enclosingTreeLevel> = <root.el.label>.tree; 79 <else> 80 if ( _first_<enclosingTreeLevel>==null ) _first_<enclosingTreeLevel> = <root.el.label>; 81 <endif> 82 <endif> 83 <actionsAfterRoot:element()> 84 <if(nullableChildList)> 85 if ( input.LA(1)==TokenConstants.DOWN ) { 86 matchStream(input, TokenConstants.DOWN, null); <checkRuleBacktrackFailure()> 87 <children:element()> 88 matchStream(input, TokenConstants.UP, null); <checkRuleBacktrackFailure()> 89 } 90 <else> 91 matchStream(input, TokenConstants.DOWN, null); <checkRuleBacktrackFailure()> 92 <children:element()> 93 matchStream(input, TokenConstants.UP, null); <checkRuleBacktrackFailure()> 94 <endif> 95 <if(!rewriteMode)> 96 adaptor.addChild(root_<enclosingTreeLevel>, root_<treeLevel>); 97 <endif> 98 _last = _save_last_<treeLevel>; 99 }<\n> 100 >> 101 102 // TOKEN AST STUFF 103 104 /** ID! and output=AST (same as plain tokenRef) 'cept add 105 * setting of _last 106 */ 107 tokenRefBang(token,label,elementIndex) ::= << 108 _last = <ASTLabelType>(input.LT(1)); 109 <super.tokenRef(...)> 110 >> 111 112 /** ID auto construct */ 113 tokenRef(token,label,elementIndex,terminalOptions) ::= << 114 _last = <ASTLabelType>(input.LT(1)); 115 <super.tokenRef(...)> 116 <if(!rewriteMode)> 117 <if(backtracking)>if ( <actions.(actionScope).synpredgate> ) {<endif> 118 <if(terminalOptions.node)> 119 <label>_tree = new <terminalOptions.node>(<label>); 120 <else> 121 <label>_tree = <ASTLabelType>(adaptor.dupNode(<label>)); 122 <endif><\n> 123 adaptor.addChild(root_<treeLevel>, <label>_tree); 124 <if(backtracking)>}<endif> 125 <else> <! rewrite mode !> 126 <if(backtracking)>if ( <actions.(actionScope).synpredgate> )<endif> 127 if ( _first_<treeLevel>==null ) _first_<treeLevel> = <label>; 128 <endif> 129 >> 130 131 /** label+=TOKEN auto construct */ 132 tokenRefAndListLabel(token,label,elementIndex) ::= << 133 <tokenRef(...)> 134 <listLabel(elem=label,...)> 135 >> 136 137 /** ^(ID ...) auto construct */ 138 tokenRefRuleRoot(token,label,elementIndex,terminalOptions) ::= << 139 _last = <ASTLabelType>(input.LT(1)); 140 <super.tokenRef(...)> 141 <if(!rewriteMode)> 142 <if(backtracking)>if ( <actions.(actionScope).synpredgate> ) {<endif> 143 <if(terminalOptions.node)> 144 <label>_tree = new <terminalOptions.node>(<label>); 145 <else> 146 <label>_tree = <ASTLabelType>(adaptor.dupNode(<label>)); 147 <endif><\n> 148 root_<treeLevel> = <ASTLabelType>(adaptor.becomeRoot(<label>_tree, root_<treeLevel>)); 149 <if(backtracking)>}<endif> 150 <endif> 151 >> 152 153 /** Match ^(label+=TOKEN ...) auto construct */ 154 tokenRefRuleRootAndListLabel(token,label,elementIndex,terminalOptions) ::= << 155 <tokenRefRuleRoot(...)> 156 <listLabel(elem=label,...)> 157 >> 158 159 /** Match . wildcard and auto dup the node/subtree */ 160 wildcard(token,label,elementIndex,terminalOptions) ::= << 161 _last = (<ASTLabelType>)input.LT(1); 162 <super.wildcard(...)> 163 <if(!rewriteMode)> 164 <if(backtracking)>if ( <actions.(actionScope).synpredgate> ) {<endif> 165 <label>_tree = (<ASTLabelType>)adaptor.dupTree(<label>); 166 adaptor.addChild(root_<treeLevel>, <label>_tree); 167 <if(backtracking)>}<endif> 168 <else> <! rewrite mode !> 169 <if(backtracking)>if ( <actions.(actionScope).synpredgate> )<endif> 170 if ( _first_<treeLevel>==null ) _first_<treeLevel> = <label>; 171 <endif> 172 >> 173 174 // SET AST 175 176 matchSet(s,label,terminalOptions,elementIndex,postmatchCode) ::= << 177 _last = <ASTLabelType>(input.LT(1)); 178 <super.matchSet(..., postmatchCode={ 179 <if(!rewriteMode)> 180 <if(backtracking)>if ( <actions.(actionScope).synpredgate> ) {<endif> 181 <if(terminalOptions.node)> 182 <label>_tree = new <terminalOptions.node>(<label>); 183 <else> 184 <label>_tree = <ASTLabelType>(adaptor.dupNode(<label>)); 185 <endif><\n> 186 adaptor.addChild(root_<treeLevel>, <label>_tree); 187 <if(backtracking)>}<endif> 188 <endif> 189 } 190 )> 191 >> 192 193 matchRuleBlockSet(s,label,terminalOptions,elementIndex,postmatchCode,treeLevel="0") ::= << 194 <matchSet(...)> 195 <noRewrite()> <! set return tree !> 196 >> 197 198 matchSetBang(s,label,elementIndex,postmatchCode) ::= << 199 _last = <ASTLabelType>(input.LT(1)); 200 <super.matchSet(...)> 201 >> 202 203 matchSetRuleRoot(s,label,terminalOptions,elementIndex,debug) ::= << 204 <super.matchSet(..., postmatchCode={ 205 <if(!rewriteMode)> 206 <if(backtracking)>if ( <actions.(actionScope).synpredgate> ) {<endif> 207 <if(terminalOptions.node)> 208 <label>_tree = new <terminalOptions.node>(<label>); 209 <else> 210 <label>_tree = <ASTLabelType>(adaptor.dupNode(<label>)); 211 <endif><\n> 212 root_<treeLevel> = <ASTLabelType>(adaptor.becomeRoot(<label>_tree, root_<treeLevel>)); 213 <if(backtracking)>}<endif> 214 <endif> 215 } 216 )> 217 >> 218 219 // RULE REF AST 220 221 /** rule auto construct */ 222 ruleRef(rule,label,elementIndex,args,scope) ::= << 223 _last = <ASTLabelType>(input.LT(1)); 224 <super.ruleRef(...)> 225 <if(backtracking)>if ( <actions.(actionScope).synpredgate> ) <endif> 226 <if(!rewriteMode)> 227 adaptor.addChild(root_<treeLevel>, <label>.tree); 228 <else> <! rewrite mode !> 229 if ( _first_<treeLevel>==null ) _first_<treeLevel> = <label>.tree; 230 <endif> 231 >> 232 233 /** x+=rule auto construct */ 234 ruleRefAndListLabel(rule,label,elementIndex,args,scope) ::= << 235 <ruleRef(...)> 236 <listLabel(elem=label+".tree",...)> 237 >> 238 239 /** ^(rule ...) auto construct */ 240 ruleRefRuleRoot(rule,label,elementIndex,args,scope) ::= << 241 _last = <ASTLabelType>(input.LT(1)); 242 <super.ruleRef(...)> 243 <if(!rewriteMode)> 244 <if(backtracking)>if ( <actions.(actionScope).synpredgate> ) <endif>root_<treeLevel> = <ASTLabelType>(adaptor.becomeRoot(<label>.tree, root_<treeLevel>)); 245 <endif> 246 >> 247 248 /** ^(x+=rule ...) auto construct */ 249 ruleRefRuleRootAndListLabel(rule,label,elementIndex,args,scope) ::= << 250 <ruleRefRuleRoot(...)> 251 <listLabel(elem=label+".tree",...)> 252 >> 253 254 /** rule when output=AST and tracking for rewrite */ 255 ruleRefTrack(rule,label,elementIndex,args,scope) ::= << 256 _last = <ASTLabelType>(input.LT(1)); 257 <super.ruleRefTrack(...)> 258 >> 259 260 /** x+=rule when output=AST and tracking for rewrite */ 261 ruleRefTrackAndListLabel(rule,label,elementIndex,args,scope) ::= << 262 _last = <ASTLabelType>(input.LT(1)); 263 <super.ruleRefTrackAndListLabel(...)> 264 >> 265 266 /** ^(rule ...) rewrite */ 267 ruleRefRuleRootTrack(rule,label,elementIndex,args,scope) ::= << 268 _last = <ASTLabelType>(input.LT(1)); 269 <super.ruleRefRootTrack(...)> 270 >> 271 272 /** ^(x+=rule ...) rewrite */ 273 ruleRefRuleRootTrackAndListLabel(rule,label,elementIndex,args,scope) ::= << 274 _last = <ASTLabelType>(input.LT(1)); 275 <super.ruleRefRuleRootTrackAndListLabel(...)> 276 >> 277 278 /** Streams for token refs are tree nodes now; override to 279 * change nextToken to nextNode. 280 */ 281 createRewriteNodeFromElement(token,terminalOptions,scope) ::= << 282 <if(terminalOptions.node)> 283 new <terminalOptions.node>(stream_<token>.nextNode()) 284 <else> 285 stream_<token>.nextNode() 286 <endif> 287 >> 288 289 ruleCleanUp() ::= << 290 <super.ruleCleanUp()> 291 <if(!rewriteMode)> 292 <if(backtracking)>if ( <actions.(actionScope).synpredgate> ) {<\n><endif> 293 retval.tree = <ASTLabelType>(adaptor.rulePostProcessing(root_0)); 294 <if(backtracking)>}<endif> 295 <endif> 296 >> 297