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