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 
     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