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/** Templates for building ASTs during tree parsing. 34 * 35 * Deal with many combinations. Dimensions are: 36 * Auto build or rewrite 37 * no label, label, list label (label/no-label handled together) 38 * child, root 39 * token, set, rule, wildcard 40 * 41 * Each combination has its own template except that label/no label 42 * is combined into tokenRef, ruleRef, ... 43 */ 44 45/** Add a variable to track last element matched */ 46ruleDeclarations() ::= << 47<super.ruleDeclarations()> 48<ASTLabelType> _first_0 = default(<ASTLabelType>); 49<ASTLabelType> _last = default(<ASTLabelType>);<\n> 50>> 51 52/** What to emit when there is no rewrite rule. For auto build 53 * mode, does nothing. 54 */ 55noRewrite(rewriteBlockLevel, treeLevel) ::= << 56<if(backtracking)>if (<actions.(actionScope).synpredgate>) {<endif> 57<if(rewriteMode)> 58retval.Tree = (<ASTLabelType>)_first_0; 59if (adaptor.GetParent(retval.Tree)!=null && adaptor.IsNil(adaptor.GetParent(retval.Tree))) 60 retval.Tree = (<ASTLabelType>)adaptor.GetParent(retval.Tree); 61<endif> 62<if(backtracking)>}<endif> 63>> 64 65/** match ^(root children) in tree parser; override here to 66 * add tree construction actions. 67 */ 68tree(root, actionsAfterRoot, children, nullableChildList, 69 enclosingTreeLevel, treeLevel) ::= << 70_last = (<ASTLabelType>)input.LT(1); 71{ 72<ASTLabelType> _save_last_<treeLevel> = _last; 73<ASTLabelType> _first_<treeLevel> = default(<ASTLabelType>); 74<if(!rewriteMode)> 75<ASTLabelType> root_<treeLevel> = (<ASTLabelType>)adaptor.Nil(); 76<endif> 77<root:element()> 78<if(rewriteMode)> 79<if(backtracking)>if (<actions.(actionScope).synpredgate>)<endif> 80<if(root.el.rule)> 81if (_first_<enclosingTreeLevel> == null) _first_<enclosingTreeLevel> = <root.el.label>.Tree; 82<else> 83if (_first_<enclosingTreeLevel> == null) _first_<enclosingTreeLevel> = <root.el.label>; 84<endif> 85<endif> 86<actionsAfterRoot:element()> 87<if(nullableChildList)> 88if (input.LA(1) == TokenTypes.Down) { 89 Match(input, TokenTypes.Down, null); <checkRuleBacktrackFailure()> 90 <children:element()> 91 Match(input, TokenTypes.Up, null); <checkRuleBacktrackFailure()> 92} 93<else> 94Match(input, TokenTypes.Down, null); <checkRuleBacktrackFailure()> 95<children:element()> 96Match(input, TokenTypes.Up, null); <checkRuleBacktrackFailure()> 97<endif> 98<if(!rewriteMode)> 99adaptor.AddChild(root_<enclosingTreeLevel>, root_<treeLevel>); 100<endif> 101_last = _save_last_<treeLevel>; 102}<\n> 103>> 104 105// TOKEN AST STUFF 106 107/** ID! and output=AST (same as plain tokenRef) 'cept add 108 * setting of _last 109 */ 110tokenRefBang(token,label,elementIndex,terminalOptions) ::= << 111_last = (<ASTLabelType>)input.LT(1); 112<super.tokenRef(...)> 113>> 114 115/** ID auto construct */ 116tokenRef(token,label,elementIndex,terminalOptions) ::= << 117_last = (<ASTLabelType>)input.LT(1); 118<super.tokenRef(...)> 119<if(!rewriteMode)> 120<if(backtracking)>if (<actions.(actionScope).synpredgate>) {<endif> 121<if(terminalOptions.node)> 122<label>_tree = new <terminalOptions.node>(<if(terminalOptions.type)><terminalOptions.type>,<endif><label><if(terminalOptions.text)>,<terminalOptions.text; format="string"><endif>); 123<else> 124<label>_tree = (<ASTLabelType>)adaptor.DupNode(<if(terminalOptions.type)><terminalOptions.type>,<endif><label><if(terminalOptions.text)>,<terminalOptions.text; format="string"><endif>); 125<endif><\n> 126adaptor.AddChild(root_<treeLevel>, <label>_tree); 127<if(backtracking)>}<endif> 128<else> <! rewrite mode !> 129<if(backtracking)>if (<actions.(actionScope).synpredgate>)<endif> 130if (_first_<treeLevel> == null) _first_<treeLevel> = <label>; 131<endif> 132>> 133 134/** label+=TOKEN auto construct */ 135tokenRefAndListLabel(token,label,elementIndex,terminalOptions) ::= << 136<tokenRef(...)> 137<listLabelElem(elem=label,...)> 138>> 139 140/** ^(ID ...) auto construct */ 141tokenRefRuleRoot(token,label,elementIndex,terminalOptions) ::= << 142_last = (<ASTLabelType>)input.LT(1); 143<super.tokenRef(...)> 144<if(!rewriteMode)> 145<if(backtracking)>if (<actions.(actionScope).synpredgate>) {<endif> 146<if(terminalOptions.node)> 147<label>_tree = new <terminalOptions.node>(<if(terminalOptions.type)><terminalOptions.type>,<endif><label><if(terminalOptions.text)>,<terminalOptions.text; format="string"><endif>); 148<else> 149<label>_tree = (<ASTLabelType>)adaptor.DupNode(<if(terminalOptions.type)><terminalOptions.type>,<endif><label><if(terminalOptions.text)>,<terminalOptions.text; format="string"><endif>); 150<endif><\n> 151root_<treeLevel> = (<ASTLabelType>)adaptor.BecomeRoot(<label>_tree, root_<treeLevel>); 152<if(backtracking)>}<endif> 153<endif> 154>> 155 156/** Match ^(label+=TOKEN ...) auto construct */ 157tokenRefRuleRootAndListLabel(token,label,elementIndex,terminalOptions) ::= << 158<tokenRefRuleRoot(...)> 159<listLabelElem(elem=label,...)> 160>> 161 162/** Match . wildcard and auto dup the node/subtree */ 163wildcard(token,label,elementIndex,terminalOptions) ::= << 164_last = (<ASTLabelType>)input.LT(1); 165<super.wildcard(...)> 166<if(!rewriteMode)> 167<if(backtracking)>if (<actions.(actionScope).synpredgate>) {<endif> 168<label>_tree = (<ASTLabelType>)adaptor.DupTree(<label>); 169adaptor.AddChild(root_<treeLevel>, <label>_tree); 170<if(backtracking)>}<endif> 171<else> <! rewrite mode !> 172<if(backtracking)>if (<actions.(actionScope).synpredgate>)<endif> 173if (_first_<treeLevel> == null) _first_<treeLevel> = <label>; 174<endif> 175>> 176 177// SET AST 178 179matchSet(s,label,terminalOptions,elementIndex,postmatchCode) ::= << 180_last = (<ASTLabelType>)input.LT(1); 181<super.matchSet(postmatchCode={ 182<if(!rewriteMode)> 183<if(backtracking)>if (<actions.(actionScope).synpredgate>) {<endif> 184<if(terminalOptions.node)> 185<label>_tree = new <terminalOptions.node>(<if(terminalOptions.type)><terminalOptions.type>,<endif><label><if(terminalOptions.text)>,<terminalOptions.text; format="string"><endif>); 186<else> 187<label>_tree = (<ASTLabelType>)adaptor.DupNode(<if(terminalOptions.type)><terminalOptions.type>,<endif><label><if(terminalOptions.text)>,<terminalOptions.text; format="string"><endif>); 188<endif><\n> 189adaptor.AddChild(root_<treeLevel>, <label>_tree); 190<if(backtracking)>\}<endif> 191<endif> 192}, ... 193)> 194>> 195 196matchRuleBlockSet(s,label,terminalOptions,elementIndex,postmatchCode,treeLevel="0") ::= << 197<matchSet(...)> 198<noRewrite(...)> <! set return tree !> 199>> 200 201matchSetBang(s,label,terminalOptions,elementIndex,postmatchCode) ::= << 202_last = (<ASTLabelType>)input.LT(1); 203<super.matchSet(...)> 204>> 205 206matchSetRuleRoot(s,label,terminalOptions,elementIndex,debug) ::= << 207<super.matchSet(postmatchCode={ 208<if(!rewriteMode)> 209<if(backtracking)>if (<actions.(actionScope).synpredgate>) {<endif> 210<if(terminalOptions.node)> 211<label>_tree = new <terminalOptions.node>(<if(terminalOptions.type)><terminalOptions.type>,<endif><label><if(terminalOptions.text)>,<terminalOptions.text; format="string"><endif>); 212<else> 213<label>_tree = (<ASTLabelType>)adaptor.DupNode(<if(terminalOptions.type)><terminalOptions.type>,<endif><label><if(terminalOptions.text)>,<terminalOptions.text; format="string"><endif>); 214<endif><\n> 215root_<treeLevel> = (<ASTLabelType>)adaptor.BecomeRoot(<label>_tree, root_<treeLevel>); 216<if(backtracking)>\}<endif> 217<endif> 218}, ... 219)> 220>> 221 222// RULE REF AST 223 224/** rule auto construct */ 225ruleRef(rule,label,elementIndex,args,scope) ::= << 226_last = (<ASTLabelType>)input.LT(1); 227<super.ruleRef(...)> 228<if(backtracking)>if (<actions.(actionScope).synpredgate>)<endif> 229<if(!rewriteMode)> 230adaptor.AddChild(root_<treeLevel>, <label>.Tree); 231<else> <! rewrite mode !> 232if (_first_<treeLevel> == null) _first_<treeLevel> = <label>.Tree; 233<endif> 234>> 235 236/** x+=rule auto construct */ 237ruleRefAndListLabel(rule,label,elementIndex,args,scope) ::= << 238<ruleRef(...)> 239<listLabelElem(elem={<label>.Tree},...)> 240>> 241 242/** ^(rule ...) auto construct */ 243ruleRefRuleRoot(rule,label,elementIndex,args,scope) ::= << 244_last = (<ASTLabelType>)input.LT(1); 245<super.ruleRef(...)> 246<if(!rewriteMode)> 247<if(backtracking)>if (<actions.(actionScope).synpredgate>) <endif>root_<treeLevel> = (<ASTLabelType>)adaptor.BecomeRoot(<label>.Tree, root_<treeLevel>); 248<endif> 249>> 250 251/** ^(x+=rule ...) auto construct */ 252ruleRefRuleRootAndListLabel(rule,label,elementIndex,args,scope) ::= << 253<ruleRefRuleRoot(...)> 254<listLabelElem(elem={<label>.Tree},...)> 255>> 256 257/** rule when output=AST and tracking for rewrite */ 258ruleRefTrack(rule,label,elementIndex,args,scope) ::= << 259_last = (<ASTLabelType>)input.LT(1); 260<super.ruleRefTrack(...)> 261>> 262 263/** x+=rule when output=AST and tracking for rewrite */ 264ruleRefTrackAndListLabel(rule,label,elementIndex,args,scope) ::= << 265_last = (<ASTLabelType>)input.LT(1); 266<super.ruleRefTrackAndListLabel(...)> 267>> 268 269/** ^(rule ...) rewrite */ 270ruleRefRuleRootTrack(rule,label,elementIndex,args,scope) ::= << 271_last = (<ASTLabelType>)input.LT(1); 272<super.ruleRefRootTrack(...)> 273>> 274 275/** ^(x+=rule ...) rewrite */ 276ruleRefRuleRootTrackAndListLabel(rule,label,elementIndex,args,scope) ::= << 277_last = (<ASTLabelType>)input.LT(1); 278<super.ruleRefRuleRootTrackAndListLabel(...)> 279>> 280 281/** Streams for token refs are tree nodes now; override to 282 * change NextToken to NextNode. 283 */ 284createRewriteNodeFromElement(token,terminalOptions,args) ::= <% 285<if(terminalOptions.node)> 286new <terminalOptions.node>(<if(terminalOptions.type)><terminalOptions.type>,<endif>stream_<token>.NextNode()) 287<else> 288stream_<token>.NextNode() 289<endif> 290%> 291 292ruleCleanUp() ::= << 293<super.ruleCleanUp()> 294<if(!rewriteMode)> 295<if(backtracking)>if (<actions.(actionScope).synpredgate>) {<endif> 296retval.Tree = (<ASTLabelType>)adaptor.RulePostProcessing(root_0); 297<if(backtracking)>}<endif> 298<endif> 299>> 300