1/** Templates for building ASTs during normal parsing. 2 * 3 * Deal with many combinations. Dimensions are: 4 * Auto build or rewrite 5 * no label, label, list label (label/no-label handled together) 6 * child, root 7 * token, set, rule, wildcard 8 * 9 * The situation is not too bad as rewrite (->) usage makes ^ and ! 10 * invalid. There is no huge explosion of combinations. 11 */ 12group ASTParser; 13 14@rule.setErrorReturnValue() ::= << 15retval.tree = this.adaptor.errorNode(this.input, retval.start, this.input.LT(-1), re); 16>> 17 18// TOKEN AST STUFF 19 20/** ID and output=AST */ 21tokenRef(token,label,elementIndex,terminalOptions) ::= << 22<super.tokenRef(...)> 23<if(backtracking)>if ( <actions.(actionScope).synpredgate> ) {<endif> 24<label>_tree = <createNodeFromToken(...)>; 25this.adaptor.addChild(root_0, <label>_tree); 26<if(backtracking)>}<endif> 27>> 28 29/** ID! and output=AST (same as plain tokenRef) */ 30tokenRefBang(token,label,elementIndex) ::= "<super.tokenRef(...)>" 31 32/** ID^ and output=AST */ 33tokenRefRuleRoot(token,label,elementIndex,terminalOptions) ::= << 34<super.tokenRef(...)> 35<if(backtracking)>if ( <actions.(actionScope).synpredgate> ) {<endif> 36<label>_tree = <createNodeFromToken(...)>; 37root_0 = this.adaptor.becomeRoot(<label>_tree, root_0); 38<if(backtracking)>}<endif> 39>> 40 41/** ids+=ID! and output=AST */ 42tokenRefBangAndListLabel(token,label,elementIndex,terminalOptions) ::= << 43<tokenRefBang(...)> 44<listLabel(elem=label,...)> 45>> 46 47/** label+=TOKEN when output=AST but not rewrite alt */ 48tokenRefAndListLabel(token,label,elementIndex,terminalOptions) ::= << 49<tokenRef(...)> 50<listLabel(elem=label,...)> 51>> 52 53/** Match label+=TOKEN^ when output=AST but not rewrite alt */ 54tokenRefRuleRootAndListLabel(token,label,terminalOptions,elementIndex) ::= << 55<tokenRefRuleRoot(...)> 56<listLabel(elem=label,...)> 57>> 58 59// SET AST 60 61// the match set stuff is interesting in that it uses an argument list 62// to pass code to the default matchSet; another possible way to alter 63// inherited code. I don't use the region stuff because I need to pass 64// different chunks depending on the operator. I don't like making 65// the template name have the operator as the number of templates gets 66// large but this is the most flexible--this is as opposed to having 67// the code generator call matchSet then add root code or ruleroot code 68// plus list label plus ... The combinations might require complicated 69// rather than just added on code. Investigate that refactoring when 70// I have more time. 71 72matchSet(s,label,terminalOptions,elementIndex,postmatchCode) ::= << 73<super.matchSet(..., postmatchCode={<if(backtracking)>if ( <actions.(actionScope).synpredgate> ) <endif>this.adaptor.addChild(root_0, <createNodeFromToken(...)>);})> 74>> 75 76matchRuleBlockSet(s,label,terminalOptions,elementIndex,postmatchCode,treeLevel="0") ::= << 77<matchSet(...)> 78>> 79 80matchSetBang(s,label,elementIndex,postmatchCode) ::= "<super.matchSet(...)>" 81 82// note there is no matchSetTrack because -> rewrites force sets to be 83// plain old blocks of alts: (A|B|...|C) 84 85matchSetRuleRoot(s,label,terminalOptions,elementIndex,debug) ::= << 86<if(label)> 87<label>=input.LT(1);<\n> 88<endif> 89<super.matchSet(..., postmatchCode={<if(backtracking)>if ( <actions.(actionScope).synpredgate> ) <endif>root_0 = this.adaptor.becomeRoot(<createNodeFromToken(...)>, root_0);})> 90>> 91 92// RULE REF AST 93 94/** rule when output=AST */ 95ruleRef(rule,label,elementIndex,args,scope) ::= << 96<super.ruleRef(...)> 97<if(backtracking)>if ( <actions.(actionScope).synpredgate> ) <endif>this.adaptor.addChild(root_0, <label>.getTree()); 98>> 99 100/** rule! is same as normal rule ref */ 101ruleRefBang(rule,label,elementIndex,args,scope) ::= "<super.ruleRef(...)>" 102 103/** rule^ */ 104ruleRefRuleRoot(rule,label,elementIndex,args,scope) ::= << 105<super.ruleRef(...)> 106<if(backtracking)>if ( <actions.(actionScope).synpredgate> ) <endif>root_0 = this.adaptor.becomeRoot(<label>.getTree(), root_0); 107>> 108 109/** x+=rule when output=AST */ 110ruleRefAndListLabel(rule,label,elementIndex,args,scope) ::= << 111<ruleRef(...)> 112<listLabel(elem=label+".getTree()",...)> 113>> 114 115/** x+=rule! when output=AST is a rule ref with list addition */ 116ruleRefBangAndListLabel(rule,label,elementIndex,args,scope) ::= << 117<ruleRefBang(...)> 118<listLabel(elem=label+".getTree()",...)> 119>> 120 121/** x+=rule^ */ 122ruleRefRuleRootAndListLabel(rule,label,elementIndex,args,scope) ::= << 123<ruleRefRuleRoot(...)> 124<listLabel(elem=label+".getTree()",...)> 125>> 126 127// WILDCARD AST 128 129wildcard(label,elementIndex) ::= << 130<super.wildcard(...)> 131<if(backtracking)>if ( <actions.(actionScope).synpredgate> ) {<endif> 132<label>_tree = this.adaptor.create(<label>); 133this.adaptor.addChild(root_0, <label>_tree); 134<if(backtracking)>}<endif> 135>> 136 137wildcardBang(label,elementIndex) ::= "<super.wildcard(...)>" 138 139wildcardRuleRoot(label,elementIndex) ::= << 140<super.wildcard(...)> 141<if(backtracking)>if ( <actions.(actionScope).synpredgate> ) {<endif> 142<label>_tree = this.adaptor.create(<label>); 143root_0 = this.adaptor.becomeRoot(<label>_tree, root_0); 144<if(backtracking)>}<endif> 145>> 146 147createNodeFromToken(label,terminalOptions) ::= << 148<if(terminalOptions.node)> 149new <terminalOptions.node>(<label>) <! new MethodNode(IDLabel) !> 150<else> 151this.adaptor.create(<label>) 152<endif> 153>> 154 155ruleCleanUp() ::= << 156<super.ruleCleanUp()> 157<if(backtracking)>if ( <actions.(actionScope).synpredgate> ) {<\n><endif> 158retval.tree = this.adaptor.rulePostProcessing(root_0); 159this.adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); 160<if(backtracking)>}<endif> 161>> 162