Home | History | Annotate | Download | only in ActionScript
      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