mirror of
https://github.com/marcin-szczepanski/jFuzzyLogic.git
synced 2024-12-21 17:15:28 +01:00
441 lines
13 KiB
Plaintext
441 lines
13 KiB
Plaintext
|
/*
|
||
|
[The "BSD licence"]
|
||
|
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.
|
||
|
*/
|
||
|
|
||
|
/* in sync with Java/AST.stg revision 36 */
|
||
|
|
||
|
group AST;
|
||
|
|
||
|
finishedBacktracking(block) ::= <<
|
||
|
<if(backtracking)>
|
||
|
if self._state.backtracking == 0:
|
||
|
<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() ::= <<
|
||
|
<@super.init()>
|
||
|
self._adaptor = CommonTreeAdaptor()
|
||
|
>>
|
||
|
|
||
|
@genericParser.members() ::= <<
|
||
|
<@super.members()>
|
||
|
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:{<it.label.text>_tree = None}; separator="\n">
|
||
|
<ruleDescriptor.tokenListLabels:{<it.label.text>_tree = None}; separator="\n">
|
||
|
<ruleDescriptor.allTokenRefsInAltsWithRewrites
|
||
|
:{stream_<it> = RewriteRule<rewriteElementType>Stream(self._adaptor, "token <it>")}; separator="\n">
|
||
|
<ruleDescriptor.allRuleRefsInAltsWithRewrites
|
||
|
:{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,hetero) ::= <<
|
||
|
<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,hetero) ::= <<
|
||
|
<tokenRefTrack(...)>
|
||
|
<listLabel(elem=label,...)>
|
||
|
>>
|
||
|
|
||
|
/** ^(ID ...) track for rewrite */
|
||
|
tokenRefRuleRootTrack(token,label,elementIndex,hetero) ::= <<
|
||
|
<tokenRefBang(...)>
|
||
|
<finishedBacktracking({stream_<token>.add(<label>)})>
|
||
|
>>
|
||
|
|
||
|
/** Match ^(label+=TOKEN ...) track for rewrite */
|
||
|
tokenRefRuleRootTrackAndListLabel(token,label,elementIndex,hetero) ::= <<
|
||
|
<tokenRefRuleRootTrack(...)>
|
||
|
<listLabel(elem=label,...)>
|
||
|
>>
|
||
|
|
||
|
wildcardTrack(label,elementIndex) ::= <<
|
||
|
<super.wildcard(...)>
|
||
|
>>
|
||
|
|
||
|
/** 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(elem=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(elem=label+".tree",...)>
|
||
|
>>
|
||
|
|
||
|
// R e w r i t e
|
||
|
|
||
|
rewriteCode(
|
||
|
alts, description,
|
||
|
referencedElementsDeep, // ALL referenced elements to right of ->
|
||
|
referencedTokenLabels,
|
||
|
referencedTokenListLabels,
|
||
|
referencedRuleLabels,
|
||
|
referencedRuleListLabels,
|
||
|
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=", ">
|
||
|
<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
|
||
|
:{stream_<it> = RewriteRule<rewriteElementType>Stream(self._adaptor, "token <it>", <it>)};
|
||
|
separator="\n"
|
||
|
>
|
||
|
<referencedTokenListLabels
|
||
|
:{stream_<it> = RewriteRule<rewriteElementType>Stream(self._adaptor, "token <it>", list_<it>)};
|
||
|
separator="\n"
|
||
|
>
|
||
|
<referencedRuleLabels
|
||
|
:{
|
||
|
if <it> is not None:
|
||
|
stream_<it> = RewriteRuleSubtreeStream(self._adaptor, "token <it>", <it>.tree)
|
||
|
else:
|
||
|
stream_<it> = RewriteRuleSubtreeStream(self._adaptor, "token <it>", None)
|
||
|
};
|
||
|
separator="\n"
|
||
|
>
|
||
|
<referencedRuleListLabels
|
||
|
:{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()>
|
||
|
<e.el>
|
||
|
>>
|
||
|
|
||
|
/** Gen ID or ID[args] */
|
||
|
rewriteTokenRef(token,elementIndex,hetero,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,hetero,args) ::= <<
|
||
|
root_<treeLevel> = self._adaptor.becomeRoot(<createRewriteNodeFromElement(...)>, root_<treeLevel>)<\n>
|
||
|
>>
|
||
|
|
||
|
rewriteImaginaryTokenRef(args,token,hetero,elementIndex) ::= <<
|
||
|
self._adaptor.addChild(root_<treeLevel>, <createImaginaryNode(tokenType=token, ...)>)<\n>
|
||
|
>>
|
||
|
|
||
|
rewriteImaginaryTokenRefRoot(args,token,hetero,elementIndex) ::= <<
|
||
|
root_<treeLevel> = self._adaptor.becomeRoot(<createImaginaryNode(tokenType=token, ...)>, 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>
|
||
|
>>
|
||
|
|
||
|
createImaginaryNode(tokenType,hetero,args) ::= <<
|
||
|
<if(hetero)>
|
||
|
<! new MethodNode(IDLabel, args) !>
|
||
|
<hetero>(<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,hetero,args) ::= <<
|
||
|
<if(hetero)>
|
||
|
<hetero>(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>
|
||
|
>>
|