/*
 [The "BSD license"]
 Copyright (c) 2005-2006 Terence Parr
 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.
*/

finishedBacktracking(block) ::= <<
<if(backtracking)>
if <actions.(actionScope).synpredgate>:
    <block>
<else>
<block>
<endif>
>>

@outputFile.imports() ::= <<
<@super.imports()>
<if(!TREE_PARSER)><! tree parser would already have imported !>
from antlr3.tree import *<\n>
<endif>
>>

/** Add an adaptor property that knows how to build trees */
@genericParser.init() ::= <<
self._adaptor = None
self.adaptor = CommonTreeAdaptor()
<@super.init()>
>>

@genericParser.members() ::= <<
<@super.members()>
<astAccessor()>
>>

astAccessor() ::= <<
def getTreeAdaptor(self):
    return self._adaptor

def setTreeAdaptor(self, adaptor):
    self._adaptor = adaptor
    <grammar.directDelegates:{g|<g:delegateName()>.adaptor = adaptor}; separator="\n">

adaptor = property(getTreeAdaptor, setTreeAdaptor)
>>

@returnScope.ruleReturnInit() ::= <<
self.tree = None
>>


/** Add a variable to track rule's return AST */
ruleDeclarations() ::= <<
<super.ruleDeclarations()>
root_0 = None<\n>
>>

ruleLabelDefs() ::= <<
<super.ruleLabelDefs()>
<[ruleDescriptor.tokenLabels,ruleDescriptor.wildcardTreeLabels,
  ruleDescriptor.wildcardTreeListLabels]
    :{it | <it.label.text>_tree = None}; separator="\n">
<ruleDescriptor.tokenListLabels:{it | <it.label.text>_tree = None}; separator="\n">
<ruleDescriptor.allTokenRefsInAltsWithRewrites
    :{it | stream_<it> = RewriteRule<rewriteElementType>Stream(self._adaptor, "token <it>")}; separator="\n">
<ruleDescriptor.allRuleRefsInAltsWithRewrites
    :{it | stream_<it> = RewriteRuleSubtreeStream(self._adaptor, "rule <it>")}; separator="\n">
>>

/** When doing auto AST construction, we must define some variables;
 *  These should be turned off if doing rewrites.  This must be a "mode"
 *  as a rule could have both rewrite and AST within the same alternative
 *  block.
 */
@alt.declarations() ::= <<
<if(autoAST)>
<if(outerAlt)>
<if(!rewriteMode)>
root_0 = self._adaptor.nil()<\n>
<endif>
<endif>
<endif>
>>


// T r a c k i n g  R u l e  E l e m e n t s

/** ID and track it for use in a rewrite rule */
tokenRefTrack(token,label,elementIndex,terminalOptions) ::= <<
<tokenRefBang(...)> <! Track implies no auto AST construction!>
<finishedBacktracking({stream_<token>.add(<label>)})>
>>

/** ids+=ID and track it for use in a rewrite rule; adds to ids *and*
 *  to the tracking list stream_ID for use in the rewrite.
 */
tokenRefTrackAndListLabel(token,label,elementIndex,terminalOptions) ::= <<
<tokenRefTrack(...)>
<listLabel(elem=label,...)>
>>

/** ^(ID ...) track for rewrite */
tokenRefRuleRootTrack(token,label,elementIndex,terminalOptions) ::= <<
<tokenRefBang(...)>
<finishedBacktracking({stream_<token>.add(<label>)})>
>>

/** Match ^(label+=TOKEN ...) track for rewrite */
tokenRefRuleRootTrackAndListLabel(token,label,elementIndex,terminalOptions) ::= <<
<tokenRefRuleRootTrack(...)>
<listLabel(elem=label,...)>
>>

/** rule when output=AST and tracking for rewrite */
ruleRefTrack(rule,label,elementIndex,args,scope) ::= <<
<super.ruleRef(...)>
<finishedBacktracking({stream_<rule.name>.add(<label>.tree)})>
>>

/** x+=rule when output=AST and tracking for rewrite */
ruleRefTrackAndListLabel(rule,label,elementIndex,args,scope) ::= <<
<ruleRefTrack(...)>
<listLabel(label, {<label>.tree})>
>>

/** ^(rule ...) rewrite */
ruleRefRuleRootTrack(rule,label,elementIndex,args,scope) ::= <<
<ruleRefRuleRoot(...)>
<finishedBacktracking({stream_<rule.name>.add(<label>.tree)})>
>>

/** ^(x+=rule ...) rewrite */
ruleRefRuleRootTrackAndListLabel(rule,label,elementIndex,args,scope) ::= <<
<ruleRefRuleRootTrack(...)>
<listLabel(label, {<label>.tree})>
>>

// R e w r i t e

rewriteCode(
        alts, description,
        referencedElementsDeep, // ALL referenced elements to right of ->
        referencedTokenLabels,
        referencedTokenListLabels,
        referencedRuleLabels,
        referencedRuleListLabels,
        referencedWildcardLabels,
        referencedWildcardListLabels,
        rewriteBlockLevel, enclosingTreeLevel, treeLevel) ::=
<<
# AST Rewrite
# elements: <referencedElementsDeep; separator=", ">
# token labels: <referencedTokenLabels; separator=", ">
# rule labels: <referencedRuleLabels; separator=", ">
# token list labels: <referencedTokenListLabels; separator=", ">
# rule list labels: <referencedRuleListLabels; separator=", ">
# wildcard labels: <[referencedWildcardLabels,referencedWildcardListLabels]; separator=", ">
<finishedBacktracking({
<prevRuleRootRef()>.tree = root_0
<rewriteCodeLabels()>
root_0 = self._adaptor.nil()
<first(alts):rewriteAltFirst(); anchor>

<rest(alts):{a | el<rewriteAltRest(a)>}; anchor, separator="\n\n">

<! if tree parser and rewrite=true !>
<if(TREE_PARSER)>
<if(rewriteMode)>
<prevRuleRootRef()>.tree = self._adaptor.rulePostProcessing(root_0)
self.input.replaceChildren(
    self._adaptor.getParent(retval.start),
    self._adaptor.getChildIndex(retval.start),
    self._adaptor.getChildIndex(_last),
    retval.tree
    )<\n>
<endif>
<endif>

<! if parser or tree-parser and rewrite!=true, we need to set result !>
<if(!TREE_PARSER)>
<prevRuleRootRef()>.tree = root_0<\n>
<else>
<if(!rewriteMode)>
<prevRuleRootRef()>.tree = root_0<\n>
<endif>
<endif>
})>
>>

rewriteCodeLabels() ::= <<
<referencedTokenLabels
    :{it | stream_<it> = RewriteRule<rewriteElementType>Stream(self._adaptor, "token <it>", <it>)};
    separator="\n"
>
<referencedTokenListLabels
    :{it | stream_<it> = RewriteRule<rewriteElementType>Stream(self._adaptor, "token <it>", list_<it>)};
    separator="\n"
>
<referencedWildcardLabels
    :{it | stream_<it> = RewriteRuleSubtreeStream(self._adaptor, "wildcard <it>", <it>)};
    separator="\n"
>
<referencedWildcardListLabels
    :{it | stream_<it> = RewriteRuleSubtreeStream(self._adaptor, "wildcard <it>", list_<it>)};
    separator="\n"
>
<referencedRuleLabels
    :{it |
if <it> is not None:
    stream_<it> = RewriteRuleSubtreeStream(self._adaptor, "rule <it>", <it>.tree)
else:
    stream_<it> = RewriteRuleSubtreeStream(self._adaptor, "token <it>", None)
};
    separator="\n"
>
<referencedRuleListLabels
    :{it| stream_<it> = RewriteRuleSubtreeStream(self._adaptor, "token <it>", list_<it>)};
    separator="\n"
>
>>

/** Generate code for an optional rewrite block; note it uses the deep ref'd element
  *  list rather shallow like other blocks.
  */
rewriteOptionalBlock(
        alt,rewriteBlockLevel,
        referencedElementsDeep, // all nested refs
        referencedElements, // elements in immediately block; no nested blocks
        description) ::=
<<
# <fileName>:<description>
if <referencedElementsDeep:{el | stream_<el>.hasNext()}; separator=" or ">:
    <alt>

<referencedElementsDeep:{el | stream_<el>.reset();<\n>}>
>>

rewriteClosureBlock(
        alt,rewriteBlockLevel,
        referencedElementsDeep, // all nested refs
        referencedElements, // elements in immediately block; no nested blocks
        description) ::=
<<
# <fileName>:<description>
while <referencedElements:{el | stream_<el>.hasNext()}; separator=" or ">:
    <alt>

<referencedElements:{el | stream_<el>.reset();<\n>}>
>>

rewritePositiveClosureBlock(
        alt,rewriteBlockLevel,
        referencedElementsDeep, // all nested refs
        referencedElements, // elements in immediately block; no nested blocks
        description) ::=
<<
# <fileName>:<description>
if not (<referencedElements:{el | stream_<el>.hasNext()}; separator=" or ">):
    raise RewriteEarlyExitException()

while <referencedElements:{el | stream_<el>.hasNext()}; separator=" or ">:
    <alt>

<referencedElements:{el | stream_<el>.reset()<\n>}>
>>

rewriteAltRest(a) ::= <<
<if(a.pred)>if <a.pred>:
    # <a.description>
    <a.alt>
<else>se: <! little hack to get if .. elif .. else block right !>
    # <a.description>
    <a.alt>
<endif>
>>

rewriteAltFirst(a) ::= <<
<if(a.pred)>
if <a.pred>:
    # <a.description>
    <a.alt>
<else>
# <a.description>
<a.alt>
<endif>
>>

/** For empty rewrites: "r : ... -> ;" */
rewriteEmptyAlt() ::= "root_0 = None"

rewriteTree(root,children,description,enclosingTreeLevel,treeLevel) ::= <<
# <fileName>:<description>
root_<treeLevel> = self._adaptor.nil()
<root:rewriteElement()>
<children:rewriteElement()>
self._adaptor.addChild(root_<enclosingTreeLevel>, root_<treeLevel>)<\n>
>>

rewriteElementList(elements) ::= "<elements:rewriteElement()>"

rewriteElement(e) ::= <<
<@pregen><@end>
<e.el>
>>

/** Gen ID or ID[args] */
rewriteTokenRef(token,elementIndex,terminalOptions,args) ::= <<
self._adaptor.addChild(root_<treeLevel>, <createRewriteNodeFromElement(...)>)<\n>
>>

/** Gen $label ... where defined via label=ID */
rewriteTokenLabelRef(label,elementIndex) ::= <<
self._adaptor.addChild(root_<treeLevel>, stream_<label>.nextNode())<\n>
>>

/** Gen $label ... where defined via label+=ID */
rewriteTokenListLabelRef(label,elementIndex) ::= <<
self._adaptor.addChild(root_<treeLevel>, stream_<label>.nextNode())<\n>
>>

/** Gen ^($label ...) */
rewriteTokenLabelRefRoot(label,elementIndex) ::= <<
root_<treeLevel> = self._adaptor.becomeRoot(stream_<label>.nextNode(), root_<treeLevel>)<\n>
>>

/** Gen ^($label ...) where label+=... */
rewriteTokenListLabelRefRoot ::= rewriteTokenLabelRefRoot

/** Gen ^(ID ...) or ^(ID[args] ...) */
rewriteTokenRefRoot(token,elementIndex,terminalOptions,args) ::= <<
root_<treeLevel> = self._adaptor.becomeRoot(<createRewriteNodeFromElement(...)>, root_<treeLevel>)<\n>
>>

rewriteImaginaryTokenRef(args,token,terminalOptions,elementIndex) ::= <<
self._adaptor.addChild(root_<treeLevel>, <createImaginaryNode(token, terminalOptions, args)>)<\n>
>>

rewriteImaginaryTokenRefRoot(args,token,terminalOptions,elementIndex) ::= <<
root_<treeLevel> = self._adaptor.becomeRoot(<createImaginaryNode(token, terminalOptions, args)>, root_<treeLevel>)<\n>
>>

/** plain -> {foo} action */
rewriteAction(action) ::= <<
<!FIXME(96,untested)!>
root_0 = <action><\n>
>>

/** What is the name of the previous value of this rule's root tree?  This
 *  let's us refer to $rule to mean previous value.  I am reusing the
 *  variable 'tree' sitting in retval struct to hold the value of root_0 right
 *  before I set it during rewrites.  The assign will be to retval.tree.
 */
prevRuleRootRef() ::= "retval"

rewriteRuleRef(rule) ::= <<
self._adaptor.addChild(root_<treeLevel>, stream_<rule>.nextTree())<\n>
>>

rewriteRuleRefRoot(rule) ::= <<
root_<treeLevel> = self._adaptor.becomeRoot(stream_<rule>.nextNode(), root_<treeLevel>)<\n>
>>

rewriteNodeAction(action) ::= <<
self._adaptor.addChild(root_<treeLevel>, <action>)<\n>
>>

rewriteNodeActionRoot(action) ::= <<
root_<treeLevel> = self._adaptor.becomeRoot(<action>, root_<treeLevel>)<\n>
>>

/** Gen $ruleLabel ... where defined via ruleLabel=rule */
rewriteRuleLabelRef(label) ::= <<
self._adaptor.addChild(root_<treeLevel>, stream_<label>.nextTree())<\n>
>>

/** Gen $ruleLabel ... where defined via ruleLabel+=rule */
rewriteRuleListLabelRef(label) ::= <<
self._adaptor.addChild(root_<treeLevel>, stream_<label>.nextTree())<\n>
>>

/** Gen ^($ruleLabel ...) where ruleLabel=rule */
rewriteRuleLabelRefRoot(label) ::= <<
root_<treeLevel> = self._adaptor.becomeRoot(stream_<label>.nextNode(), root_<treeLevel>)<\n>
>>

/** Gen ^($ruleLabel ...) where ruleLabel+=rule */
rewriteRuleListLabelRefRoot(label) ::= <<
root_<treeLevel> = self._adaptor.becomeRoot(stream_<label>.nextNode(), root_<treeLevel>)<\n>
>>

rewriteWildcardLabelRef(label) ::= <<
self._adaptor.addChild(root_<treeLevel>, stream_<label>.nextTree())<\n>
>>

createImaginaryNode(tokenType,terminalOptions,args) ::= <<
<if(terminalOptions.node)>
<! new MethodNode(IDLabel, args) !>
<terminalOptions.node>(<tokenType><if(args)>, <args; separator=", "><endif>)
<else>
<if (!args)>self._adaptor.createFromType(<tokenType>, "<tokenType>")
<else>self._adaptor.create(<tokenType>, <args; separator=", ">)
<endif>
<endif>
>>

//<! need to call different adaptor.create*() methods depending of argument count !>
//<if (!args)>self._adaptor.createFromType(<tokenType>, "<tokenType>")
//<else><if (!rest(args))>self._adaptor.createFromType(<tokenType>, <first(args)>)
//<else><if (!rest(rest(args)))>self._adaptor.createFromToken(<tokenType>, <first(args)>, <first(rest(args))>)
//<endif>
//<endif>
//<endif>


createRewriteNodeFromElement(token,terminalOptions,args) ::= <<
<if(terminalOptions.node)>
<terminalOptions.node>(stream_<token>.nextToken()<if(args)>, <args; separator=", "><endif>)
<else>
<if(args)> <! must create new node from old !>
<! need to call different adaptor.create*() methods depending of argument count !>
<if (!args)>self._adaptor.createFromType(<token>, "<token>")
<else><if (!rest(args))>self._adaptor.createFromToken(<token>, <first(args)>)
<else><if (!rest(rest(args)))>self._adaptor.createFromToken(<token>, <first(args)>, <first(rest(args))>)
<endif>
<endif>
<endif>
<else>
stream_<token>.nextNode()
<endif>
<endif>
>>
