/*
 * [The "BSD license"]
 * Copyright (c) 2011 Terence Parr
 * All rights reserved.
 *
 * Conversion to C#:
 * Copyright (c) 2011 Sam Harwell, Pixel Mine, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/** Templates for building ASTs during normal parsing.
 *
 *  Deal with many combinations.  Dimensions are:
 *  Auto build or rewrite
 *    no label, label, list label  (label/no-label handled together)
 *    child, root
 *    token, set, rule, wildcard
 *
 *  The situation is not too bad as rewrite (->) usage makes ^ and !
 *  invalid. There is no huge explosion of combinations.
 */

@rule.setErrorReturnValue() ::= <<
retval.Tree = (<ASTLabelType>)adaptor.ErrorNode(input, retval.Start, input.LT(-1), re);
<! System.out.WriteLine("<ruleName> returns "+((CommonTree)retval.tree).toStringTree()); !>
>>

// TOKEN AST STUFF

/** ID and output=AST */
tokenRef(token,label,elementIndex,terminalOptions) ::= <%
<super.tokenRef(...)>
<if(!ruleDescriptor.isSynPred)>
<if(backtracking)><\n>if (state.backtracking == 0) {<endif>
<\n><label>_tree = <createNodeFromToken(...)>;
<\n>adaptor.AddChild(root_0, <label>_tree);
<if(backtracking)><\n>}<endif>
<endif>
%>

/** ID! and output=AST (same as plain tokenRef) */
tokenRefBang(token,label,elementIndex,terminalOptions) ::= "<super.tokenRef(...)>"

/** ID^ and output=AST */
tokenRefRuleRoot(token,label,elementIndex,terminalOptions) ::= <%
<super.tokenRef(...)>
<if(!ruleDescriptor.isSynPred)>
<if(backtracking)><\n>if (<actions.(actionScope).synpredgate>) {<endif>
<\n><label>_tree = <createNodeFromToken(...)>;
<\n>root_0 = (<ASTLabelType>)adaptor.BecomeRoot(<label>_tree, root_0);
<if(backtracking)><\n>}<endif>
<endif>
%>

/** ids+=ID! and output=AST */
tokenRefBangAndListLabel(token,label,elementIndex,terminalOptions) ::= <<
<tokenRefBang(...)>
<listLabelElem(elem=label,elemType=labelType,...)>
>>

/** label+=TOKEN when output=AST but not rewrite alt */
tokenRefAndListLabel(token,label,elementIndex,terminalOptions) ::= <<
<tokenRef(...)>
<listLabelElem(elem=label,elemType=labelType,...)>
>>

/** Match label+=TOKEN^ when output=AST but not rewrite alt */
tokenRefRuleRootAndListLabel(token,label,terminalOptions,elementIndex) ::= <<
<tokenRefRuleRoot(...)>
<listLabelElem(elem=label,elemType=labelType,...)>
>>

// SET AST

// the match set stuff is interesting in that it uses an argument list
// to pass code to the default matchSet; another possible way to alter
// inherited code.  I don't use the region stuff because I need to pass
// different chunks depending on the operator.  I don't like making
// the template name have the operator as the number of templates gets
// large but this is the most flexible--this is as opposed to having
// the code generator call matchSet then add root code or ruleroot code
// plus list label plus ...  The combinations might require complicated
// rather than just added on code.  Investigate that refactoring when
// I have more time.

matchSet(s,label,terminalOptions,elementIndex,postmatchCode) ::= <<
<super.matchSet(postmatchCode={<if(!ruleDescriptor.isSynPred)><if(backtracking)>if (<actions.(actionScope).synpredgate>) <endif>adaptor.AddChild(root_0, <createNodeFromToken(...)>);<endif>}, ...)>
>>

matchRuleBlockSet(s,label,terminalOptions,elementIndex,postmatchCode,treeLevel="0") ::= <<
<matchSet(...)>
>>

matchSetBang(s,label,elementIndex,terminalOptions,postmatchCode) ::= "<super.matchSet(...)>"

// note there is no matchSetTrack because -> rewrites force sets to be
// plain old blocks of alts: (A|B|...|C)

matchSetRuleRoot(s,label,terminalOptions,elementIndex,debug) ::= <<
<if(label)>
<label>=(<labelType>)input.LT(1);
<endif>
<super.matchSet(postmatchCode={<if(!ruleDescriptor.isSynPred)><if(backtracking)>if (<actions.(actionScope).synpredgate>) <endif>root_0 = (<ASTLabelType>)adaptor.BecomeRoot(<createNodeFromToken(...)>, root_0);<endif>}, ...)>
>>

// RULE REF AST

/** rule when output=AST */
ruleRef(rule,label,elementIndex,args,scope) ::= <%
<super.ruleRef(...)>
<if(!ruleDescriptor.isSynPred)>
<\n><if(backtracking)>if (<actions.(actionScope).synpredgate>) <endif>adaptor.AddChild(root_0, <label>.Tree);
<endif>
%>

/** rule! is same as normal rule ref */
ruleRefBang(rule,label,elementIndex,args,scope) ::= "<super.ruleRef(...)>"

/** rule^ */
ruleRefRuleRoot(rule,label,elementIndex,args,scope) ::= <<
<super.ruleRef(...)>
<if(backtracking)>if (<actions.(actionScope).synpredgate>) <endif>root_0 = (<ASTLabelType>)adaptor.BecomeRoot(<label>.Tree, root_0);
>>

/** x+=rule when output=AST */
ruleRefAndListLabel(rule,label,elementIndex,args,scope) ::= <<
<ruleRef(...)>
<listLabelElem(elem={<label>.Tree},elemType=ASTLabelType,...)>
>>

/** x+=rule! when output=AST is a rule ref with list addition */
ruleRefBangAndListLabel(rule,label,elementIndex,args,scope) ::= <<
<ruleRefBang(...)>
<listLabelElem(elem={<label>.Tree},elemType=ASTLabelType,...)>
>>

/** x+=rule^ */
ruleRefRuleRootAndListLabel(rule,label,elementIndex,args,scope) ::= <<
<ruleRefRuleRoot(...)>
<listLabelElem(elem={<label>.Tree},elemType=ASTLabelType,...)>
>>

// WILDCARD AST

wildcard(token,label,elementIndex,terminalOptions) ::= <<
<super.wildcard(...)>
<if(!ruleDescriptor.isSynPred)>
<if(backtracking)>if (<actions.(actionScope).synpredgate>) {<endif>
<label>_tree = (<ASTLabelType>)adaptor.Create(<label>);
adaptor.AddChild(root_0, <label>_tree);
<if(backtracking)>}<endif>
<endif>
>>

wildcardBang(label,elementIndex) ::= "<super.wildcard(...)>"

wildcardRuleRoot(token,label,elementIndex,terminalOptions) ::= <<
<super.wildcard(...)>
<if(!ruleDescriptor.isSynPred)>
<if(backtracking)>if (<actions.(actionScope).synpredgate>) {<endif>
<label>_tree = (<ASTLabelType>)adaptor.Create(<label>);
root_0 = (<ASTLabelType>)adaptor.BecomeRoot(<label>_tree, root_0);
<if(backtracking)>}<endif>
<endif>
>>

createNodeFromToken(label,terminalOptions) ::= <%
<if(terminalOptions.node)>
new <terminalOptions.node>(<if(terminalOptions.type)><terminalOptions.type>,<endif><label><if(terminalOptions.text)>,<terminalOptions.text; format="string"><endif>)
<else>
(<ASTLabelType>)adaptor.Create(<if(terminalOptions.type)><terminalOptions.type>,<endif><label><if(terminalOptions.text)>,<terminalOptions.text; format="string"><endif>)
<endif>
%>

ruleCleanUp() ::= <<
<super.ruleCleanUp()>
<if(backtracking)>if (<actions.(actionScope).synpredgate>) {<endif>
retval.Tree = (<ASTLabelType>)adaptor.RulePostProcessing(root_0);
adaptor.SetTokenBoundaries(retval.Tree, retval.Start, retval.Stop);
<if(backtracking)>}<endif>
>>
