| /* |
| [The "BSD license"] |
| Copyright (c) 2008 Erik van Bilsen |
| Copyright (c) 2007-2008 Johannes Luber |
| Copyright (c) 2005-2007 Kunle Odutola |
| Copyright (c) 2005 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. |
| */ |
| group AST; |
| |
| @outputFile.imports() ::= << |
| <@super.imports()><if(!TREE_PARSER)><! tree parser would already have imported !> Antlr.Runtime.Tree,<\n><endif> |
| >> |
| |
| @genericParser.members() ::= << |
| <@super.members()> |
| <parserMembers()> |
| >> |
| |
| @genericParser.membersConstructor() ::= << |
| <@super.membersConstructor()> |
| <parserMembersConstructor()> |
| >> |
| |
| @genericParser.membersImplementation() ::= << |
| <@super.membersImplementation()> |
| <parserMembersImplementation()> |
| >> |
| |
| /** Add an adaptor property that knows how to build trees */ |
| parserMembers() ::= << |
| strict protected |
| FAdaptor: ITreeAdaptor; |
| procedure SetAdaptor(const Value: ITreeAdaptor); |
| property Adaptor: ITreeAdaptor read FAdaptor; |
| public |
| property TreeAdaptor: ITreeAdaptor read FAdaptor write SetAdaptor; |
| |
| >> |
| |
| parserMembersConstructor() ::= << |
| FAdaptor := TCommonTreeAdaptor.Create; |
| >> |
| |
| parserMembersImplementation() ::= << |
| procedure T<grammar.recognizerName>.SetAdaptor(const Value: ITreeAdaptor); |
| begin |
| FAdaptor := Value; |
| <grammar.directDelegates:{g|<g:delegateName()>.TreeAdaptor := FAdaptor;}> |
| end; |
| >> |
| |
| @returnScope.ruleReturnMembers() ::= << |
| function T<grammar.recognizerName>.T<ruleDescriptor:returnStructName()>.GetTree: IANTLRInterface; |
| begin |
| Result := FTree; |
| end; |
| |
| procedure T<grammar.recognizerName>.T<ruleDescriptor:returnStructName()>.SetTree(const Value: IANTLRInterface); |
| begin |
| FTree := Value as I<ASTLabelType>; |
| end; |
| >> |
| |
| @returnScopeDeclaration.ruleReturnMembers() ::= << |
| strict private |
| FTree: I<ASTLabelType>; |
| protected |
| { IRuleReturnScope } |
| function GetTree: IANTLRInterface; override; |
| procedure SetTree(const Value: IANTLRInterface); override; |
| >> |
| |
| /** Add a variable to track rule's return AST */ |
| ruleDeclarations() ::= << |
| <super.ruleDeclarations()> |
| Root[0] := nil;<\n> |
| >> |
| |
| ruleDeclarationVars() ::= << |
| <super.ruleDeclarationVars()> |
| Root: array [0..63] of I<ASTLabelType>; |
| >> |
| |
| ruleLabelDefs() ::= << |
| <super.ruleLabelDefs()> |
| <ruleDescriptor.tokenLabels:{<it.label.text>_tree := nil;}; separator="\n"> |
| <ruleDescriptor.tokenListLabels:{<it.label.text>_tree := nil;}; separator="\n"> |
| <ruleDescriptor.allTokenRefsInAltsWithRewrites:{Locals['Stream_<it>'] := TRewriteRule<rewriteElementType>Stream.Create(Adaptor,'token <it>');}; separator="\n"> |
| <ruleDescriptor.allRuleRefsInAltsWithRewrites:{Locals['Stream_<it>'] := TRewriteRuleSubtreeStream.Create(Adaptor,'rule <it>');}; separator="\n"> |
| >> |
| |
| ruleLabelDefVars() ::= << |
| <super.ruleLabelDefVars()> |
| <ruleDescriptor.tokenLabels:{<it.label.text>_tree: I<ASTLabelType>;}; separator="\n"> |
| <ruleDescriptor.tokenListLabels:{<it.label.text>_tree: I<ASTLabelType>;}; 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] := Adaptor.GetNilNode as I<ASTLabelType>; |
| <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!> |
| <if(backtracking)>if (State.Backtracking = 0) then <endif>(Locals['Stream_<token>'] as IRewriteRuleElementStream).Add(<label>);<\n> |
| >> |
| |
| /** 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(...)> |
| <if(backtracking)>if (State.Backtracking = 0) then <endif>(Locals['Stream_<token>'] as IRewriteRuleElementStream).Add(<label>);<\n> |
| >> |
| |
| /** Match ^(label+=TOKEN ...) track for rewrite */ |
| tokenRefRuleRootTrackAndListLabel(token,label,elementIndex,terminalOptions) ::= << |
| <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(...)> |
| <if(backtracking)>if (State.Backtracking = 0) then <endif>(Locals['Stream_<rule.name>'] as IRewriteRuleElementStream).Add(<label>.Tree);<\n> |
| >> |
| |
| /** 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(...)> |
| <if(backtracking)>if (State.Backtracking = 0) then <endif>(Locals['Stream_<rule>'] as IRewriteRuleElementStream).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, |
| 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=", "> |
| <if(backtracking)> |
| if (State.Backtracking = 0) then |
| begin<\n> |
| <endif> |
| <prevRuleRootRef()>.Tree := Root[0]; |
| <rewriteCodeLabels()> |
| Root[0] := Adaptor.GetNilNode as I<ASTLabelType>; |
| <alts:rewriteAlt(); separator="else "> |
| <! if tree parser and rewrite=true !> |
| <if(TREE_PARSER)> |
| <if(rewriteMode)> |
| <prevRuleRootRef()>.Tree = (<ASTLabelType>)adaptor.rulePostProcessing(root[0]); |
| input.ReplaceChildren(adaptor.GetParent(retval.Start), |
| adaptor.GetChildIndex(retval.Start), |
| adaptor.GetChildIndex(_last), |
| retval.Tree); |
| <endif> |
| <endif> |
| <! if parser or rewrite!=true, we need to set result !> |
| <if(!TREE_PARSER)> |
| <prevRuleRootRef()>.Tree := Root[0];<\n> |
| <endif> |
| <if(!rewriteMode)> |
| <prevRuleRootRef()>.Tree := Root[0];<\n> |
| <endif> |
| <if(backtracking)> |
| end; |
| <endif> |
| >> |
| |
| rewriteCodeLabels() ::= << |
| <referencedTokenLabels |
| :{Locals['Stream_<it>'] := TRewriteRule<rewriteElementType>Stream.Create(Adaptor, 'token <it>', <it>);}; |
| separator="\n" |
| > |
| <referencedTokenListLabels |
| :{Locals['Stream_<it>'] := TRewriteRule<rewriteElementType>Stream.Create(Adaptor,'token <it>', list_<it>);}; |
| separator="\n" |
| > |
| <referencedRuleLabels:{ |
| if Assigned(<it>) then |
| Locals['Stream_<it>'] := TRewriteRuleSubtreeStream.Create(Adaptor, 'token <it>', <it>.Tree) |
| else |
| Locals['Stream_<it>'] := TRewriteRuleSubtreeStream.Create(Adaptor, 'token <it>', nil);}; separator="\n"> |
| <referencedRuleListLabels |
| :{Locals['Stream_<it>'] := TRewriteRuleSubtreeStream.Create(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 | (Locals['Stream_<el>'] as IRewriteRuleElementStream).HasNext}; separator=" or ">) then |
| begin |
| <alt> |
| end; |
| <referencedElementsDeep:{el | (Locals['Stream_<el>'] as IRewriteRuleElementStream).Reset;<\n>}> |
| >> |
| |
| rewriteClosureBlock( |
| alt,rewriteBlockLevel, |
| referencedElementsDeep, // all nested refs |
| referencedElements, // elements in immediately block; no nested blocks |
| description) ::= |
| << |
| (* <fileName>:<description> *) |
| while (<referencedElements:{el | (Locals['Stream_<el>'] as IRewriteRuleElementStream).HasNext}; separator=" or ">) do |
| begin |
| <alt> |
| end; |
| <referencedElements:{el | (Locals['Stream_<el>'] as IRewriteRuleElementStream).Reset();<\n>}> |
| >> |
| |
| rewritePositiveClosureBlock( |
| alt,rewriteBlockLevel, |
| referencedElementsDeep, // all nested refs |
| referencedElements, // elements in immediately block; no nested blocks |
| description) ::= |
| << |
| if (not (<referencedElements:{el | (Locals['Stream_<el>'] as IRewriteRuleElementStream).HasNext}; separator=" or ">)) then |
| raise ERewriteEarlyExitException.Create(''); |
| |
| while (<referencedElements:{el | (Locals['Stream_<el>'] as IRewriteRuleElementStream).HasNext}; separator=" or ">) do |
| begin |
| <alt> |
| end; |
| <referencedElements:{el | (Locals['Stream_<el>'] as IRewriteRuleElementStream).Reset();<\n>}> |
| >> |
| |
| rewriteAlt(a) ::= << |
| (* <a.description> *) |
| <if(a.pred)> |
| if (<a.pred>) then |
| begin |
| <a.alt> |
| end<\n> |
| <else> |
| begin |
| <a.alt> |
| end;<\n> |
| <endif> |
| >> |
| |
| /** For empty rewrites: "r : ... -> ;" */ |
| rewriteEmptyAlt() ::= "Root[0] = null;" |
| |
| rewriteTree(root,children,description,enclosingTreeLevel,treeLevel) ::= << |
| (* <fileName>:<description> *) |
| begin |
| Root[<treeLevel>] := Adaptor.GetNilNode as I<ASTLabelType>; |
| <root:rewriteElement()> |
| <children:rewriteElement()> |
| Adaptor.AddChild(Root[<enclosingTreeLevel>], Root[<treeLevel>]); |
| end;<\n> |
| >> |
| |
| rewriteElementList(elements) ::= "<elements:rewriteElement()>" |
| |
| rewriteElement(e) ::= << |
| <@pregen()> |
| <e.el> |
| >> |
| |
| /** Gen ID or ID[args] */ |
| rewriteTokenRef(token,elementIndex,terminalOptions,args) ::= << |
| Adaptor.AddChild(Root[<treeLevel>], <createRewriteNodeFromElement(...)>);<\n> |
| >> |
| |
| /** Gen $label ... where defined via label=ID */ |
| rewriteTokenLabelRef(label,elementIndex) ::= << |
| Adaptor.AddChild(Root[<treeLevel>], (Locals['Stream_<label>'] as IRewriteRuleElementStream).NextNode());<\n> |
| >> |
| |
| /** Gen $label ... where defined via label+=ID */ |
| rewriteTokenListLabelRef(label,elementIndex) ::= << |
| Adaptor.AddChild(Root[<treeLevel>], (Locals['Stream_<label>'] as IRewriteRuleElementStream).NextNode);<\n> |
| >> |
| |
| /** Gen ^($label ...) */ |
| rewriteTokenLabelRefRoot(label,elementIndex) ::= << |
| Root[<treeLevel>] := Adaptor.BecomeRoot((Locals['Stream_<label>'] as IRewriteRuleElementStream).NextNode(), Root[<treeLevel>]) as I<ASTLabelType>;<\n> |
| >> |
| |
| /** Gen ^($label ...) where label+=... */ |
| rewriteTokenListLabelRefRoot ::= rewriteTokenLabelRefRoot |
| |
| /** Gen ^(ID ...) or ^(ID[args] ...) */ |
| rewriteTokenRefRoot(token,elementIndex,terminalOptions,args) ::= << |
| Root[<treeLevel>] := Adaptor.BecomeRoot(<createRewriteNodeFromElement(...)>, Root[<treeLevel>]) as I<ASTLabelType>;<\n> |
| >> |
| |
| rewriteImaginaryTokenRef(args,token,terminalOptions,elementIndex) ::= << |
| Adaptor.AddChild(Root[<treeLevel>], <createImaginaryNode(tokenType=token, ...)>);<\n> |
| >> |
| |
| rewriteImaginaryTokenRefRoot(args,token,terminalOptions,elementIndex) ::= << |
| Root[<treeLevel>] := Adaptor.BecomeRoot(<createImaginaryNode(tokenType=token, ...)>, Root[<treeLevel>]) as I<ASTLabelType>;<\n> |
| >> |
| |
| /** plain -> {foo} action */ |
| rewriteAction(action) ::= << |
| 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) ::= << |
| Adaptor.AddChild(Root[<treeLevel>], (Locals['Stream_<rule>'] as IRewriteRuleElementStream).NextTree());<\n> |
| >> |
| |
| rewriteRuleRefRoot(rule) ::= << |
| Root[<treeLevel>] := Adaptor.BecomeRoot((Locals['Stream_<rule>'] as IRewriteRuleElementStream).NextNode, Root[<treeLevel>]) as I<ASTLabelType>;<\n> |
| >> |
| |
| rewriteNodeAction(action) ::= << |
| Adaptor.AddChild(Root[<treeLevel>], <action>);<\n> |
| >> |
| |
| rewriteNodeActionRoot(action) ::= << |
| Root[<treeLevel>] := Adaptor.BecomeRoot(<action>, Root[<treeLevel>]) as I<ASTLabelType>;<\n> |
| >> |
| |
| /** Gen $ruleLabel ... where defined via ruleLabel=rule */ |
| rewriteRuleLabelRef(label) ::= << |
| Adaptor.AddChild(Root[<treeLevel>], (Locals['Stream_<label>'] as IRewriteRuleElementStream).NextTree());<\n> |
| >> |
| |
| /** Gen $ruleLabel ... where defined via ruleLabel+=rule */ |
| rewriteRuleListLabelRef(label) ::= << |
| Adaptor.AddChild(Root[<treeLevel>], (Locals['Stream_<label>'] as IRewriteRuleElementStream).NextTree());<\n> |
| >> |
| |
| /** Gen ^($ruleLabel ...) where ruleLabel=rule */ |
| rewriteRuleLabelRefRoot(label) ::= << |
| Root[<treeLevel>] := Adaptor.BecomeRoot((Locals['Stream_<label>'] as IRewriteRuleElementStream).NextNode, Root[<treeLevel>]) as I<ASTLabelType>;<\n> |
| >> |
| |
| /** Gen ^($ruleLabel ...) where ruleLabel+=rule */ |
| rewriteRuleListLabelRefRoot(label) ::= << |
| Root[<treeLevel>] := Adaptor.BecomeRoot((Locals['Stream_<label>'] as IRewriteRuleElementStream).NextNode, Root[<treeLevel>]) as I<ASTLabelType>;<\n> |
| >> |
| |
| createImaginaryNode(tokenType,terminalOptions,args) ::= << |
| <if(terminalOptions.node)> |
| <! new MethodNode(IDLabel, args) !> |
| T<terminalOptions.node>.Create(<tokenType><if(args)>, <args; separator=", "><endif>) |
| <else> |
| Adaptor.CreateNode(<tokenType>, <args; separator=", "><if(!args)>'<tokenType>'<endif>) as I<ASTLabelType> |
| <endif> |
| >> |
| |
| createRewriteNodeFromElement(token,terminalOptions,args) ::= << |
| <if(terminalOptions.node)> |
| T<terminalOptions.node>.Create((Locals['Stream_<token>'] as IRewriteRuleElementStream).NextToken<if(args)>, <args; separator=", "><endif>) |
| <else> |
| <if(args)> <! must create new node from old !> |
| Adaptor.Create(<token>, <args; separator=", ">) |
| <else> |
| (Locals['Stream_<token>'] as IRewriteRuleElementStream).NextNode |
| <endif> |
| <endif> |
| >> |