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