Home | History | Annotate | Download | only in Delphi
      1 /*
      2  [The "BSD license"]
      3  Copyright (c) 2008 Erik van Bilsen
      4  Copyright (c) 2007-2008 Johannes Luber
      5  Copyright (c) 2005-2007 Kunle Odutola
      6  Copyright (c) 2005-2006 Terence Parr
      7  All rights reserved.
      8 
      9  Redistribution and use in source and binary forms, with or without
     10  modification, are permitted provided that the following conditions
     11  are met:
     12  1. Redistributions of source code must retain the above copyright
     13     notice, this list of conditions and the following disclaimer.
     14  2. Redistributions in binary form must reproduce the above copyright
     15     notice, this list of conditions and the following disclaimer in the
     16     documentation and/or other materials provided with the distribution.
     17  3. The name of the author may not be used to endorse or promote products
     18     derived from this software without specific prior written permission.
     19 
     20  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     21  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     22  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     23  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     24  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     25  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     29  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 */
     31 
     32 /** Templates for building ASTs during tree parsing.
     33  *
     34  *  Deal with many combinations.  Dimensions are:
     35  *  Auto build or rewrite
     36  *    no label, label, list label  (label/no-label handled together)
     37  *    child, root
     38  *    token, set, rule, wildcard
     39  *
     40  *  Each combination has its own template except that label/no label
     41  *  is combined into tokenRef, ruleRef, ...
     42  */
     43 group ASTTreeParser;
     44 
     45 /** Add a variable to track last element matched */
     46 ruleDeclarations() ::= <<
     47 <super.ruleDeclarations()>
     48 _First[0] := nil;
     49 _Last := nil;<\n>
     50 >>
     51 
     52 ruleDeclarationVars() ::= <<
     53 <super.ruleDeclarationVars()>
     54 _First, _Save_Last: array [0..63] of I<ASTLabelType>;
     55 _Last: I<ASTLabelType>;
     56 >>
     57 
     58 /** What to emit when there is no rewrite rule.  For auto build
     59  *  mode, does nothing.
     60  */
     61 noRewrite(rewriteBlockLevel, treeLevel) ::= <<
     62 <if(backtracking)>if (State.Backtracking = 0) then
     63 begin<endif>
     64 <if(rewriteMode)>
     65 RetVal.Tree := _First[0] as I<ASTLabelType>;
     66 if (Adaptor.GetParent(RetVal.Tree) \<\> nil) and (Adaptor.IsNil(Adaptor.GetParent(RetVal.Tree))) then
     67   RetVal.Tree := Adaptor.GetParent(RetVal.Tree) as I<ASTLabelType>;
     68 <endif>
     69 <if(backtracking)>end;<endif>
     70 >>
     71 
     72 /** match ^(root children) in tree parser; override here to
     73  *  add tree construction actions.
     74  */
     75 tree(root, actionsAfterRoot, children, nullableChildList,
     76      enclosingTreeLevel, treeLevel) ::= <<
     77 _Last := Input.LT(1) as I<ASTLabelType>;
     78 begin
     79   _Save_Last[<treeLevel>] := _Last;
     80   _First[<treeLevel>] := nil;
     81 <if(!rewriteMode)>
     82   Root[<treeLevel>] := Adaptor.GetNilNode as I<ASTLabelType>;<\n>
     83 <endif>
     84   <root:element()>
     85 <if(rewriteMode)>
     86 <if(backtracking)>if (State.Backtracking = 0) then <endif>
     87 <if(root.el.rule)>
     88   if (_First[<enclosingTreeLevel>] = nil) then _First[<enclosingTreeLevel>] := <root.el.label>.Tree;
     89 <else>
     90   if (_First[<enclosingTreeLevel>] = nil) then _First[<enclosingTreeLevel>] := <root.el.label>;
     91 <endif>
     92 <endif>
     93   <actionsAfterRoot:element()>
     94 <if(nullableChildList)>
     95   if (Input.LA(1) = TToken.DOWN) then
     96   begin
     97     Match(Input, TToken.DOWN, nil); <checkRuleBacktrackFailure()>
     98     <children:element()>
     99     Match(Input, TToken.UP, nil); <checkRuleBacktrackFailure()>
    100   end;
    101 <else>
    102   Match(Input, TToken.DOWN, nil); <checkRuleBacktrackFailure()>
    103   <children:element()>
    104   Match(Input, TToken.UP, nil); <checkRuleBacktrackFailure()>
    105 <endif>
    106 <if(!rewriteMode)>
    107   Adaptor.AddChild(Root[<enclosingTreeLevel>], Root[<treeLevel>]);
    108 <endif>
    109   _Last := _Save_Last[<treeLevel>];
    110 end;<\n>
    111 >>
    112 
    113 // TOKEN AST STUFF
    114 
    115 /** ID! and output=AST (same as plain tokenRef) 'cept add
    116  *  setting of _last
    117  */
    118 tokenRefBang(token,label,elementIndex) ::= <<
    119 _Last := Input.LT(1) as I<ASTLabelType>;
    120 <super.tokenRef(...)>
    121 >>
    122 
    123 /** ID auto construct */
    124 tokenRef(token,label,elementIndex,terminalOptions) ::= <<
    125 _Last := Input.LT(1) as I<ASTLabelType>;
    126 <super.tokenRef(...)>
    127 <if(!rewriteMode)>
    128 <if(backtracking)>
    129 if (State.Backtracking = 0) then
    130 begin<\n>
    131 <endif>
    132 <if(terminalOptions.node)>
    133 <label>_tree := T<terminalOptions.node>.Create(<label>);
    134 <else>
    135 	<label>_tree := Adaptor.DupNode(<label>) as I<ASTLabelType>;
    136 <endif><\n>
    137 	Adaptor.AddChild(Root[<treeLevel>], <label>_tree);
    138 <if(backtracking)>
    139 end;
    140 <endif>
    141 <else> <! rewrite mode !>
    142 <if(backtracking)>if (State.Backtracking = 0) then <endif>
    143 if (_First[<treeLevel>] = nil) then _First[<treeLevel>] := <label>;
    144 <endif>
    145 >>
    146 
    147 /** label+=TOKEN auto construct */
    148 tokenRefAndListLabel(token,label,elementIndex,terminalOptions) ::= <<
    149 <tokenRef(...)>
    150 <listLabel(elem=label,...)>
    151 >>
    152 
    153 /** ^(ID ...) auto construct */
    154 tokenRefRuleRoot(token,label,elementIndex,terminalOptions) ::= <<
    155 _Last := Input.LT(1) as I<ASTLabelType>;
    156 <super.tokenRef(...)>
    157 <if(!rewriteMode)>
    158 <if(backtracking)>
    159 if (State.Backtracking = 0) then
    160 begin
    161 <endif>
    162 <if(terminalOptions.node)>
    163 <label>_tree := T<terminalOptions.node>.Create(<label>);
    164 <else>
    165 	<label>_tree := Adaptor.DupNode(<label>) as I<ASTLabelType>;
    166 <endif><\n>
    167 	Root[<treeLevel>] := Adaptor.BecomeRoot(<label>_tree, Root[<treeLevel>]) as I<ASTLabelType>;
    168 <if(backtracking)>
    169 end;
    170 <endif>
    171 <endif>
    172 >>
    173 
    174 /** Match ^(label+=TOKEN ...) auto construct */
    175 tokenRefRuleRootAndListLabel(token,label,elementIndex,terminalOptions) ::= <<
    176 <tokenRefRuleRoot(...)>
    177 <listLabel(elem=label,...)>
    178 >>
    179 
    180 // SET AST
    181 
    182 matchSet(s,label,terminalOptions,elementIndex,postmatchCode) ::= <<
    183 _Llast := Input.LT(1) as I<ASTLabelType>;
    184 <super.matchSet(..., postmatchCode={
    185 <if(!rewriteMode)>
    186 <if(backtracking)>if (State.Backtracking = 0) then begin <endif>
    187 <if(terminalOptions.node)>
    188 <label>_tree := T<terminalOptions.node>.Create(<label>);
    189 <else>
    190 <label>_tree := Adaptor.DupNode(<label>) as I<ASTLabelType>;
    191 <endif><\n>
    192 Adaptor.AddChild(Root[<treeLevel>], <label>_tree);
    193 <if(backtracking)>end;<endif>
    194 <endif>
    195 }
    196 )>
    197 >>
    198 
    199 matchRuleBlockSet(s,label,terminalOptions,elementIndex,postmatchCode,treeLevel="0") ::= <<
    200 <matchSet(...)>
    201 <noRewrite()> <! set return tree !>
    202 >>
    203 
    204 matchSetBang(s,label,elementIndex,postmatchCode) ::= <<
    205 _Last := Input.LT(1) as I<ASTLabelType>;
    206 <super.matchSet(...)>
    207 >>
    208 
    209 matchSetRuleRoot(s,label,terminalOptions,elementIndex,debug) ::= <<
    210 <super.matchSet(..., postmatchCode={
    211 <if(!rewriteMode)>
    212 <if(backtracking)>if (State.Backtracking = 0) then begin <endif>
    213 <if(terminalOptions.node)>
    214 <label>_tree := T<terminalOptions.node>.Create(<label>);
    215 <else>
    216 <label>_tree := Adaptor.DupNode(<label>) as I<ASTLabelType>;
    217 <endif><\n>
    218 Root[<treeLevel>] := Adaptor.BecomeRoot(<label>_tree, Root[<treeLevel>]) as I<ASTLabelType>;
    219 <if(backtracking)>end;<endif>
    220 <endif>
    221 }
    222 )>
    223 >>
    224 
    225 // RULE REF AST
    226 
    227 /** rule auto construct */
    228 ruleRef(rule,label,elementIndex,args,scope) ::= <<
    229 _Last := Input.LT(1) as I<ASTLabelType>;
    230 <super.ruleRef(...)>
    231 <if(backtracking)>if (State.Backtracking = 0) then <endif>
    232 <if(!rewriteMode)>
    233 Adaptor.AddChild(Root[<treeLevel>], <label>.Tree);
    234 <else> <! rewrite mode !>
    235 if (_First[<treeLevel>] = nil) then _First[<treeLevel>] := <label>.Tree;
    236 <endif>
    237 >>
    238 
    239 /** x+=rule auto construct */
    240 ruleRefAndListLabel(rule,label,elementIndex,args,scope) ::= <<
    241 <ruleRef(...)>
    242 <listLabel(elem=label+".Tree",...)>
    243 >>
    244 
    245 /** ^(rule ...) auto construct */
    246 ruleRefRuleRoot(rule,label,elementIndex,args,scope) ::= <<
    247 _Last := Input.LT(1) as I<ASTLabelType>;
    248 <super.ruleRef(...)>
    249 <if(!rewriteMode)>
    250 <if(backtracking)>if (State.Backtracking = 0) then <endif>Root[<treeLevel>] := Adaptor.BecomeRoot(<label>.Tree, Root[<treeLevel>]) as I<ASTLabelType>;
    251 <endif>
    252 >>
    253 
    254 /** ^(x+=rule ...) auto construct */
    255 ruleRefRuleRootAndListLabel(rule,label,elementIndex,args,scope) ::= <<
    256 <ruleRefRuleRoot(...)>
    257 <listLabel(elem=label+".Tree",...)>
    258 >>
    259 
    260 /** rule when output=AST and tracking for rewrite */
    261 ruleRefTrack(rule,label,elementIndex,args,scope) ::= <<
    262 _Last := Input.LT(1) as I<ASTLabelType>;
    263 <super.ruleRefTrack(...)>
    264 >>
    265 
    266 /** x+=rule when output=AST and tracking for rewrite */
    267 ruleRefTrackAndListLabel(rule,label,elementIndex,args,scope) ::= <<
    268 _Last := Input.LT(1) as I<ASTLabelType>;
    269 <super.ruleRefTrackAndListLabel(...)>
    270 >>
    271 
    272 /** ^(rule ...) rewrite */
    273 ruleRefRuleRootTrack(rule,label,elementIndex,args,scope) ::= <<
    274 _Last := Input.LT(1) as I<ASTLabelType>;
    275 <super.ruleRefRootTrack(...)>
    276 >>
    277 
    278 /** ^(x+=rule ...) rewrite */
    279 ruleRefRuleRootTrackAndListLabel(rule,label,elementIndex,args,scope) ::= <<
    280 _Last := Input.LT(1) as I<ASTLabelType>;
    281 <super.ruleRefRuleRootTrackAndListLabel(...)>
    282 >>
    283 
    284 /** Streams for token refs are tree nodes now; override to
    285  *  change nextToken to nextNode.
    286  */
    287 createRewriteNodeFromElement(token,terminalOptions,scope) ::= <<
    288 <if(terminalOptions.node)>
    289 T<terminalOptions.node>.Create((Locals['Stream_<token>'] as IRewriteRuleElementStream).NextNode)
    290 <else>
    291 (Locals['Stream_<token>'] as IRewriteRuleElementStream).NextNode
    292 <endif>
    293 >>
    294 
    295 ruleCleanUp() ::= <<
    296 <super.ruleCleanUp()>
    297 <if(!rewriteMode)>
    298 <if(backtracking)>
    299 if (State.Backtracking = 0) then
    300 begin<\n>
    301 <endif>
    302 RetVal.Tree := Adaptor.RulePostProcessing(Root[0]) as I<ASTLabelType>;
    303 <if(backtracking)>
    304 end;
    305 <endif>
    306 <endif>
    307 >>
    308