AST.stg revision 324c4644fee44b9898524c09511bd33c3f12e2df
1/* 2 * [The "BSD license"] 3 * Copyright (c) 2011 Terence Parr 4 * All rights reserved. 5 * 6 * Conversion to C#: 7 * Copyright (c) 2011 Sam Harwell, Pixel Mine, Inc. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33@outputFile.imports() ::= << 34<@super.imports()> 35 36<if(!TREE_PARSER)> 37<! tree parser would already have imported !> 38using Antlr.Runtime.Tree; 39using RewriteRuleITokenStream = Antlr.Runtime.Tree.RewriteRuleTokenStream; 40<endif> 41>> 42 43@genericParser.members() ::= << 44<@super.members()> 45<parserMembers()> 46>> 47 48parserCtorBody() ::= << 49<super.parserCtorBody()> 50<treeAdaptorType()> treeAdaptor = default(<treeAdaptorType()>); 51CreateTreeAdaptor(ref treeAdaptor); 52TreeAdaptor = treeAdaptor<if(!actions.(actionScope).treeAdaptorType)> ?? new CommonTreeAdaptor()<endif>; 53>> 54 55/** Add an adaptor property that knows how to build trees */ 56parserMembers() ::= << 57// Implement this function in your helper file to use a custom tree adaptor 58partial void CreateTreeAdaptor(ref <treeAdaptorType()> adaptor); 59 60private <treeAdaptorType()> adaptor; 61 62public <treeAdaptorType()> TreeAdaptor 63{ 64 get 65 { 66 return adaptor; 67 } 68 69 set 70 { 71 this.adaptor = value; 72 <grammar.directDelegates:{g|<g:delegateName()>.TreeAdaptor = this.adaptor;}> 73 } 74} 75>> 76 77treeAdaptorType() ::= << 78<actions.(actionScope).treeAdaptorType; null="ITreeAdaptor"> 79>> 80 81ruleReturnBaseType() ::= <% 82Ast<if(TREE_PARSER)>Tree<else>Parser<endif>RuleReturnScope\<<ASTLabelType>, <labelType>> 83%> 84 85/** Add a variable to track rule's return AST */ 86ruleDeclarations() ::= << 87<super.ruleDeclarations()> 88<ASTLabelType> root_0 = default(<ASTLabelType>);<\n> 89>> 90 91ruleLabelDefs(ruleDescriptor, labelType, ASTLabelType, rewriteElementType) ::= <% 92<super.ruleLabelDefs(...)> 93<if(!ruleDescriptor.isSynPred)> 94<[ruleDescriptor.tokenLabels,ruleDescriptor.wildcardTreeLabels,ruleDescriptor.wildcardTreeListLabels] 95 :{it|<\n><ASTLabelType> <it.label.text>_tree = default(<ASTLabelType>);}> 96<ruleDescriptor.tokenListLabels:{it|<\n><ASTLabelType> <it.label.text>_tree = default(<ASTLabelType>);}> 97<ruleDescriptor.allTokenRefsInAltsWithRewrites 98 :{it|<\n>RewriteRule<rewriteElementType>Stream stream_<it>=new RewriteRule<rewriteElementType>Stream(adaptor,"token <it>");}> 99<ruleDescriptor.allRuleRefsInAltsWithRewrites 100 :{it|<\n>RewriteRuleSubtreeStream stream_<it>=new RewriteRuleSubtreeStream(adaptor,"rule <it>");}> 101<endif> 102%> 103 104/** When doing auto AST construction, we must define some variables; 105 * These should be turned off if doing rewrites. This must be a "mode" 106 * as a rule could have both rewrite and AST within the same alternative 107 * block. 108 */ 109@alt.declarations() ::= << 110<if(autoAST && outerAlt && !rewriteMode && !ruleDescriptor.isSynPred)> 111root_0 = (<ASTLabelType>)adaptor.Nil(); 112<endif> 113>> 114 115// T r a c k i n g R u l e E l e m e n t s 116 117/** ID and track it for use in a rewrite rule */ 118tokenRefTrack(token,label,elementIndex,terminalOptions) ::= << 119<tokenRefBang(...)> <! Track implies no auto AST construction!> 120<if(backtracking)>if (<actions.(actionScope).synpredgate>) <endif>stream_<token>.Add(<label>);<\n> 121>> 122 123/** ids+=ID and track it for use in a rewrite rule; adds to ids *and* 124 * to the tracking list stream_ID for use in the rewrite. 125 */ 126tokenRefTrackAndListLabel(token,label,elementIndex,terminalOptions) ::= << 127<tokenRefTrack(...)> 128<listLabelElem(elem=label,elemType=labelType,...)> 129>> 130 131/** ^(ID ...) track for rewrite */ 132tokenRefRuleRootTrack(token,label,elementIndex,terminalOptions) ::= << 133<tokenRefBang(...)> 134<if(backtracking)>if (<actions.(actionScope).synpredgate>) <endif>stream_<token>.Add(<label>); 135>> 136 137/** Match ^(label+=TOKEN ...) track for rewrite */ 138tokenRefRuleRootTrackAndListLabel(token,label,elementIndex,terminalOptions) ::= << 139<tokenRefRuleRootTrack(...)> 140<listLabelElem(elem=label,elemType=labelType,...)> 141>> 142 143/** rule when output=AST and tracking for rewrite */ 144ruleRefTrack(rule,label,elementIndex,args,scope) ::= << 145<super.ruleRef(...)> 146<if(backtracking)>if (<actions.(actionScope).synpredgate>) <endif>stream_<rule.name>.Add(<label>.Tree); 147>> 148 149/** x+=rule when output=AST and tracking for rewrite */ 150ruleRefTrackAndListLabel(rule,label,elementIndex,args,scope) ::= << 151<ruleRefTrack(...)> 152<listLabelElem(elem={<label>.Tree},elemType=ASTLabelType,...)> 153>> 154 155/** ^(rule ...) rewrite */ 156ruleRefRuleRootTrack(rule,label,elementIndex,args,scope) ::= << 157<ruleRefRuleRoot(...)> 158<if(backtracking)>if (<actions.(actionScope).synpredgate>) <endif>stream_<rule>.Add(<label>.Tree); 159>> 160 161/** ^(x+=rule ...) rewrite */ 162ruleRefRuleRootTrackAndListLabel(rule,label,elementIndex,args,scope) ::= << 163<ruleRefRuleRootTrack(...)> 164<listLabelElem(elem={<label>.Tree},elemType=ASTLabelType,...)> 165>> 166 167// R e w r i t e 168 169rewriteCode( 170 alts, description, 171 referencedElementsDeep, // ALL referenced elements to right of -> 172 referencedTokenLabels, 173 referencedTokenListLabels, 174 referencedRuleLabels, 175 referencedRuleListLabels, 176 referencedWildcardLabels, 177 referencedWildcardListLabels, 178 rewriteBlockLevel, enclosingTreeLevel, treeLevel) ::= << 179<\n>{ 180// AST REWRITE 181// elements: <referencedElementsDeep; separator=", "> 182// token labels: <referencedTokenLabels; separator=", "> 183// rule labels: <referencedRuleLabels; separator=", "> 184// token list labels: <referencedTokenListLabels; separator=", "> 185// rule list labels: <referencedRuleListLabels; separator=", "> 186// wildcard labels: <[referencedWildcardLabels,referencedWildcardListLabels]; separator=", "> 187<if(backtracking)> 188if (<actions.(actionScope).synpredgate>) { 189<endif> 190<prevRuleRootRef()>.Tree = root_0; 191<rewriteCodeLabels()> 192root_0 = (<ASTLabelType>)adaptor.Nil(); 193<alts:rewriteAlt(); separator="else "> 194<! if tree parser and rewrite=true !> 195<if(TREE_PARSER&&rewriteMode)> 196<prevRuleRootRef()>.Tree = (<ASTLabelType>)adaptor.RulePostProcessing(root_0); 197input.ReplaceChildren(adaptor.GetParent(retval.Start), 198 adaptor.GetChildIndex(retval.Start), 199 adaptor.GetChildIndex(_last), 200 retval.Tree); 201<endif> 202<! if parser or tree-parser && rewrite!=true, we need to set result !> 203<if(!TREE_PARSER||!rewriteMode)> 204<prevRuleRootRef()>.Tree = root_0; 205<endif> 206<if(backtracking)> 207} 208<endif> 209} 210 211>> 212 213rewriteCodeLabels() ::= << 214<referencedTokenLabels 215 :{it|RewriteRule<rewriteElementType>Stream stream_<it>=new RewriteRule<rewriteElementType>Stream(adaptor,"token <it>",<it>);}; 216 separator="\n" 217> 218<referencedTokenListLabels 219 :{it|RewriteRule<rewriteElementType>Stream stream_<it>=new RewriteRule<rewriteElementType>Stream(adaptor,"token <it>", list_<it>);}; 220 separator="\n" 221> 222<referencedWildcardLabels 223 :{it|RewriteRuleSubtreeStream stream_<it>=new RewriteRuleSubtreeStream(adaptor,"wildcard <it>",<it>);}; 224 separator="\n" 225> 226<referencedWildcardListLabels 227 :{it|RewriteRuleSubtreeStream stream_<it>=new RewriteRuleSubtreeStream(adaptor,"wildcard <it>",list_<it>);}; 228 separator="\n" 229> 230<referencedRuleLabels 231 :{it|RewriteRuleSubtreeStream stream_<it>=new RewriteRuleSubtreeStream(adaptor,"rule <it>",<it>!=null?<it>.Tree:null);}; 232 separator="\n" 233> 234<referencedRuleListLabels 235 :{it|RewriteRuleSubtreeStream stream_<it>=new RewriteRuleSubtreeStream(adaptor,"token <it>",list_<it>);}; 236 separator="\n" 237> 238>> 239 240/** Generate code for an optional rewrite block; note it uses the deep ref'd element 241 * list rather shallow like other blocks. 242 */ 243rewriteOptionalBlock( 244 alt,rewriteBlockLevel, 245 referencedElementsDeep, // all nested refs 246 referencedElements, // elements in immediately block; no nested blocks 247 description) ::= 248<< 249// <fileName>:<description> 250if (<referencedElementsDeep:{el | stream_<el>.HasNext}; separator="||">) 251{ 252 <alt> 253} 254<referencedElementsDeep:{el | stream_<el>.Reset();<\n>}> 255>> 256 257rewriteClosureBlock( 258 alt,rewriteBlockLevel, 259 referencedElementsDeep, // all nested refs 260 referencedElements, // elements in immediately block; no nested blocks 261 description) ::= 262<< 263// <fileName>:<description> 264while ( <referencedElements:{el | stream_<el>.HasNext}; separator="||"> ) 265{ 266 <alt> 267} 268<referencedElements:{el | stream_<el>.Reset();<\n>}> 269>> 270 271rewritePositiveClosureBlock( 272 alt,rewriteBlockLevel, 273 referencedElementsDeep, // all nested refs 274 referencedElements, // elements in immediately block; no nested blocks 275 description) ::= 276<< 277if (!(<referencedElements:{el | stream_<el>.HasNext}; separator="||">)) 278{ 279 throw new RewriteEarlyExitException(); 280} 281while ( <referencedElements:{el | stream_<el>.HasNext}; separator="||"> ) 282{ 283 <alt> 284} 285<referencedElements:{el | stream_<el>.Reset();<\n>}> 286>> 287 288rewriteAlt(a) ::= << 289// <a.description> 290<if(a.pred)> 291if (<a.pred>) 292{ 293 <a.alt> 294} 295<else> 296{ 297 <a.alt> 298} 299<endif> 300>> 301 302/** For empty rewrites: "r : ... -> ;" */ 303rewriteEmptyAlt() ::= "root_0 = null;" 304 305rewriteTree(root,children,description,enclosingTreeLevel,treeLevel) ::= << 306// <fileName>:<description> 307{ 308<ASTLabelType> root_<treeLevel> = (<ASTLabelType>)adaptor.Nil(); 309<root:rewriteElement()> 310<children:rewriteElement()> 311adaptor.AddChild(root_<enclosingTreeLevel>, root_<treeLevel>); 312}<\n> 313>> 314 315rewriteElementList(elements) ::= "<elements:rewriteElement()>" 316 317rewriteElement(e) ::= <% 318<@pregen()> 319DebugLocation(<e.line>, <e.pos>);<\n> 320<e.el> 321%> 322 323/** Gen ID or ID[args] */ 324rewriteTokenRef(token,elementIndex,terminalOptions,args) ::= << 325adaptor.AddChild(root_<treeLevel>, <createRewriteNodeFromElement(...)>);<\n> 326>> 327 328/** Gen $label ... where defined via label=ID */ 329rewriteTokenLabelRef(label,elementIndex) ::= << 330adaptor.AddChild(root_<treeLevel>, stream_<label>.NextNode());<\n> 331>> 332 333/** Gen $label ... where defined via label+=ID */ 334rewriteTokenListLabelRef(label,elementIndex) ::= << 335adaptor.AddChild(root_<treeLevel>, stream_<label>.NextNode());<\n> 336>> 337 338/** Gen ^($label ...) */ 339rewriteTokenLabelRefRoot(label,elementIndex) ::= << 340root_<treeLevel> = (<ASTLabelType>)adaptor.BecomeRoot(stream_<label>.NextNode(), root_<treeLevel>);<\n> 341>> 342 343/** Gen ^($label ...) where label+=... */ 344rewriteTokenListLabelRefRoot ::= rewriteTokenLabelRefRoot 345 346/** Gen ^(ID ...) or ^(ID[args] ...) */ 347rewriteTokenRefRoot(token,elementIndex,terminalOptions,args) ::= << 348root_<treeLevel> = (<ASTLabelType>)adaptor.BecomeRoot(<createRewriteNodeFromElement(...)>, root_<treeLevel>);<\n> 349>> 350 351rewriteImaginaryTokenRef(args,token,terminalOptions,elementIndex) ::= << 352adaptor.AddChild(root_<treeLevel>, <createImaginaryNode(tokenType=token, ...)>);<\n> 353>> 354 355rewriteImaginaryTokenRefRoot(args,token,terminalOptions,elementIndex) ::= << 356root_<treeLevel> = (<ASTLabelType>)adaptor.BecomeRoot(<createImaginaryNode(tokenType=token, ...)>, root_<treeLevel>);<\n> 357>> 358 359/** plain -> {foo} action */ 360rewriteAction(action) ::= << 361root_0 = <action>;<\n> 362>> 363 364/** What is the name of the previous value of this rule's root tree? This 365 * let's us refer to $rule to mean previous value. I am reusing the 366 * variable 'tree' sitting in retval struct to hold the value of root_0 right 367 * before I set it during rewrites. The assign will be to retval.tree. 368 */ 369prevRuleRootRef() ::= "retval" 370 371rewriteRuleRef(rule) ::= << 372adaptor.AddChild(root_<treeLevel>, stream_<rule>.NextTree());<\n> 373>> 374 375rewriteRuleRefRoot(rule) ::= << 376root_<treeLevel> = (<ASTLabelType>)adaptor.BecomeRoot(stream_<rule>.NextNode(), root_<treeLevel>);<\n> 377>> 378 379rewriteNodeAction(action) ::= << 380adaptor.AddChild(root_<treeLevel>, <action>);<\n> 381>> 382 383rewriteNodeActionRoot(action) ::= << 384root_<treeLevel> = (<ASTLabelType>)adaptor.BecomeRoot(<action>, root_<treeLevel>);<\n> 385>> 386 387/** Gen $ruleLabel ... where defined via ruleLabel=rule */ 388rewriteRuleLabelRef(label) ::= << 389adaptor.AddChild(root_<treeLevel>, stream_<label>.NextTree());<\n> 390>> 391 392/** Gen $ruleLabel ... where defined via ruleLabel+=rule */ 393rewriteRuleListLabelRef(label) ::= << 394adaptor.AddChild(root_<treeLevel>, stream_<label>.NextTree());<\n> 395>> 396 397/** Gen ^($ruleLabel ...) where ruleLabel=rule */ 398rewriteRuleLabelRefRoot(label) ::= << 399root_<treeLevel> = (<ASTLabelType>)adaptor.BecomeRoot(stream_<label>.NextNode(), root_<treeLevel>);<\n> 400>> 401 402/** Gen ^($ruleLabel ...) where ruleLabel+=rule */ 403rewriteRuleListLabelRefRoot(label) ::= << 404root_<treeLevel> = (<ASTLabelType>)adaptor.BecomeRoot(stream_<label>.NextNode(), root_<treeLevel>);<\n> 405>> 406 407rewriteWildcardLabelRef(label) ::= << 408adaptor.AddChild(root_<treeLevel>, stream_<label>.NextTree());<\n> 409>> 410 411createImaginaryNode(tokenType,terminalOptions,args) ::= <% 412<if(terminalOptions.node)> 413<! new MethodNode(IDLabel, args) !> 414new <terminalOptions.node>(<tokenType><if(args)>, <args; separator=", "><endif>) 415<else> 416(<ASTLabelType>)adaptor.Create(<tokenType>, <args; separator=", "><if(!args)>"<tokenType>"<endif>) 417<endif> 418%> 419 420createRewriteNodeFromElement(token,terminalOptions,args) ::= <% 421<if(terminalOptions.node)> 422new <terminalOptions.node>(stream_<token>.NextToken()<if(args)>, <args; separator=", "><endif>) 423<else> 424<if(args)> <! must create new node from old !> 425adaptor.Create(<token>, <args; separator=", ">) 426<else> 427stream_<token>.NextNode() 428<endif> 429<endif> 430%> 431