AST.stg revision 324c4644fee44b9898524c09511bd33c3f12e2df
1/* 2 [The "BSD license"] 3 Copyright (c) 2006, 2007 Kay Roepke 2010 Alan Condit 4 All rights reserved. 5 6 Redistribution and use in source and binary forms, with or without 7 modification, are permitted provided that the following conditions 8 are met: 9 1. Redistributions of source code must retain the above copyright 10 notice, this list of conditions and the following disclaimer. 11 2. Redistributions in binary form must reproduce the above copyright 12 notice, this list of conditions and the following disclaimer in the 13 documentation and/or other materials provided with the distribution. 14 3. The name of the author may not be used to endorse or promote products 15 derived from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27*/ 28@genericParserHeaderFile.memVars() ::= << 29/* AST parserHeaderFile.memVars */ 30NSInteger ruleLevel; 31NSArray *ruleNames; 32<@super.memVars()> /* AST super.memVars */ 33<parserMemVars()> /* AST parserMemVars */ 34>> 35 36@genericParserHeaderFile.properties() ::= << 37/* AST parserHeaderFile.properties */ 38<@super.properties()> /* AST super.properties */ 39<parserProperties()> /* AST parserproperties */ 40>> 41 42@genericParserHeaderFile.methodsDecl() ::= << 43/* AST parserHeaderFile.methodsDecl */ 44<@super.methodsDecl()> /* AST super.methodsDecl */ 45<parserMethodsDecl()> /* AST parsermethodsDecl */ 46>> 47 48@genericParser.synthesize() ::= << 49/* AST genericParser.synthesize */ 50<@super.synthesize()> 51<parserSynthesize()> 52>> 53 54@genericParser.methods() ::= << 55/* AST genericParser.methods */ 56<@super.methods()> 57<parserMethods()> 58>> 59 60/* additional init code for tree support */ 61@genericParser.init() ::= << 62/* AST genericParser.init */ 63<@super.init()> 64[self setTreeAdaptor:[[ANTLRCommonTreeAdaptor newTreeAdaptor] retain]]; 65>> 66 67@genericParser.dealloc() ::= << 68/* AST genericParser.dealloc */ 69[self setTreeAdaptor:nil]; 70<@super.dealloc()> 71>> 72 73/* Add an adaptor property that knows how to build trees */ 74parserMemVars() ::= << 75/* AST parserMemVars */ 76id\<ANTLRTreeAdaptor> treeAdaptor; 77>> 78 79/* Add an adaptor property that knows how to build trees */ 80parserProperties() ::= << 81/* AST parserProperties */ 82@property (retain, getter=getTreeAdaptor, setter=setTreeAdaptor:) id\<ANTLRTreeAdaptor> treeAdaptor; 83>> 84 85/** Declaration of additional tree support methods - go in interface of parserHeaderFile() */ 86parserMethodsDecl() ::= << 87/* AST parserMethodsDecl */ 88- (id\<ANTLRTreeAdaptor>) getTreeAdaptor; 89- (void) setTreeAdaptor:(id\<ANTLRTreeAdaptor>)theTreeAdaptor; 90>> 91 92/* Add an adaptor property that knows how to build trees */ 93parserSynthesize() ::= << 94/* AST parserProperties */ 95@synthesize treeAdaptor; 96>> 97 98/** Definition of addition tree support methods - go in implementation of genericParser() */ 99parserMethods() ::= << 100/* AST parserMethods */ 101- (id\<ANTLRTreeAdaptor>) getTreeAdaptor 102{ 103 return treeAdaptor; 104} 105 106- (void) setTreeAdaptor:(id\<ANTLRTreeAdaptor>)aTreeAdaptor 107{ 108 if (aTreeAdaptor != treeAdaptor) { 109 treeAdaptor = aTreeAdaptor; 110 } 111} 112>> 113 114/** addition memVars for returnscopes */ 115@returnScopeInterface.memVars() ::= << 116/* AST returnScopeInterface.memVars */ 117<recognizer.ASTLabelType; null="ANTLRCommonTree"> *tree; 118>> 119 120/** the interface of returnScope properties */ 121@returnScopeInterface.properties() ::= << 122/* AST returnScopeInterface.properties */ 123@property (retain, getter=getTree, setter=setTree:) <recognizer.ASTLabelType; null="ANTLRCommonTree"> *tree; 124>> 125 126/** the interface of returnScope methodsDecl */ 127@returnScopeInterface.methodsDecl() ::= << 128/* AST returnScopeInterface.methodsDecl */ 129- (<recognizer.ASTLabelType; null="ANTLRCommonTree"> *)getTree;<\n> 130- (void) setTree:(<recognizer.ASTLabelType; null="ANTLRCommonTree"> *)aTree;<\n> 131>> 132 133/** the implementation of returnScope synthesize */ 134@returnScopeImplementation.synthesize() ::= << 135/* AST returnScope.synthesize */ 136@synthesize tree; 137>> 138 139/** the implementation of returnScope methods */ 140@returnScopeImplementation.methods() ::= << 141/* AST returnScope.methods */ 142- (<ASTLabelType> *)getTree 143{ 144 return tree; 145} 146 147- (void) setTree:(<ASTLabelType> *)aTree 148{ 149 if (tree != aTree) { 150 if ( tree ) [tree release]; 151 if ( aTree ) [aTree retain]; 152 tree = aTree; 153 } 154} 155 156- (void) dealloc 157{ 158 self.tree = nil; 159 [super dealloc]; 160} 161 162>> 163 164/** Add a variable to track rule's return AST */ 165ruleDeclarations() ::= << 166/* AST ruleDeclarations */ 167<super.ruleDeclarations()> 168<ASTLabelType> *root_0 = nil;<\n> 169>> 170 171ruleLabelDefs() ::= << 172/* AST ruleLabelDefs */ 173<super.ruleLabelDefs()> 174<[ruleDescriptor.tokenLabels,ruleDescriptor.wildcardTreeLabels, 175 ruleDescriptor.wildcardTreeListLabels]:{it | <ASTLabelType> *<it.label.text>_tree=nil;}; separator="\n"> 176<ruleDescriptor.tokenListLabels:{it | <ASTLabelType> *<it.label.text>_tree = nil;}; separator="\n"> 177<ruleDescriptor.allTokenRefsInAltsWithRewrites:{it | ANTLRRewriteRuleTokenStream *stream_<it> = 178 [[ANTLRRewriteRule<rewriteElementType>Stream newANTLRRewriteRule<rewriteElementType>Stream:treeAdaptor 179 description:@"token <it>"] retain];}; separator="\n"> 180<ruleDescriptor.allRuleRefsInAltsWithRewrites:{it | ANTLRRewriteRuleSubtreeStream *stream_<it> = 181 [[ANTLRRewriteRuleSubtreeStream newANTLRRewriteRuleSubtreeStream:treeAdaptor 182 description:@"rule <it>"] retain];}; separator="\n"> 183>> 184 185ruleCleanUp() ::= << 186/* AST ruleCleanUp */ 187<super.ruleCleanUp()> 188<[ruleDescriptor.allTokenRefsInAltsWithRewrites,ruleDescriptor.allRuleRefsInAltsWithRewrites]:{it | [stream_<it> release];}; separator="\n"> 189<! 190<if(ruleDescriptor.hasMultipleReturnValues)> 191<if(backtracking)>if ( state.backtracking == 0 ) {<\n> 192<endif> 193 [<prevRuleRootRef()> setTree:(<ASTLabelType> *)[treeAdaptor rulePostProcessing:root_0]];<\n> 194 [treeAdaptor setTokenBoundaries:[<prevRuleRootRef()> getTree] 195 From:[<prevRuleRootRef()> getStart] 196 To:[<prevRuleRootRef()> getStop]];<\n> 197<if(backtracking)>}<\n> 198<endif> 199<endif> 200[root_0 release]; 201!> 202>> 203 204rewriteCodeLabelsCleanUp() ::= << 205/* AST rewriteCodeLabelsCleanUp */ 206 <referencedTokenLabels:{it | [stream_<it> release];}; separator="\n"> 207 <referencedTokenListLabels:{it | [stream_<it> release];}; separator="\n"> 208 <referencedRuleLabels:{it | [stream_<it> release];}; separator="\n"> 209 <referencedRuleListLabels:{it | [stream_<it> release];}; separator="\n"> 210>> 211 212/** When doing auto AST construction, we must define some variables; 213 * These should be turned off if doing rewrites. This must be a "mode" 214 * as a rule could have both rewrite and AST within the same alternative 215 * block. 216 */ 217@alt.declarations() ::= << 218<if(autoAST)> 219<if(outerAlt)> 220<if(!rewriteMode)> 221root_0 = (<ASTLabelType> *)[[[treeAdaptor class] newEmptyTree] retain];<\n> 222<endif> 223<endif> 224<endif> 225>> 226 227// T r a c k i n g R u l e E l e m e n t s 228 229/** ID and track it for use in a rewrite rule */ 230tokenRefTrack(token,label,elementIndex) ::= << 231<! <super.tokenRef(...)> !> 232<tokenRefBang(...)> <! Track implies no auto AST construction!> 233<if(backtracking)> 234if ( <actions.(actionScope).synpredgate> ) <endif> 235 [stream_<token> addElement:<label>];<\n> 236>> 237 238/** ids+=ID and track it for use in a rewrite rule; adds to ids *and* 239 * to the tracking list stream_ID for use in the rewrite. 240 */ 241tokenRefTrackAndListLabel(token,label,elementIndex) ::= << 242<tokenRefTrack(...)> 243<listLabel(elem=label,...)> 244>> 245 246/** ^(ID ...) track for rewrite */ 247tokenRefRuleRootTrack(token,label,elementIndex) ::= << 248<! <super.tokenRef(...)> !> 249<tokenRefBang(...)> 250<if(backtracking)> 251if ( !<actions.(actionScope).synpredgate> ) <endif> 252 [stream_<token> addElement:<label>];<\n> 253>> 254 255/** Match ^(label+=TOKEN ...) track for rewrite */ 256tokenRefRuleRootTrackAndListLabel(token,label,elementIndex) ::= << 257<tokenRefRuleRootTrack(...)> 258<listLabel(elem=label,...)> 259>> 260 261/** rule when output=AST and tracking for rewrite */ 262ruleRefTrack(rule,label,elementIndex,args,scope) ::= << 263<super.ruleRef(...)> 264<if(backtracking)>if ( <actions.(actionScope).synpredgate> ) <endif> 265[stream_<rule.name> addElement:[<label> getTree]]; 266>> 267 268/** x+=rule when output=AST and tracking for rewrite */ 269ruleRefTrackAndListLabel(rule,label,elementIndex,args,scope) ::= << 270<ruleRefTrack(...)> 271<listLabel(elem={[<label> getTree]},...)> 272>> 273 274/** ^(rule ...) rewrite */ 275ruleRefRuleRootTrack(rule,label,elementIndex,args,scope) ::= << 276<! <super.ruleRefRuleRoot(...)> !> 277<ruleRefRuleRoot(...)> 278<if(backtracking)>if ( <actions.(actionScope).synpredgate> ) <endif> 279 [stream_<rule.name> addElement:[<label> getTree]];<\n> 280>> 281 282/** ^(x+=rule ...) rewrite */ 283ruleRefRuleRootTrackAndListLabel(rule,label,elementIndex,args,scope) ::= << 284<ruleRefRuleRootTrack(...)> 285<listLabel(elem={[<label> getTree]},...)> 286>> 287 288// R e w r i t e 289 290rewriteCode( 291 alts, description, 292 referencedElementsDeep, // ALL referenced elements to right of -> 293 referencedTokenLabels, 294 referencedTokenListLabels, 295 referencedRuleLabels, 296 referencedRuleListLabels, 297 referencedWildcardLabels, 298 referencedWildcardListLabels, 299 rewriteBlockLevel, enclosingTreeLevel, treeLevel) ::= 300<< 301 302// AST REWRITE 303// elements: <referencedElementsDeep; separator=", "> 304// token labels: <referencedTokenLabels; separator=", "> 305// rule labels: <referencedRuleLabels; separator=", "> 306// token list labels: <referencedTokenListLabels; separator=", "> 307// rule list labels: <referencedRuleListLabels; separator=", "> 308// wildcard labels: <[referencedWildcardLabels,referencedWildcardListLabels]; separator=", "> 309<if(backtracking)> 310if ( <actions.(actionScope).synpredgate> ) {<\n> 311<endif> 312<prevRuleRootRef()>.tree = root_0;<\n> 313<rewriteCodeLabels()> 314root_0 = (<ASTLabelType> *)[[[treeAdaptor class] newEmptyTree] retain];<\n> 315<alts:rewriteAlt(); separator="else "> 316<! if tree parser and rewrite=true !> 317<if(TREE_PARSER)> 318<if(rewriteMode)> 319<prevRuleRootRef()>.tree = (<ASTLabelType>)[treeAdaptor rulePostProcessing:root_0]; 320[input replaceChildren:[treeAdaptor getParent:retval.start] 321 From:[treeAdaptor getChildIndex:retval.start] 322 To:[treeAdaptor getChildIndex:_last] 323 With:retval.tree]; 324<endif> 325<endif> 326<! if parser or tree-parser && rewrite!=true, we need to set result !> 327<if(!TREE_PARSER)> 328<prevRuleRootRef()>.tree = root_0;<\n> 329<else> 330<if(!rewriteMode)> 331<prevRuleRootRef()>.tree = root_0;<\n> 332<endif> 333<endif> 334<if(backtracking)> 335} 336<endif> 337>> 338 339rewriteCodeLabels() ::= << 340<referencedTokenLabels 341 :{it | ANTLRRewriteRule<rewriteElementType>Stream *stream_<it> = 342 [[ANTLRRewriteRule<rewriteElementType>Stream newANTLRRewriteRule<rewriteElementType>Stream:treeAdaptor description:@"token <it>" element:<it>] retain];}; 343 separator="\n" 344> 345<referencedTokenListLabels:{it | ANTLRRewriteRule<rewriteElementType>Stream *stream_<it> = 346 [[ANTLRRewriteRule<rewriteElementType>Stream newANTLRRewriteRule<rewriteElementType>Stream:treeAdaptor 347 description:@"token <it>" elements:list_<it>] retain];}; 348 separator="\n" 349> 350<referencedWildcardLabels:{it | RewriteRuleSubtreeStream stream_<it> = 351 [[ANTLRRewriteRuleSubtreeStream newANTLRRewriteRuleSubtreeStream:treeAdaptor 352 description:"wildcard <it>" element:<it>] retain];}; 353 separator="\n" 354> 355<referencedWildcardListLabels:{it | RewriteRuleSubtreeStream stream_<it> = 356 [[ANTLRRewriteRuleSubtreeStream newANTLRRewriteRuleSubtreeStream:treeAdaptor 357 descriptor:"wildcard <it>" elements:list_<it>] retain];}; 358 separator="\n" 359> 360<referencedRuleLabels:{it | ANTLRRewriteRuleSubtreeStream *stream_<it> = 361 [[ANTLRRewriteRuleSubtreeStream newANTLRRewriteRuleSubtreeStream:treeAdaptor 362 description:@"token <it>" element:<it>!=nil?[<it> getTree]:nil] retain];}; 363 separator="\n" 364> 365<referencedRuleListLabels:{it | ANTLRRewriteRuleSubtreeStream *stream_<it> = 366 [[ANTLRRewriteRuleSubtreeStream newANTLRRewriteRuleSubtreeStream:treeAdaptor 367 description:@"token <it>" elements:list_<it>] retain];}; 368 separator="\n" 369> 370>> 371 372/** Generate code for an optional rewrite block; note it uses the deep ref'd element 373 * list rather shallow like other blocks. 374 */ 375rewriteOptionalBlock( 376 alt,rewriteBlockLevel, 377 referencedElementsDeep, // all nested refs 378 referencedElements, // elements in immediately block; no nested blocks 379 description) ::= 380<< 381// <fileName>:<description> 382if ( <referencedElementsDeep:{el | [stream_<el> hasNext]}; separator="||"> ) { 383 <alt> 384} 385<referencedElementsDeep:{el | [stream_<el> reset];<\n>}> 386>> 387 388rewriteClosureBlock( 389 alt,rewriteBlockLevel, 390 referencedElementsDeep, // all nested refs 391 referencedElements, // elements in immediately block; no nested blocks 392 description) ::= 393<< 394// <fileName>:<description> 395while ( <referencedElements:{el | [stream_<el> hasNext]}; separator="||"> ) { 396 <alt> 397} 398<referencedElements:{el | [stream_<el> reset];<\n>}> 399>> 400 401rewritePositiveClosureBlock( 402 alt,rewriteBlockLevel, 403 referencedElementsDeep, // all nested refs 404 referencedElements, // elements in immediately block; no nested blocks 405 description) ::= 406<< 407// <fileName>:<description> 408{ 409if ( !(<referencedElements:{el | [stream_<el> hasNext]}; separator=" || ">) ) { 410 @throw [ANTLRRewriteEarlyExitException newException]; 411} 412while ( <referencedElements:{el | [stream_<el> hasNext]}; separator=" || "> ) { 413 <alt> 414} 415<referencedElements:{el | [stream_<el> reset];<\n>}> 416} 417>> 418 419rewriteAlt(a) ::= << 420// <a.description> 421<if(a.pred)> 422if (<a.pred>) { 423 <a.alt> 424}<\n> 425<else> 426{ 427 <a.alt> 428}<\n> 429<endif> 430>> 431 432/** For empty rewrites: "r : ... -> ;" */ 433rewriteEmptyAlt() ::= "root_0 = nil;" 434 435rewriteTree(root,children,description,enclosingTreeLevel,treeLevel) ::= << 436// <fileName>:<description> 437{ 438 <ASTLabelType> *root_<treeLevel> = (<ASTLabelType> *)[[[treeAdaptor class] newEmptyTree] retain]; 439 <root:rewriteElement()> 440 <children:rewriteElement()> 441 [treeAdaptor addChild:root_<treeLevel> toTree:root_<enclosingTreeLevel>]; 442}<\n> 443>> 444 445rewriteElementList(elements) ::= "<elements:rewriteElement()>" 446 447rewriteElement(e) ::= << 448<@pregen()> 449<e.el> 450>> 451 452/** Gen ID or ID[args] */ 453rewriteTokenRef(token,elementIndex,terminalOptions,args) ::= << 454 // TODO: args: <args; separator=", "> 455[treeAdaptor addChild:<createRewriteNodeFromElement(...)> toTree:root_<treeLevel>];<\n> 456>> 457 458/** Gen $label ... where defined via label=ID */ 459rewriteTokenLabelRef(label,elementIndex) ::= << 460[treeAdaptor addChild:[stream_<label> nextNode] toTree:root_<treeLevel>];<\n> 461>> 462 463/** Gen $label ... where defined via label+=ID */ 464rewriteTokenListLabelRef(label,elementIndex) ::= << 465[treeAdaptor addChild:[stream_<label> nextNode] toTree:root_<treeLevel>];<\n> 466>> 467 468/** Gen ^($label ...) */ 469rewriteTokenLabelRefRoot(label,elementIndex) ::= << 470root_<treeLevel> = (<ASTLabelType> *)[treeAdaptor becomeRoot:[stream_<label> nextNode] old:root_<treeLevel>];<\n> 471>> 472 473/** Gen ^($label ...) where label+=... */ 474rewriteTokenListLabelRefRoot ::= rewriteTokenLabelRefRoot 475 476/** Gen ^(ID ...) or ^(ID[args] ...) */ 477rewriteTokenRefRoot(token,elementIndex,terminalOptions,args) ::= << 478root_<treeLevel> = (<ASTLabelType> *)[treeAdaptor becomeRoot:<createRewriteNodeFromElement(...)> old:root_<treeLevel>];<\n> 479>> 480 481rewriteImaginaryTokenRef(args,token,terminalOptions,elementIndex) ::= << 482[treeAdaptor addChild:<createImaginaryNode(tokenType=token, ...)> toTree:root_<treeLevel>];<\n> 483>> 484 485rewriteImaginaryTokenRefRoot(args,token,terminalOptions,elementIndex) ::= << 486root_<treeLevel> = (<ASTLabelType> *)[treeAdaptor becomeRoot:<createImaginaryNode(tokenType=token, ...)> old:root_<treeLevel>];<\n> 487>> 488 489/** plain -> {foo} action */ 490rewriteAction(action) ::= << 491root_0 = <action>;<\n> 492>> 493 494/** What is the name of the previous value of this rule's root tree? This 495 * let's us refer to $rule to mean previous value. I am reusing the 496 * variable 'tree' sitting in retval struct to hold the value of root_0 right 497 * before I set it during rewrites. The assign will be to retval.tree. 498 */ 499prevRuleRootRef() ::= "retval" 500 501rewriteRuleRef(rule) ::= << 502[treeAdaptor addChild:[stream_<rule> nextTree] toTree:root_<treeLevel>];<\n> 503>> 504 505rewriteRuleRefRoot(rule) ::= << 506root_<treeLevel> = (<ASTLabelType> *)[treeAdaptor becomeRoot:(id\<ANTLRTree>)[stream_<rule> nextNode] old:root_<treeLevel>];<\n> 507>> 508 509rewriteNodeAction(action) ::= << 510[treeAdaptor addChild:<action> toTree:root_<treeLevel>];<\n> 511>> 512 513rewriteNodeActionRoot(action) ::= << 514root_<treeLevel> = (<ASTLabelType> *)[treeAdaptor becomeRoot:<action> old:root_<treeLevel>];<\n> 515>> 516 517/** Gen $ruleLabel ... where defined via ruleLabel=rule */ 518rewriteRuleLabelRef(label) ::= << 519[treeAdaptor addChild:[stream_<label> nextTree] toTree:root_<treeLevel>];<\n> 520>> 521 522/** Gen $ruleLabel ... where defined via ruleLabel+=rule */ 523rewriteRuleListLabelRef(label) ::= << 524[treeAdaptor addChild:[stream_<label> nextTree] toTree:root_<treeLevel>];<\n> 525>> 526 527/** Gen ^($ruleLabel ...) where ruleLabel=rule */ 528rewriteRuleLabelRefRoot(label) ::= << 529root_<treeLevel> = (<ASTLabelType> *)[treeAdaptor becomeRoot:[stream_<label> nextNode] old:root_<treeLevel>];<\n> 530>> 531 532/** Gen ^($ruleLabel ...) where ruleLabel+=rule */ 533rewriteRuleListLabelRefRoot(label) ::= << 534root_<treeLevel> = (<ASTLabelType> *)[treeAdaptor becomeRoot:[stream_<label> nextNode] old:root_<treeLevel>];<\n> 535>> 536 537rewriteWildcardLabelRef(label) ::= << 538[treeAdaptor addChild:[stream_<label> nextTree] toTree:root_<treeLevel>];<\n> 539>> 540 541createImaginaryNode(tokenType,terminalOptions,args) ::= << 542<if(terminalOptions.node)> 543 [<terminalOptions.node> new<terminalOptions.node>:<tokenType> <if(args)>, <args; separator=", "><endif>] 544<else> 545 <if(args)> 546 [[treeAdaptor createTree:<tokenType> <if(first(args))>FromToken:<first(args)><endif> <if(first(rest(args)))>Text:<first(rest(args))><else>Text:@"<tokenType>"<endif>] retain] 547 <else> 548 [[treeAdaptor createTree:<tokenType> Text:@"<tokenType>"] retain] 549 <endif> 550<endif> 551>> 552 553createRewriteNodeFromElement(token,terminalOptions,args) ::= << 554<if(terminalOptions.node)> 555 [<terminalOptions.node> new<terminalOptions.node>:[stream_<token> nextToken]<if(args)>, <args; separator=", "><endif>] 556<else> 557 <if(args)> <! must create new node from old !> 558 [[treeAdaptor createTree:<token> Text:<first(rest(args))> <args; separator=", ">] retain] 559 <else> 560 [stream_<token> nextNode] 561 <endif> 562<endif> 563>> 564