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 group AST; 29 30 @outputFile.imports() ::= << 31 <@super.imports()> 32 <if(!TREE_PARSER)><! tree parser would already have imported !> 33 import org.antlr.runtime.tree.*;<\n> 34 <endif> 35 >> 36 37 @genericParser.members() ::= << 38 <@super.members()> 39 <parserMembers()> 40 >> 41 42 /** Add an adaptor property that knows how to build trees */ 43 parserMembers() ::= << 44 protected var adaptor:TreeAdaptor = new CommonTreeAdaptor();<\n> 45 override public function set treeAdaptor(adaptor:TreeAdaptor):void { 46 this.adaptor = adaptor; 47 <grammar.directDelegates:{g|<g:delegateName()>.treeAdaptor = this.adaptor;}> 48 } 49 override public function get treeAdaptor():TreeAdaptor { 50 return adaptor; 51 } 52 >> 53 54 @returnScope.ruleReturnMembers() ::= << 55 <ASTLabelType> tree; 56 public function get tree():Object { return tree; } 57 >> 58 59 /** Add a variable to track rule's return AST */ 60 ruleDeclarations() ::= << 61 <super.ruleDeclarations()> 62 var root_0:<ASTLabelType> = null;<\n> 63 >> 64 65 ruleLabelDefs() ::= << 66 <super.ruleLabelDefs()> 67 <[ruleDescriptor.tokenLabels,ruleDescriptor.wildcardTreeLabels, 68 ruleDescriptor.wildcardTreeListLabels]:{var <it.label.text>_tree:<ASTLabelType>=null;}; separator="\n"> 69 <ruleDescriptor.tokenListLabels:{var <it.label.text>_tree:<ASTLabelType>=null;}; separator="\n"> 70 <ruleDescriptor.allTokenRefsInAltsWithRewrites 71 :{var stream_<it>:RewriteRule<rewriteElementType>Stream=new RewriteRule<rewriteElementType>Stream(adaptor,"token <it>");}; separator="\n"> 72 <ruleDescriptor.allRuleRefsInAltsWithRewrites 73 :{var stream_<it>:RewriteRuleSubtreeStream=new RewriteRuleSubtreeStream(adaptor,"rule <it>");}; separator="\n"> 74 >> 75 76 /** When doing auto AST construction, we must define some variables; 77 * These should be turned off if doing rewrites. This must be a "mode" 78 * as a rule could have both rewrite and AST within the same alternative 79 * block. 80 */ 81 @alt.declarations() ::= << 82 <if(autoAST)> 83 <if(outerAlt)> 84 <if(!rewriteMode)> 85 root_0 = <ASTLabelType>(adaptor.nil());<\n> 86 <endif> 87 <endif> 88 <endif> 89 >> 90 91 // T r a c k i n g R u l e E l e m e n t s 92 93 /** ID and track it for use in a rewrite rule */ 94 tokenRefTrack(token,label,elementIndex,terminalOptions) ::= << 95 <tokenRefBang(...)> <! Track implies no auto AST construction!> 96 <if(backtracking)>if ( <actions.(actionScope).synpredgate> ) <endif>stream_<token>.add(<label>);<\n> 97 >> 98 99 /** ids+=ID and track it for use in a rewrite rule; adds to ids *and* 100 * to the tracking list stream_ID for use in the rewrite. 101 */ 102 tokenRefTrackAndListLabel(token,label,elementIndex,terminalOptions) ::= << 103 <tokenRefTrack(...)> 104 <listLabel(elem=label,...)> 105 >> 106 107 /** ^(ID ...) track for rewrite */ 108 tokenRefRuleRootTrack(token,label,elementIndex,terminalOptions) ::= << 109 <tokenRefBang(...)> 110 <if(backtracking)>if ( <actions.(actionScope).synpredgate> ) <endif>stream_<token>.add(<label>);<\n> 111 >> 112 113 /** Match ^(label+=TOKEN ...) track for rewrite */ 114 tokenRefRuleRootTrackAndListLabel(token,label,elementIndex,terminalOptions) ::= << 115 <tokenRefRuleRootTrack(...)> 116 <listLabel(elem=label,...)> 117 >> 118 119 /** rule when output=AST and tracking for rewrite */ 120 ruleRefTrack(rule,label,elementIndex,args,scope) ::= << 121 <super.ruleRef(...)> 122 <if(backtracking)>if ( <actions.(actionScope).synpredgate> ) <endif>stream_<rule.name>.add(<label>.tree); 123 >> 124 125 /** x+=rule when output=AST and tracking for rewrite */ 126 ruleRefTrackAndListLabel(rule,label,elementIndex,args,scope) ::= << 127 <ruleRefTrack(...)> 128 <listLabel(elem=label+".tree",...)> 129 >> 130 131 /** ^(rule ...) rewrite */ 132 ruleRefRuleRootTrack(rule,label,elementIndex,args,scope) ::= << 133 <ruleRefRuleRoot(...)> 134 <if(backtracking)>if ( <actions.(actionScope).synpredgate> ) <endif>stream_<rule>.add(<label>.tree); 135 >> 136 137 /** ^(x+=rule ...) rewrite */ 138 ruleRefRuleRootTrackAndListLabel(rule,label,elementIndex,args,scope) ::= << 139 <ruleRefRuleRootTrack(...)> 140 <listLabel(elem=label+".tree",...)> 141 >> 142 143 // R e w r i t e 144 145 rewriteCode( 146 alts, description, 147 referencedElementsDeep, // ALL referenced elements to right of -> 148 referencedTokenLabels, 149 referencedTokenListLabels, 150 referencedRuleLabels, 151 referencedRuleListLabels, 152 referencedWildcardLabels, 153 referencedWildcardListLabels, 154 rewriteBlockLevel, enclosingTreeLevel, treeLevel) ::= 155 << 156 157 // AST REWRITE 158 // elements: <referencedElementsDeep; separator=", "> 159 // token labels: <referencedTokenLabels; separator=", "> 160 // rule labels: <referencedRuleLabels; separator=", "> 161 // token list labels: <referencedTokenListLabels; separator=", "> 162 // rule list labels: <referencedRuleListLabels; separator=", "> 163 <if(backtracking)> 164 if ( <actions.(actionScope).synpredgate> ) {<\n> 165 <endif> 166 <prevRuleRootRef()>.tree = root_0; 167 <rewriteCodeLabels()> 168 root_0 = <ASTLabelType>(adaptor.nil()); 169 <alts:rewriteAlt(); separator="else "> 170 <! if tree parser and rewrite=true !> 171 <if(TREE_PARSER)> 172 <if(rewriteMode)> 173 <prevRuleRootRef()>.tree = <ASTLabelType>(adaptor.rulePostProcessing(root_0)); 174 input.replaceChildren(adaptor.getParent(retval.start), 175 adaptor.getChildIndex(retval.start), 176 adaptor.getChildIndex(_last), 177 retval.tree); 178 <endif> 179 <endif> 180 <! if parser or tree-parser && rewrite!=true, we need to set result !> 181 <if(!TREE_PARSER)> 182 <prevRuleRootRef()>.tree = root_0; 183 <else> 184 <if(!rewriteMode)> 185 <prevRuleRootRef()>.tree = root_0; 186 <endif> 187 <endif> 188 <if(backtracking)> 189 } 190 <endif> 191 >> 192 193 rewriteCodeLabels() ::= << 194 <referencedTokenLabels 195 :{var stream_<it>:RewriteRule<rewriteElementType>Stream=new RewriteRule<rewriteElementType>Stream(adaptor,"token <it>",<it>);}; 196 separator="\n" 197 > 198 <referencedTokenListLabels 199 :{var stream_<it>:RewriteRule<rewriteElementType>Stream=new RewriteRule<rewriteElementType>Stream(adaptor,"token <it>", list_<it>);}; 200 separator="\n" 201 > 202 <referencedWildcardLabels 203 :{var stream_<it>:RewriteRuleSubtreeStream=new RewriteRuleSubtreeStream(adaptor,"wildcard <it>",<it>);}; 204 separator="\n" 205 > 206 <referencedWildcardListLabels 207 :{var stream_<it>:RewriteRuleSubtreeStream=new RewriteRuleSubtreeStream(adaptor,"wildcard <it>",list_<it>);}; 208 separator="\n" 209 > 210 <referencedRuleLabels 211 :{var stream_<it>:RewriteRuleSubtreeStream=new RewriteRuleSubtreeStream(adaptor,"rule <it>",<it>!=null?<it>.tree:null);}; 212 separator="\n" 213 > 214 <referencedRuleListLabels 215 :{var stream_<it>:RewriteRuleSubtreeStream=new RewriteRuleSubtreeStream(adaptor,"rule <it>",list_<it>);}; 216 separator="\n" 217 > 218 >> 219 220 /** Generate code for an optional rewrite block; note it uses the deep ref'd element 221 * list rather shallow like other blocks. 222 */ 223 rewriteOptionalBlock( 224 alt,rewriteBlockLevel, 225 referencedElementsDeep, // all nested refs 226 referencedElements, // elements in immediately block; no nested blocks 227 description) ::= 228 << 229 // <fileName>:<description> 230 if ( <referencedElementsDeep:{el | stream_<el>.hasNext}; separator="||"> ) { 231 <alt> 232 } 233 <referencedElementsDeep:{el | stream_<el>.reset();<\n>}> 234 >> 235 236 rewriteClosureBlock( 237 alt,rewriteBlockLevel, 238 referencedElementsDeep, // all nested refs 239 referencedElements, // elements in immediately block; no nested blocks 240 description) ::= 241 << 242 // <fileName>:<description> 243 while ( <referencedElements:{el | stream_<el>.hasNext}; separator="||"> ) { 244 <alt> 245 } 246 <referencedElements:{el | stream_<el>.reset();<\n>}> 247 >> 248 249 rewritePositiveClosureBlock( 250 alt,rewriteBlockLevel, 251 referencedElementsDeep, // all nested refs 252 referencedElements, // elements in immediately block; no nested blocks 253 description) ::= 254 << 255 if ( !(<referencedElements:{el | stream_<el>.hasNext}; separator="||">) ) { 256 throw new RewriteEarlyExitException(); 257 } 258 while ( <referencedElements:{el | stream_<el>.hasNext}; separator="||"> ) { 259 <alt> 260 } 261 <referencedElements:{el | stream_<el>.reset();<\n>}> 262 >> 263 264 rewriteAlt(a) ::= << 265 // <a.description> 266 <if(a.pred)> 267 if (<a.pred>) { 268 <a.alt> 269 }<\n> 270 <else> 271 { 272 <a.alt> 273 }<\n> 274 <endif> 275 >> 276 277 /** For empty rewrites: "r : ... -> ;" */ 278 rewriteEmptyAlt() ::= "root_0 = null;" 279 280 rewriteTree(root,children,description,enclosingTreeLevel,treeLevel) ::= << 281 // <fileName>:<description> 282 { 283 var root_<treeLevel>:<ASTLabelType> = <ASTLabelType>(adaptor.nil()); 284 <root:rewriteElement()> 285 <children:rewriteElement()> 286 adaptor.addChild(root_<enclosingTreeLevel>, root_<treeLevel>); 287 }<\n> 288 >> 289 290 rewriteElementList(elements) ::= "<elements:rewriteElement()>" 291 292 rewriteElement(e) ::= << 293 <@pregen()> 294 <e.el> 295 >> 296 297 /** Gen ID or ID[args] */ 298 rewriteTokenRef(token,elementIndex,terminalOptions,args) ::= << 299 adaptor.addChild(root_<treeLevel>, <createRewriteNodeFromElement(...)>);<\n> 300 >> 301 302 /** Gen $label ... where defined via label=ID */ 303 rewriteTokenLabelRef(label,elementIndex) ::= << 304 adaptor.addChild(root_<treeLevel>, stream_<label>.nextNode());<\n> 305 >> 306 307 /** Gen $label ... where defined via label+=ID */ 308 rewriteTokenListLabelRef(label,elementIndex) ::= << 309 adaptor.addChild(root_<treeLevel>, stream_<label>.nextNode());<\n> 310 >> 311 312 /** Gen ^($label ...) */ 313 rewriteTokenLabelRefRoot(label,elementIndex) ::= << 314 root_<treeLevel> = <ASTLabelType>(adaptor.becomeRoot(stream_<label>.nextNode(), root_<treeLevel>));<\n> 315 >> 316 317 /** Gen ^($label ...) where label+=... */ 318 rewriteTokenListLabelRefRoot ::= rewriteTokenLabelRefRoot 319 320 /** Gen ^(ID ...) or ^(ID[args] ...) */ 321 rewriteTokenRefRoot(token,elementIndex,terminalOptions,args) ::= << 322 root_<treeLevel> = <ASTLabelType>(adaptor.becomeRoot(<createRewriteNodeFromElement(...)>, root_<treeLevel>));<\n> 323 >> 324 325 rewriteImaginaryTokenRef(args,token,terminalOptions,elementIndex) ::= << 326 adaptor.addChild(root_<treeLevel>, <createImaginaryNode(tokenType=token, ...)>);<\n> 327 >> 328 329 rewriteImaginaryTokenRefRoot(args,token,terminalOptions,elementIndex) ::= << 330 root_<treeLevel> = <ASTLabelType>(adaptor.becomeRoot(<createImaginaryNode(tokenType=token, ...)>, root_<treeLevel>));<\n> 331 >> 332 333 /** plain -> {foo} action */ 334 rewriteAction(action) ::= << 335 root_0 = <action>;<\n> 336 >> 337 338 /** What is the name of the previous value of this rule's root tree? This 339 * let's us refer to $rule to mean previous value. I am reusing the 340 * variable 'tree' sitting in retval struct to hold the value of root_0 right 341 * before I set it during rewrites. The assign will be to retval.tree. 342 */ 343 prevRuleRootRef() ::= "retval" 344 345 rewriteRuleRef(rule) ::= << 346 adaptor.addChild(root_<treeLevel>, stream_<rule>.nextTree());<\n> 347 >> 348 349 rewriteRuleRefRoot(rule) ::= << 350 root_<treeLevel> = <ASTLabelType>(adaptor.becomeRoot(stream_<rule>.nextNode(), root_<treeLevel>));<\n> 351 >> 352 353 rewriteNodeAction(action) ::= << 354 adaptor.addChild(root_<treeLevel>, <action>);<\n> 355 >> 356 357 rewriteNodeActionRoot(action) ::= << 358 root_<treeLevel> = <ASTLabelType>(adaptor.becomeRoot(<action>, root_<treeLevel>));<\n> 359 >> 360 361 /** Gen $ruleLabel ... where defined via ruleLabel=rule */ 362 rewriteRuleLabelRef(label) ::= << 363 adaptor.addChild(root_<treeLevel>, stream_<label>.nextTree());<\n> 364 >> 365 366 /** Gen $ruleLabel ... where defined via ruleLabel+=rule */ 367 rewriteRuleListLabelRef(label) ::= << 368 adaptor.addChild(root_<treeLevel>, stream_<label>.nextTree());<\n> 369 >> 370 371 /** Gen ^($ruleLabel ...) where ruleLabel=rule */ 372 rewriteRuleLabelRefRoot(label) ::= << 373 root_<treeLevel> = <ASTLabelType>(adaptor.becomeRoot(stream_<label>.nextNode(), root_<treeLevel>));<\n> 374 >> 375 376 /** Gen ^($ruleLabel ...) where ruleLabel+=rule */ 377 rewriteRuleListLabelRefRoot(label) ::= << 378 root_<treeLevel> = <ASTLabelType>(adaptor.becomeRoot(stream_<label>.nextNode(), root_<treeLevel>));<\n> 379 >> 380 381 rewriteWildcardLabelRef(label) ::= << 382 adaptor.addChild(root_<treeLevel>, stream_<label>.nextTree());<\n> 383 >> 384 385 createImaginaryNode(tokenType,terminalOptions,args) ::= << 386 <if(terminalOptions.node)> 387 <! new MethodNode(IDLabel, args) !> 388 new <terminalOptions.node>(<tokenType><if(args)>, <args; separator=", "><endif>) 389 <else> 390 <ASTLabelType>(adaptor.create(<tokenType>, <args; separator=", "><if(!args)>"<tokenType>"<endif>)) 391 <endif> 392 >> 393 394 createRewriteNodeFromElement(token,terminalOptions,args) ::= << 395 <if(terminalOptions.node)> 396 new <terminalOptions.node>(stream_<token>.nextToken()<if(args)>, <args; separator=", "><endif>) 397 <else> 398 <if(args)> <! must create new node from old !> 399 adaptor.create(<token>, <args; separator=", ">) 400 <else> 401 stream_<token>.nextNode() 402 <endif> 403 <endif> 404 >> 405