Codebase list stringtemplate / 4780e9a
Update upstream source from tag 'upstream/3.2.1' Update to upstream version '3.2.1' with Debian dir d62a315bf3ef0be33da12677abbee6132e36b283 Emmanuel Bourg 3 years ago
90 changed file(s) with 38034 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 Changes to ST (StringTemplate).
1
2 #### Releases
3
4 3.2.1: September 22, 2009
5
6 3.2: June 11, 2008
7
8 3.1: January 23, 2008
9
10 3.0: September 6, 2006
11
12 2.2: August 5, 2005
13
14 2.1: January 22, 2005
15
16 2.0: July 16, 2004
17
18 1.0.3: Feb 5, 2004
19
20 1.0.2: Oct 14, 2003
21
22 #### Fixed bugs and changes
23
24 09-22-2009 -- 3.2.1 release
25
26 07-11-2009
27
28 o If default arg is a template with single expression wrapped in parens, x={<(...)>},
29 then eval to string rather than setting x to the template for later eval. Useful
30 in rare cases where the expression can change value when you read it, such as
31 accessing time value or random number generator object.
32
33 o Added line break operator <\\>. It consumes remaining whitespace on that line, the first
34 and then any whitespace. Added a number of unit tests. example:
35
36 "foo <\\>
37 bar"
38
39 emits "foo bar". All of the whitespace after the <\\> gets thrown away like a comment.
40
41 07-02-2009
42
43 o IF with false condition results in missing not empty value. So,
44 <names:{n | <if(n.cool)><n><endif>}; separator=",">
45 doesn't emit a separator for non-cool names. See
46 http://www.antlr.org/pipermail/stringtemplate-interest/2009-July/002020.html
47
48 WARNING: You now pay a penalty now for a separator if the iterated value is
49 nullable. Nullable if iterable or a template with nothing buf IF statements.
50 If nullable, ST writes each element to a temp buffer before emitting. Expensive.
51
52 08-13-2008
53
54 o IF conditionals and list elements couldn't use template
55 application. Can do $if(names:{$it$})$Fail!$endif$ and
56 $[names:{$it$!},phones]$ and $[names, ["foo","bar"]:{$it$!},phones]$
57 Can't use IF inside of a [...] because those are expressions not
58 statements.
59
60 08-11-2008
61
62 o Made template output sensitive to the anchor of any enclosing template
63 instances. ST used to ignore anchor unless you had a wrap and now it
64 looks at anchor like an indent; uses widest. ST used to give this:
65
66 { a,
67 { 1,
68 2,
69 3 }
70 , b }
71
72 for these templates where the first was stuck into second
73 <\n>{ <stuff; anchor, separator=",\n"> }<\n>
74 { <values; anchor, separator=", "> }
75
76 but now gives:
77
78 { a,
79 { 1,
80 2,
81 3 }
82 , b };
83
84 see testSubtemplatesAnchorToo()
85
86 o To deal with combined anchors and indentation, force indents to
87 include any current anchor point. Prevents a check later in write
88 to deal with anchors when starting new line. See pushIndentation()
89
90 06-11-2008 -- 3.2 release
91
92 o Fixed ST-36; allow <elseif>
93
94 o Fixed ST-37; chk for null
95
96 06-04-2008
97
98 o Added \r\n normalization in AutoIndentWriter. Converts \r\n or \n
99 to whatever the writer's newline instance var is. wrap="\n" will
100 give the proper newline by locale as will \n and \r\n in the
101 templates or even incoming data attributes (toString()'d of course).
102 Added unit tests. It even works with special literals <\r\n> and <\n>.
103
104 06-03-2008
105
106 o Fixed ST-39; an obscure memory leak issue with embeddedInstances
107
108 06-02-2008
109
110 o rest and strip returned iterators. Made them return show list copies
111 so recursion works. iterators have side-effects. Added 2 unit tests.
112
113 o implemented trunc. returns all but last element.
114
115 o Fix ST-33; [a,b] cat function used iterators; side-effect problem.
116
117 05-07-2008
118
119 o Had a problem with "int" : "0" in a map but ST as incoming lookup key.
120 Decided that I'd lookup as raw object first so Integer lookup works
121 but I try toString version if not found. Document this!
122
123 05-06-2008
124
125 o <aMap.(k)> no longer calls toString() on k.
126 <aMap.keys:{k|<k>:<aMap.(k)>} was not working when aMap had Integer
127 keys. Added unit test.
128
129 04-07-2008
130
131 o Made unit tests not depend on map order. commented out tests that fail.
132
133 02-11-2008
134
135 o debug tags now emit group name with tags. improves debugging ability.
136
137 01-23-2008 -- 3.1 release
138
139 o reader was not closed in PathGroupLoader.
140
141 o removed some counters used to test the efficiency of reflection cache.
142
143 o updated unit tests to work with new improved error messages.
144
145 o $first(list).prop$ is not allowed. Fixed and added a unit test.
146
147 12-29-2007
148
149 o Improved error message for "template not found". Shows template hierarchy
150 now not just context (if any). E.g.,
151 Can't find template noRewrite.st; group hierarchy is [Java]
152
153 12-12-2007
154
155 o allows unicode escapes as expression literals but only if it's the whole
156 expression: <\uFEA5\n\u00C2> Previously could only do one char and just
157 the special ones like <\n>.
158
159 12-11-2007
160
161 o resolve ST-34. Super group loading was not using template lexer
162 (<...> or $...$) according to subclass. Updated group loader interface.
163
164 11-09-2007
165
166 o added elseif. $if(x)$...$elseif(y)$...$else$...$endif$
167
168 o updated some unit tests (names, guts) to make more sense.
169
170 o updated group.g and eval.g so that list literals can have empty
171 atoms like $["a",,"b"]:{n | ...}; null="nullstring"$.
172
173 11-08-2007
174
175 o "default" was not a valid value in map. had testLiterals looking even at strings in lexer for
176 group.g. ST-15
177
178 o ST-18 fixed. put close in a finally block.
179
180 08-30-2007
181
182 o i0 was not set when you applied a template to a single value.
183
184 08-17-2007
185
186 o Thomas Brandon pointed out that we have a bug in our if/else computation.
187 You could not reference super.attr inside the if/else sub templates.
188
189 August 6, 2007: 3.1b1 (starting towards a 3.1)
190
191 05-19-2007
192
193 o changed to 3.1b1 in anticipation of diong a 3.1 release using ANTLR v3.
194
195 05-03-2007
196
197 o Updated group.g to allow default clause by itself in map (from Caleb Lyness)
198
199 o Caleb also revamped entire TestStringTemplate to run under windows.
200
201 o Added 16 bit char unit test also.
202
203 01-30-2007
204
205 o Made convertArrayToList create an ArrayWrappedInList so it doesn't
206 copy arrays any more.
207
208 01-27-2007
209
210 o John Snyders found bug in format stuff. Renderer was being called
211 for string expr options.
212
213 o Another bug fix by John. Length problem.
214
215 ??
216
217 o added format option
218
219 10-30-2006
220
221 o \_ was not allowed in group/interface.g but in group.g. Now \_ is
222 allowed as first char.
223
224 09-25-2006
225
226 o ST.dup() was not copying renderers field.
227
228 September 6 -- 3.0 release
229
230 08-14-2006
231
232 o added toString to Aggregate so that setAttribute("foo.{x,y}", ...) and
233 then referencing foo in isolation prints something useful.
234
235 08-09-2006
236
237 o had to fix that:
238
239 <<
240 InputStream is = cl.getResourceAsStream(fileName);
241 if ( is==null ) {
242 cl = ErrorManager.class.getClassLoader();
243 is = cl.getResourceAsStream(fileName);
244 }
245 >>
246
247 08-07-2006
248
249 o allow different source of classloader:
250 ClassLoader cl = Thread.currentThread().getContextClassLoader();
251 if ( cl==null ) {
252 cl = this.getClass().getClassLoader();
253 }
254
255 07-26-2006
256
257 o fixed bug where separator did not appear in lists of stuff with lots
258 of null entries.
259
260 o map still iterates over values if you say <aMap> but it is now
261 shorthand for <aMap.values>. Similarly <aMap.keys> walks over the keys. You can do stuff like: <aMap.keys:{k| <k> maps to <aMap.k>}>.
262
263 07-24-2006
264
265 o added length(attribute) thanks to Kay Roepke. For now it does not
266 work on strings; it works on attributes so length("foo") is 1 meaning
267 1 attribute. Nulls are counted in lists so a list of 300 nulls is
268 length 300. If you don't want to count nulls, use
269 length(strip(list)).
270
271 o added strip(attribute) that returns an iterator that
272 skips any null values. strip(x)=x when x is a single-valued
273 attribute. Added StripIterator to handle this.
274
275 07-20-2006
276
277 o BACKWARD INCOMPATIBLE: I had to make a more clear distinction
278 between empty and null. Null means there is nothing there whereas
279 empty means the value is there but renders to an empty string. IF
280 conditionals now evaluate to empty if condition is false.
281
282 o BACKWARD INCOMPATIBLE: Changed how separators are generated. Now I
283 generate a separator for any non-null value in the list even if that
284 value is a conditional that evaluates to false. Iterated empty values
285 always get a separator. Note that empty is not the same thing as
286 missing. "" is not missing and hence will get a separator.
287
288 This made the ASTExpr.write separator computation much simpler and
289 allowed me to properly handle the new "null" option.
290
291 o Added null=expr option on expressions.
292
293 For null values in iterated attributes and single attributes that are
294 null, use this value instead of skipping. For single valued
295 attributes like <name; null="n/a">
296
297 It's a shorthand for
298
299 <if(name)><name><else>n/a<endif>
300
301 For iterated values
302
303 <values; null="0", separator=",">
304
305 you get 0 for or null list values. Works for template application
306 like this also:
307
308 <values:{v| <v>}; null="0">
309
310 This does not replace empty strings like "" as they are not null.
311
312 07-11-2006
313
314 o made static maps in STG synchronized, also synchronized the look
315 up/def methods for templates in STG.
316
317 o removed reflection property lookup; too complex for value. profiling
318 indicates it's a small cost. No thread synch issues either now.
319
320 06-24-2006
321
322 o template evaluation for anonymous templates did not properly look up
323 overridden templates. The group for anonymous templates was not reset
324 to be the current enclosing template's group (remember we can dynamically
325 set the superGroup).
326
327 06-20-2006
328
329 o Signature changed to use AttributeRenderer:
330 public void registerRenderer(Class attributeClassType,
331 AttributeRenderer renderer)
332
333 06-19-2006
334
335 o If expr in <(expr):template()> evaluated to nothing, the template was
336 still invoked.
337
338 06-12-2006
339
340 o added ability to show start/stop of template with <name>...</name>.
341 clean up! emitTemplateStartDebugString/emitTemplateStopDebugString
342 and doNotEmitDebugStringsForTemplate(tempaltename) and
343 gate:emitDebugStartStopStrings(boolean)
344
345 06-03-2006
346
347 o Improved error when property ref causes the error internally. Now shows
348 that exception rather than invocation target exception.
349
350 o Couldn't handle List<int[]>. Nested int[] was not iteratable.
351
352 06-02-2006
353
354 o Couldn't gen \ in a template. \<value> in a template escaped the <.
355 \\<value> printed both slashes. Fixed.
356
357 o added line wrap facility. st.toString(72). Wraps in between
358 expressions or elements of a multiple value attribute if you use
359 new expression option "wrap". It will not break line between
360 element and separator. toString(72) followed by toString() does not
361 wrap on the second invocation. Wrap is a soft width; does not break
362 elements to enforce a hard right edge. WARNING: separators and wrap
363 values are templates and are evaluated once *before* multi-valued
364 expressions are evaluated. You cannot change the wrap based on, for
365 example, <i>. Default values for wrap="\n", anchor="true" (any
366 non-null value means anchor).
367
368 o Updated StringTemplateWriter:
369
370 <<
371 void pushAnchorPoint();
372 void popAnchorPoint();
373 void setLineWidth(int lineWidth);
374 /** Same as write, but wrap lines using the indicated string as the
375 * wrap character (such as "\n").
376 */
377 int write(String str, String wrap) throws IOException;
378 /** Write a separator. Same as write() except that a \n cannot
379 * be inserted before emitting a separator.
380 */
381 int writeSeparator(String str) throws IOException;
382 >>
383
384 o Examples of wrapping:
385
386 <<
387 data(a) ::= <<int[] a = { 1,9,2,<values; wrap, separator=","> };\>>
388
389 int[] a = { 1,9,2,3,9,20,2,1,4,
390 6,32,5,6,77,888,2,1,6,32,5,6,77,
391 4,9,20,2,1,4,63,9,20,2,1,4,6 };
392
393 data(a) ::= <<int[] a = { 1,9,2,<values; wrap, anchor, separator=","> };\>>
394 int[] a = { 1,9,2,3,9,20,2,1,4,
395 6,32,5,6,77,
396 888,2,1,6,32,
397 5,6,77,4,9,20,
398 2,1,4,63,9,20,
399 2,1,4,6 };
400
401 data(a) ::= <<int[] a = { <{1,9,2,<values; wrap, separator=",">}; anchor> };\>>
402 int[] a = { 1,9,2,3,9,20,2,1,4,
403 6,32,5,6,77,888,2,
404 1,6,32,5,6,77,4,9,
405 20,2,1,4,63,9,20,2,
406 1,4,6 };
407 >>
408
409 05-27-2006
410
411 o Couldn't use \\\{ inside of a {...} anonymous template.
412
413 05-18-2006
414
415 o Fixed: you could not have template expressions, just simple
416 expressions in indirect template expressions like
417 $data:("foo":a())()$. I decided not to allow IF expressions inside.
418
419 o now throws exception when dots are in template names or attribute names
420
421 o don't set "it" nor "attr" default attributes if there is a parameter
422 to an anonymous block like <names:{n | ...}>
423
424 o Bug fix. If you passed in a list and then another element, it added
425 it to the list you passed in! Now, I make a (shallow) copy of the list.
426
427 o Bug fix. If you passed an element then a list to an attr and I
428 think it didn't flatten out properly!
429
430 o added build.xml ANT file (ick)
431
432 o {} and "" work as arguments now to templates
433
434 05-17-2006
435
436 o Couldn't escape in template group. \>> failed as did {...\}} for
437 anonymous templates.
438
439 o When creating an aggregate list, couldn't have spaces in {...} such
440 as "folders.{a, b}".
441
442 o Embedded templates such as {...} anonymous templates couldn't see
443 the renderers for enclosing templates. Easy to set one renderer in
444 root template for, say, Date and forget about it. If none found for
445 that class in containment hierarchy, then group hierarchy is checked.
446
447 05-12-2006
448
449 o using nativegroup to create instances now in ST.getInstanceOf. Needed
450 so that super.foo works properly. THe new instance's group will point at
451 creating group so polymorphism works properly.
452
453 04-07-2006
454
455 o BACKWARD INCOMPATIBLE: <...> is now default delimiter for group files.
456
457 04-01-2006
458
459 o note in doc that map strings are now templates and that <<...>> works too.
460 default or others can have empty values (implying no value) or use "key"
461 but not in template; it's a keyword.
462 Also, default must be at end now (and only 1). Default value is empty
463 as before.
464 To return null, use "default :" at end. Can use empty values too:
465 {"float":}, {"int":"0"}, ...
466
467 03-4-2006
468
469 o added cache for all obj.prop lookups
470
471 o added PathGroupLoader/CommonGroupLoader (which uses CLASSPATH)
472
473 03-1-2006
474
475 o added i0 which is like i except indexed from 0 not 1.
476
477 o auto defined attribute i was not defined for <a,b: {...}> case. ooops.
478
479 02-11-2006
480
481 o You couldn't have '=' in a string if preceded by '+' like foo+"ick=".
482
483 01-27-2006
484
485 o Added default lexer mechanism for groups so you can set once
486 public static void registerDefaultLexer(Class lexerClass)
487
488 01-02-2005
489
490 o Added STG.getInstanceOf(name,attributes)
491
492 12-28-2005
493
494 o Fixed bug where an expr on the first line that yields no output left
495 a blank line.
496
497 12-27-2005
498
499 o Added group inheritance notation; added unit tests. setSuperGroup(name)
500 now does something useful. Notation:
501
502 group subG : superG;
503
504 12-24-2005
505
506 o Added interfaces. See unit tests.
507
508 group Java implements ANTLRCoreTarget;
509 rule(...) ::= "..."
510 ...
511
512 You can say "optional template(args);" also. Uses group loader to
513 find interfaces.
514
515 o Added CommonGroupLoader so you can reference groups/interfaces now
516 in group files etc...
517 String tmpdir = System.getProperty("java.io.tmpdir");
518 StringTemplateGroup.registerGroupLoader(new CommonGroupLoader(tmpdir,errors));
519
520 The tmpdir can be "dir1:dir2:dir3" etc...
521
522 o There was a bug in StringTemplateGroup.isDefined that it always
523 returned true.
524
525 o Added StringTemplate.getDependencyGraph() to get a list of n->m edges
526 where template n contains template m. Also made convenient
527 getDOTForDependencyGraph(). You get a template back that lets you reset
528 node shape, fontsize, width, height attributes. Use removeAttribute
529 before setting so you are sure you only get one value.
530
531 o Added StringTemplate.toStructureString() to help discover nested structure.
532
533 11-25-2005
534
535 If you iterated multiple empty attributes, it iterated once with null values. Bizarre. Fixed.
536
537 11-12-2005
538
539 Bug in polymorphism when an overridden template called its super which called
540 another template which was also overridden; didn't call the overridden method.
541 Fixed getInstanceOf() so that it always sets the proper group so polymorphic
542 template lookup also starts at the right group.
543
544 Test testLazyEvalOfSuperInApplySuperTemplateRef was wrong...The
545 "super." prefix is (like in Java, ...) a scope override and is always
546 evaluated relative to the template in which it was defined not the
547 template in which it is evaluate!
548
549 Ugh. I *think* I have this polymorphism nailed down now.
550
551 11-11-2005
552
553 Improving error messages to be more specific when you get a parser error.
554 I'm including more context info and hopefully the file within a group file
555 the error occurs.
556
557 The defaultGroup is now public so you can know StringTemplate's default group
558 when you see it:
559 <<
560 public static StringTemplateGroup defaultGroup =
561 new StringTemplateGroup("defaultGroup", ".");
562 >>
563
564 10-27-2005
565
566 Template polymorphism bug: wouldn't work for references in IF clauses!
567
568 10-26-2005
569
570 Added regions.
571
572 10-23-2005
573
574 Any Map instance is now allowed as a "map" attribute not just Hashtable, HashMap.
575
576 10-14-2005
577
578 NullPtrExc if you registered a renderer and sent an object as an attribute
579 of another type!
580
581 10-09-2005
582
583 The tree viewer didn't work; class cast problem with Hashtable vs HashMap.
584
585 07-31-2005
586
587 Thanks to Joe Soroka, he showed me how to fix some weird thing in Java
588 where public members of an anonymous class weren't visible to
589 StringTemplate. You have to setAccessible on the field or method
590 object. Bizarre.
591
592 07-23-2005
593
594 o removed debug code as it's useless/broken
595
596 07-14-2005
597
598 o decided that {+} should not be the list creation operator. {[a,b,c]}
599 should be the thing as it mirrors the maps in group files. I want {+}
600 to mean add still.
601
602 o also decided that default arg values are templates only if "\{...}"
603 is used and strings in arg lists are just strings. I added \{...}
604 instead: $bold(it=\{$name$ Parr})$ instead. Default values can be
605 string and {...} as can args. You can have {...} on left side of
606 apply now: $\{foo}:\{($it$)}$
607
608 07-12-2005
609
610 o Decided that {+} should always return a multi-valued attribute;
611 _this is backward incompatible for anyone using + to mean string
612 cat_. Instead of
613 <<
614 $link(url="/home/"+user)$
615 >>
616 now do this:
617 <<
618 $link(url="/home/$user$")$
619 >>
620
621 07-09-2005
622
623 o added multiple attributes to left of the apply operator; works for
624 anonymous templates only! $names,phones:{n,p | $n$: $p$}$. An error
625 is generated if you have too many args for the number of parallel
626 lists. Iteration proceeds while at least one of the attributes
627 ({names} or {phones}, in this case) has values.
628
629 o added '+' cat operator for multi-valued attributes, yielding single,
630 longer multi-valued attribute. $mine+yours$ is a new list with both
631 elements; all of "mine" first then all of yours.
632
633 o allows any template invocation to assume sole argument name if
634 just one formal argument. If you do {$bold(name)$} and {bold} has one
635 formal argument, then it gets the value of name. This works also for
636 template application:
637
638 <<
639 test(names) ::= << <names:bold(),italics(); separator=", "> >>
640 bold(x) ::= "*<x>*"
641 italics(y) ::= "_<y>_"
642 >>
643
644 Note: The binding of a value to the name of a sole formal argument is
645 done dynamically so that indirect template invocation and lazy
646 evaluation stuff works properly. For example {(templateName)(value)}
647 should work for different templates with differently-name (but sole)
648 args. See unit test testInvokeIndirectTemplateWithSingleFormalArgs().
649
650 o I changed the first, rest, tail operators from yesterday. It was
651 weird doing {users:first()}...seems like {first(users)} is better.
652 This introduces a function-like syntax, which necessitated the "assign
653 to sole formal arg" functionality above that supports things like
654 {bold(name)}. Makes it possible to say {first(rest(names))} to get
655 second element now. Previous syntax made it impossible.
656
657 07-08-2005
658
659 o Added attribute functions: first (get first element), last (get last
660 element) and tail (get everything but first element). [backward
661 incompatible if you used first,last,tail as an attribute or template
662 name]
663
664 o if you are applying a template to a list and that template only has
665 one formal argument, that arg gets the same value as the iterated
666 value, "it". I.e., previously this didn't work: $list:bold()$ where
667 bold was
668 <<
669 bold(item) ::= "<b>$item$</b>"
670 >>
671
672 A template define as
673
674 <<
675 bold() ::= "<b>$it</b>"
676 >>
677
678 would still work though.
679
680 o You can define arguments for anonymous templates now, which is much
681 nicer that using <it> all the time:
682 <<
683 $names:{n| $n$}; separator=","$
684 >>
685
686 o To define an empty template, you had to write <<>>; "" didn't work.
687
688 07-06-2005
689
690 o Added maps to the group:
691
692 <<
693 typeInitMap ::= ["int"="0", "float"="0.0", default="null"]
694 >>
695
696 then within a template you can refer to them {<typeInitMap.int>},
697 which returns "0". Those strings are actually templates, but I can't
698 really think of a use for that just yet. ;) If your type name is an
699 attribute not a constant like int, then use
700 {<typeInitMap.(typeName)>}. The maps are defined in the group's scope
701 and are visible if no attribute hides them. For example, if you
702 define a formal argument called {typeInitMap} in template {foo} then
703 {foo} cannot see the map defined in the group (though you could pass
704 it in, which would be the point). If a name is not an attribute and
705 it's not in the group's maps table, then the super group is consulted
706 etc... You may not redefine a map and it may not have the same name
707 as a template in that group. The {default} value is used if you use a
708 key as a property that doesn't exist. For example {<typeInitMap.foo>}
709 returns "{null}".
710
711 07-05-2005
712
713 o Added renderers per template and group. Templates are inherited
714 from super group. Thanks to Anton Keks for his suggestion and sample
715 implementation.
716
717 06-26-2005
718
719 o literal arguments are now templates not just strings. :)
720 You can even use <<...>> literals as argument now.
721 In bug list:
722 Template inclusion expressions won't accept a nested template
723 as an argument. I'd like to be able to write <foo(bar={...})>, which
724 would mean the same thing as <foo(bar="":{...})>.
725
726 o added default argument templates like bold(x="empty") ::= ...
727 Note: because of lazy evaluation semantics, default value templates may refer
728 to argument values. Everything is evaluated after arg values are set.
729 This works for invoked templates and templates you create with code.
730
731 o all strings are now templates; does that mean "\n" is not newline anymore? Did I break compatibility?
732
733 o when calling another template, y, from within a template, x, none of the
734 x parameters are visible to y because the formal parameters force you to
735 define values. This prevents surprises and makes it easy to ensure a
736 a value is empty unless you specifically set it for that template. The
737 problem is that I need to factor templates sometimes and I want to refine
738 behavior with a subclass or just invoke another shared template but
739 <y()> erases all of x's parameters. Perhaps <y(\*)> or <y(...)> as a
740 syntax to indicate y should inherit all values. <y(name="foo", ...)>
741 would mean that I set one, but the others are inherited whereas
742 <y(name="foo")> only has name set; others are empty. Ok, I made it
743 work today. Was a 10 minute tweak. Easy. You can set manually with
744 StringTemplate.setPassThroughAttributes(). This is awesome.
745
746 06-25-2005
747
748 o When you invoke foo(x=y), x must be an attribute of foo (well if you
749 have formal args defined that is) and y is evaluated within the
750 context of the surrounding template; more precisely, it's evaluated in
751 the context of the actual template invocation (which can have
752 predefined attributes like attr, it, and i). It's weird, but foo(x=x)
753 also makes sense. See new unit test testArgEvaluationContext(). This
754 was not working before, though I thought it was!
755
756 o error messages are better for setting an undefined argument.
757
758 05-02-2005
759
760 o When a property is not found, you get a better error. I show the
761 template context (nested tree of templates).
762
763 05-01-2005
764
765 o Collections, Maps, and Iterators that are non-null but have no elements
766 return false in conditionals; e.g., $if(users)$ is false if users is
767 an empty list.
768
769 03-30-2005
770
771 o added template context upon no such element. It says stuff like:
772 <<
773 no such attribute: decisionNumber in template context
774 [outputFile lexer cyclicDFA cyclicDFAState cyclicDFAEdge lookaheadTest]
775 >>
776
777 03-28-2005
778
779 o added ability to use indirect property names. $user.(propName)$
780 evaluates (propName) to find the name of the property and then looks
781 it up in user object.
782
783 01-22-2005
784
785 o Empty output for a single attribute expression one a line by itself gets no newline (i.e., you don't get a blank line).
786
787 01-02-2005
788
789 o You can access public fields now instead of via just accessors
790
791 o empty (i.e., no char output) values in an iteration do not get a separator if specified. This will be 99% of the time what you want. Only if pure IF (no else).
792
793 12-25-2004
794
795 o Made convertArrayToList() handle long[] also and made "a.{f1,f2}" type aggregate attributes properly convert incoming arrays to lists for normalization.
796
797 12-24-2004
798
799 o Made a template lookup that is not defined throw an IllegalArgumentException rather than generate an error directly.
800
801 12-19-2004
802
803 o Made null indirect template generate nothing; used to generate null-ptr exception.
804
805 11-20-2004
806
807 o trap all antlr generated errors now and send to listener.
808
809 11-07-2004
810
811 o Added
812 <<
813 /** Specify a StringTemplateWriter implementing class to use for
814 * filtering output
815 */
816 public void setStringTemplateWriter(Class c) {
817 userSpecifiedWriter = c;
818 }
819 >>
820 and made StringTemplate.toString() sensitive to it.
821
822 11-04-2004
823
824 o added support for nonlocal file encodings; added property fileCharEncoding. The template loading routines are now sensitive to this property. Defaults to the file.encoding system property.
825
826 11-03-2004
827
828 o STG.templateIsDefinedInThisGroup -> isDefinedInThisGroup
829 o added isDefined(name) that checks whole hierarchy
830
831 10-31-2004
832
833 o addressed whitespace at begin/end of template .st file issue. Decided to let it continue to strip all front/back whitespace and then make you add it directly. This is a simple rule and can be made to do what you want. It is consistent with the strip newline before \>\> rule too.
834
835 o added <\ > for space char
836
837 o updated testing harness to be same as ANTLR 3.0's which is more sophisticated.
838
839 o the newline immediately preceding >> in a template group file is tossed out just like the newline right after the \<<
840
841 10-30-2004
842
843 o newlines ignored before <else> and <endif>. Rule is: kill a single newline
844 after <if>, <<, <else>, and <endif> (but for <endif> only if it's on a line by itself) . Kill newlines before <else> and <endif> and >>.
845
846 o added <\n>, <\r>, <\t>
847
848 o fixed \n refs in TestStringTemplate unit tests to be portable newline reference.
849
850 10-29-2004
851
852 o added $!...!$ and <!...!> comments (version 2.1b3)
853
854 10-10-2004
855
856 o allow HashMap, Hashtable precisely but not Map in attribute.property lookup
857
858 o $attributes$ is a text string when lint mode on that recursively dumps
859 out types, properties, etc... (no values)
860
861 09-25-2004
862
863 o Templates track their embedded instances; can ask for embedded
864
865 o added isXXX accessor properties so x.special invokes x.getSpecial then x.isSpecial if not successful.
866
867 o bug in st.attribute...if no attributes table, got null ptr exception
868
869 07-07-2004
870
871 o given the big changes to ST, I'm going to deprecate attr and use "it" as the default iterator attribute. Says "iterator" and is sort of like "this". I looked at "this", "that", "iter", and even "the". "ith" even [i].
872
873 07-01-2004
874
875 o a.b yields a's b attribute if a is stringtemplate, which lets you treat a list of templates or nested set of templates as a data structure. For example, given a list of templates representing output rules from antlr, i can generate both the C function definitions for those rules and the list of C function declarations:
876
877 <rules:{public void <attr.name>(<attr.args);}>
878 <rules:{public void <attr.name>(<attr.args) {<attr.body>\}}>
879
880 o applying a template to a list of attributes reused the same template, but you need a new one to get a new attribute set etc...
881
882 o apply a template to a list of attributes did a toString() rather than build up a list of templates to apply later.
883
884 o to prevent recursion, formally defined parameters hide any (dynamically) enclosing scope. The attributes can be null or have values still, but you cannot inherit an attribute from an enclosing scope, bypassing an empty local attribute formally defined in that template. See test case that used to cause infinite recursion. Hmm...can i limit to the case where same template is up the call stack somewhere? Any other inheritance should be ok, right? This
885 is not always what you want. If you set the font for a table, then nested
886 tables cannot inherit the font. However it prevents you from forgetting to
887 set the rows attr in the nested, which would cause an infinite recursive loop. Actually figured out precisely what it should be. Can't avoid infinite recursion without expensive tests so make part of lintMode:
888
889 StringTemplate: error: possible recursive self-reference to stats in template ifstat
890
891 If you get a value in getAttribute that refers to the current template or an enclosing template, must be in an infinite loop. Can't stop it, but error to errorListener. Ok, now I really have it. In ASTExpr.write, if the object to write out is a ST, then it walks up enclosing chain and makes sure it is unique. Otherwise, it's infinite recursion. Same template, different instance is fine. Only in lintMode! throws IllegalStateException.
892
893 Back to formal arg always hides enclosing value, though if you stick in a looped attribute set then I catch it in lint mode.
894
895
896 06-26-2004
897
898 o added helper method setAttribute(String,int)
899
900 o removed ability to pass hashtable in as initial args...security hole.
901
902 06-24-2004
903
904 o included templates like <font()> computed the text right away rather
905 than lazily evaluating when the outer template evaluated. Missed some
906 parameters that way.
907
908 o when embedding a template inside another via setAttribute, it must set the
909 enclosingInstance so that it can inherit attributes. This was not working
910 when you setAttribute("foo"...) multiple times for attribute foo. It was
911 just adding stuff to the internal array without checking to see if it was
912 a ST.
913
914 05-08-2004
915
916 o Improved test harness so we can time tests; added some eval speed tests.
917
918 05-07-2004
919
920 o nested IF works
921
922 o $else$ clause added
923
924 o antlr lexer used to chunk now two predefined $..$ and <..>
925
926 o added group file format
927
928 o changed boolean so that you are testing its value not presence/absence
929
930 o added formal parameter checking. Can only set attributes that exist at
931 a template or enclosing template. Can only ref attributes that exist at
932 that template or above. Throws NoSuchElement exceptions.
933
934 o added general notion of StringTemplateWriter so you can do output filters.
935
936 o predefined auto indentation filter (default used).
937
938 o properties that return arrays are converted to iterators. Factored out
939 this normalization code into static ASTExpr methods. Did not handle properties that return collections as multi-valued values.
940
941 05-03-2004
942
943 o Added Collection and Iterator stuff in ASTExpr writeAttribute. Can dump or apply template to either Map, Collection, or Iterator now.
944
945 o anything iteratable can be used for "APPLY" template
946
947
948 01-23-2004
949
950 o Fixed some errors in the escape char when in anonymous templates {...}
951
952 o Fixed so nested anonymous templates works now.
953
954 o Changed some protections and so on so that can override behavior more
955 easily.
956
957 5-16-2003
958
959 o Make StringTemplate to List interface or collection.
960 [Fixed 5-17-2003]
961
962 o Need $(foo)()$. What about $names:(boldtemplate)():italics()$?
963 What about $(foo)()+(bar)()$? $(foo+".template")()$
964 [Fixed 5-17-2003]
965
966 4-11-2003
967
968 o if a template name is not found, it will still try to apply it to an
969 attribute
970 [Fixed 5-15-2003]
971
972 o fix missing end $. now it consumes the rest of the file.
973 [Fixed 5-15-2003. Well, it still consumes, but now the listener gets
974 the error actually.]
975
976 o add more messages that go to the error listener
977 [Fixed 5-15-2003]:
978 added warning(msg) to listener
979 added setLintMode(true), makes setting of unknown attr a warning
980
981 4-01-2003 [Fixed 5-15-2003]
982
983 o attr is not re-evaluated in template application to a vector--args
984 are evaluated a priori!
985 $members:link(url=attr.homepage, title=attr.name)$
986 does not work!
987
988
0 [The "BSD licence"]
1 Copyright (c) 2003-2008 Terence Parr
2 All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0 StringTemplate 3.2.1
1 September 22, 2009
2
3 Terence Parr, parrt at cs usfca edu
4 ANTLR project lead and supreme dictator for life
5 University of San Francisco
6
7 ST (StringTemplate) is a java template engine (with ports for C# and Python) for generating source code, web pages, emails, or any other formatted text output. ST is particularly good at multi-targeted code generators, multiple site skins, and internationalization/localization. It evolved over years of effort developing jGuru.com. ST also generates this website and powers the ANTLR v3 code generator. Its distinguishing characteristic is that it strictly enforces model-view separation unlike other engines.
8
9 The main website is:
10
11 http://www.stringtemplate.org
12
13 The documentation is in the wiki:
14
15 http://www.antlr.org/wiki/display/ST/StringTemplate+Documentation
16
17 Here are the 3.2.1 release notes:
18
19 http://www.antlr.org/wiki/display/ST/3.2.1+Release+Notes
20
21 Per the license in LICENSE.txt, this software is not guaranteed to
22 work and might even destroy all life on this planet.
23
24 See the CHANGES.txt file.
0 <?xml version="1.0"?>
1
2 <!-- ===================================================================== -->
3 <!-- StringTemplate build file (contributed by Dieter Wimberger) -->
4 <!-- Terence says: I have no idea whether this does anything useful. -->
5 <!-- Somebody can fix it; seems to be almost right -->
6 <!-- ===================================================================== -->
7 <project name="stringtemplate" default="compile" basedir=".">
8
9 <target name="init">
10 <tstamp>
11 <format property="src.timestamp" pattern="dd/MM/yyyy"/>
12 <format property="year" pattern="2006-yyyy"/>
13 </tstamp>
14
15 <!-- Allow any user specific values to override the defaults -->
16 <property file="./build.properties"/>
17
18 <property name="language.dir"
19 value="${basedir}${file.separator}src${file.separator}org${file.separator}antlr${file.separator}stringtemplate${file.separator}language"/>
20
21 <property name="action.g" value="${language.dir}/action.g" />
22 <property name="angle.bracket.template.g" value="${language.dir}/angle.bracket.template.g" />
23 <property name="eval.g" value="${language.dir}/eval.g" />
24 <property name="group.g" value="${language.dir}/group.g" />
25 <property name="interface.g" value="${language.dir}/interface.g" />
26 <property name="template.g" value="${language.dir}/template.g" />
27
28 <property name="Name" value="stringtemplate"/>
29 <property name="name" value="stringtemplate"/>
30 <property name="copyright" value="${year} Terence Parr"/>
31
32 <!-- Filters -->
33 <filter token="date" value="${src.timestamp}"/>
34 <filter token="version" value="${version}"/>
35 <filter token="copyright" value="${copyright}"/>
36
37 <!-- Source related properties -->
38 <property name="src.dir" value="${basedir}${file.separator}src"/>
39 <property name="src.java" value="${src.dir}"/>
40 <property name="lib.dir" value="${basedir}${file.separator}lib${file.separator}"/>
41 <property name="src.excludes" value=""/>
42
43 <!-- Build related properties -->
44 <property name="build.dir" value="${basedir}${file.separator}build"/>
45 <property name="build.src" value="${build.dir}${file.separator}src"/>
46 <property name="build.classes" value="${build.dir}${file.separator}classes"/>
47 <property name="build.javadocs" value="${basedir}${file.separator}docs${file.separator}api"/>
48 <property name="build.jar" value="${build.dir}${file.separator}${name}.jar"/>
49
50 <path id="build.classpath">
51 <pathelement location="${antlr2.jar}"/>
52 </path>
53
54 <!--
55 <path id="build.classpath">
56 <fileset dir="${lib.dir}">
57 <include name="**/*.jar" />
58 </fileset>
59 </path>
60 -->
61
62 <property name="build.dist" value="${build.dir}${file.separator}${name}-${version}"/>
63
64 <property name="build.packages"
65 value="org.antlr.stringtemplate,org.antlr.stringtemplate.language,org.antlr.stringtemplate.misc,org.antlr.stringtemplate.test"/>
66 <property name="javadocs.additionalparam" value="" />
67
68 <property name="dist.basedir" value="${build.dir}"/>
69 <property name="dist.includes" value="${name}${file.separator}**"/>
70 <property name="dist.excludes"
71 value="**/prj/**,
72 **/dist/**,
73 **/test/**,
74 **/model/**,
75 **/build/**,
76 **/.DS_Store"
77 />
78 <property name="packages" value="${build.packages}"/>
79 <property name="library.includes" value="${bundle.includes}"/>
80
81 </target>
82
83
84 <!-- =================================================================== -->
85 <!-- Basic build targets -->
86 <!-- =================================================================== -->
87 <target name="prepare-sources" depends="init">
88 <mkdir dir="${build.dir}"/>
89 <mkdir dir="${build.src}"/>
90 <!-- specific filters -->
91 <filter token="commentstart" value="${line.separator}"/>
92 <filter token="commentend" value=""/>
93
94 <copy todir="${build.src}" filtering="true">
95 <fileset dir="${src.java}" excludes="${src.excludes}"/>
96 </copy>
97 </target>
98
99
100 <target name="generator">
101 <antlr target="${action.g}" />
102 <antlr target="${template.g}" />
103 <antlr target="${angle.bracket.template.g}" />
104 <antlr target="${eval.g}" />
105 <antlr target="${group.g}" />
106 <antlr target="${interface.g}" />
107 </target>
108
109 <!-- =================================================================== -->
110 <!-- Compiles the source code -->
111 <!-- =================================================================== -->
112 <target name="compile" depends="init, prepare-sources, generator" description="Compiles the sources. (Default)">
113 <!-- Echo compilation properties -->
114 <echo level="info" message="Compiler = ${build.compiler}"/>
115 <echo level="info" message="Optimize = ${compile.optimize}"/>
116 <echo level="info" message="Deprecation = ${compile.deprecation}"/>
117 <echo level="info" message="Debug = ${compile.debug}"/>
118
119 <mkdir dir="${build.classes}"/>
120 <javac srcdir="${build.src}"
121 destdir="${build.classes}"
122 debug="${compile.debug}"
123 optimize="${compile.optimize}"
124 deprecation="${compile.deprecation}"
125 source="1.4"
126 target="1.4"
127 >
128 <classpath refid="build.classpath"/>
129 </javac>
130 </target>
131
132 <!-- =================================================================== -->
133 <!-- Creates the jar archive -->
134 <!-- =================================================================== -->
135 <target name="jar" depends="init,compile" description="Builds the library (.jar).">
136 <jar jarfile="${build.jar}"
137 basedir="${build.classes}"
138 includes="**/*.class">
139 </jar>
140 </target>
141
142 <!-- =================================================================== -->
143 <!-- Create gzipped tarball -->
144 <!-- =================================================================== -->
145 <target name="dist" depends="init,compile,jar">
146 <mkdir dir="${build.dist}"/>
147 <tar tarfile="${build.dist}${file.separator}${name}${version}.tar"
148 basedir="${dist.basedir}"
149 includes="${dist.includes}"
150 excludes="${dist.excludes}"
151 />
152 <gzip zipfile="${build.dist}${file.separator}${name}${version}.tar.gz" src="${build.dist}${file.separator}${name}${version}.tar"/>
153 <delete file="${build.dist}${file.separator}${name}${version}.tar"/>
154
155 </target>
156
157 <!-- =================================================================== -->
158 <!-- Create zip distribution -->
159 <!-- =================================================================== -->
160 <target name="zipdist" depends="init,compile,jar">
161 <mkdir dir="${build.dist}"/>
162 <echo level="info" message="build.dist = ${build.dist}"/>
163 <echo level="info" message="dist.includes = ${dist.includes}"/>
164
165 <zip zipfile="${build.dist}${file.separator}${name}${version}.zip"
166 basedir="${dist.basedir}"
167 includes="${dist.includes}"
168 excludes="${dist.excludes}"
169 />
170 </target>
171
172
173 <!-- =================================================================== -->
174 <!-- Create docs distribution -->
175 <!-- =================================================================== -->
176 <target name="docsdist" depends="init,javadocs">
177 <zip zipfile="${build.dist}${file.separator}${name}${version}_docs.zip"
178 basedir="${basedir}"
179 includes="docs/**"
180 />
181 </target>
182
183 <!-- =================================================================== -->
184 <!-- Generate release -->
185 <!-- =================================================================== -->
186 <target name="release" depends="clean-all,jar,javadocs,dist,zipdist">
187 <echo message="Created release ${version}"/>
188 </target>
189
190 <!-- =================================================================== -->
191 <!-- Creates the API documentation -->
192 <!-- =================================================================== -->
193 <target name="javadocs" depends="init,prepare-sources">
194 <mkdir dir="${build.javadocs}"/>
195 <javadoc packagenames="${packages}"
196 sourcepath="${build.src}"
197 destdir="${build.javadocs}"
198 author="true"
199 version="true"
200 windowtitle="${Name} API"
201 doctitle="${Name} API Documentation"
202 bottom="Copyright &#169; ${copyright}"
203 additionalparam="${javadocs.additionalparam}"
204 />
205 </target>
206
207 <!-- =================================================================== -->
208 <!-- Cleans up generated classes -->
209 <!-- =================================================================== -->
210 <target name="clean-classes" depends="init">
211 <delete dir="${build.classes}"/>
212 </target>
213
214 <!-- =================================================================== -->
215 <!-- Cleans up generated javadocs -->
216 <!-- =================================================================== -->
217 <target name="clean-docs" depends="init">
218 <delete dir="${build.javadocs}"/>
219 </target>
220
221 <!-- =================================================================== -->
222 <!-- Cleans up generated jars -->
223 <!-- =================================================================== -->
224 <target name="clean-jars" depends="init">
225 <delete file="${build.jar}"/>
226 </target>
227
228
229 <!-- =================================================================== -->
230 <!-- Cleans up generated distributions -->
231 <!-- =================================================================== -->
232 <target name="clean-dist" depends="init">
233 <delete dir="${build.dist}"/>
234 </target>
235
236 <!-- =================================================================== -->
237 <!-- Cleans up all -->
238 <!-- =================================================================== -->
239 <target name="clean-all" depends="clean-classes,clean-jars, clean-dist">
240 <echo message="Cleaned all."/>
241 </target>
242
243 </project>
244
0 <?xml version="1.0" encoding="UTF-8"?>
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
2 <modelVersion>4.0.0</modelVersion>
3 <groupId>org.antlr</groupId>
4 <artifactId>stringtemplate</artifactId>
5 <packaging>jar</packaging>
6
7 <!--
8 The version number defined here in the version tag indicates how the
9 jar is named and released. When it ends with SNAPSHOT, it will be stored
10 in your local repository (~/m2 on UNIX) as stringtemplate-X.Y-SNAPSHOT, but
11 will be deplyed to the ANTLR snapshot repository at antlr.org with the word
12 SNAPSHOT replaced with the the data, time and unique number.
13 -->
14 <version>3.3-SNAPSHOT</version>
15
16 <!--
17 The name of the project as seen by IDEs and release documentation etc.
18 -->
19 <name>ANTLR StringTemplate</name>
20
21 <description>StringTemplate is a java template engine for generating source code,
22 web pages, emails, or any other formatted text output.
23
24 StringTemplate is particularly good at multi-targeted code generators,
25 multiple site skins, and internationalization/localization.
26
27 It evolved over years of effort developing jGuru.com.
28
29 StringTemplate also generates the stringtemplate website: http://www.stringtemplate.org
30 and powers the ANTLR v3 code generator. Its distinguishing characteristic
31 is that unlike other engines, it strictly enforces model-view separation.
32
33 Strict separation makes websites and code generators more flexible
34 and maintainable; it also provides an excellent defense against malicious
35 template authors.
36
37 There are currently about 600 StringTemplate source downloads a month.
38 </description>
39
40 <!--
41 The URL of the ANTLR base project
42 -->
43 <url>http://www.stringtemplate.org</url>
44 <developers>
45 <developer>
46 <name>Terence Parr</name>
47 <organization>USFCA</organization>
48 <organizationUrl>http://www.cs.usfca.edu</organizationUrl>
49 <email>parrt@antlr.org</email>
50 <roles>
51 <role>Project Leader</role>
52 <role>Developer - Java Target</role>
53 </roles>
54 <timezone>PST</timezone>
55 </developer>
56 <developer>
57 <name>Jim Idle</name>
58 <organization>Temporal Wave LLC</organization>
59 <organizationUrl>http://www.temporal-wave.com</organizationUrl>
60 <email>jimi@temporal-wave.com</email>
61 <roles>
62 <role>Developer - Maven stuff</role>
63 </roles>
64 <timezone>PST</timezone>
65 </developer>
66 </developers>
67
68 <licenses>
69 <license>
70 <name>BSD licence</name>
71 <url>http://antlr.org/license.html</url>
72 <distribution>repo</distribution>
73 </license>
74 </licenses>
75 <scm>
76 <url>http://fisheye2.cenqua.com/browse/stringtemplate</url>
77 <connection>http://fisheye2.cenqua.com/browse/stringtemplate</connection>
78 </scm>
79
80 <!--
81 Definition of the ANTLR repositories. Note that you can only deploy
82 to the repositories via scp, and so the server must already know about
83 your public key. ONly ANTLR developers are allowed to deploy to the
84 release and snapshot repositories, which are synced with the Maven central
85 repository.
86 -->
87 <distributionManagement>
88 <repository>
89 <id>antlr-repo</id>
90 <name>ANTLR Testing repository</name>
91 <url>scpexe://antlr.org/home/mavensync/antlr-repo</url>
92 </repository>
93
94 <snapshotRepository>
95 <id>antlr-snapshot</id>
96 <name>ANTLR Testing Snapshot Repository</name>
97 <url>scpexe://antlr.org/home/mavensync/antlr-snapshot</url>
98 </snapshotRepository>
99 </distributionManagement>
100
101 <dependencies>
102 <dependency>
103 <groupId>junit</groupId>
104 <artifactId>junit</artifactId>
105 <version>4.5</version>
106 <scope>test</scope>
107 </dependency>
108 <dependency>
109 <groupId>antlr</groupId>
110 <artifactId>antlr</artifactId>
111 <version>2.7.7</version>
112 <scope>compile</scope>
113 </dependency>
114 </dependencies>
115
116 <build>
117
118 <defaultGoal>install</defaultGoal>
119
120 <extensions>
121 <extension>
122 <groupId>org.apache.maven.wagon</groupId>
123 <artifactId>wagon-ssh-external</artifactId>
124 <version>1.0-beta-2</version>
125 </extension>
126 </extensions>
127
128
129 <!--
130 The root of the source code for StringTemplate
131 -->
132 <sourceDirectory>src</sourceDirectory>
133
134 <!--
135 The root of the test source code for StringTemplate.
136 -->
137 <testSourceDirectory>test</testSourceDirectory>
138
139 <!--
140 All the resources that should be on the classpath, when
141 the junit tests are run. Here we need to include the test
142 source code directory as the .st files loaded dynamically
143 by the tests, are located underneath this tree.
144 -->
145 <testResources>
146 <testResource>
147 <directory>test</directory>
148 </testResource>
149 </testResources>
150
151 <plugins>
152 <plugin>
153 <groupId>org.codehaus.mojo</groupId>
154 <artifactId>antlr-maven-plugin</artifactId>
155 <configuration>
156 <sourceDirectory>src/org/antlr/stringtemplate/language</sourceDirectory>
157 <grammars>template.g, angle.bracket.template.g, action.g, eval.g, group.g, interface.g</grammars>
158 </configuration>
159 <executions>
160 <execution>
161 <goals>
162 <goal>generate</goal>
163 </goals>
164 </execution>
165 </executions>
166 </plugin>
167 <plugin>
168 <artifactId>maven-compiler-plugin</artifactId>
169 <configuration>
170 <source>1.4</source>
171 <target>1.4</target>
172 <sourceDirectory>src</sourceDirectory>
173 </configuration>
174 </plugin>
175 <plugin>
176 <artifactId>maven-surefire-plugin</artifactId>
177 <configuration>
178 <additionalClasspathElements>
179 <additionalClasspathElement>${basedir}/src</additionalClasspathElement>
180 </additionalClasspathElements>
181 </configuration>
182 </plugin>
183
184 <plugin>
185 <groupId>org.codehaus.mojo</groupId>
186 <artifactId>findbugs-maven-plugin</artifactId>
187 <configuration>
188 <findbugsXmlOutput>true</findbugsXmlOutput>
189 <findbugsXmlWithMessages>true</findbugsXmlWithMessages>
190 <xmlOutput>true</xmlOutput>
191 </configuration>
192 </plugin>
193
194 </plugins>
195 </build>
196 </project>
0 /*
1 [The "BSD licence"]
2 Copyright (c) 2003-2005 Terence Parr
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package org.antlr.stringtemplate;
28
29 /** This interface describes an object that knows how to format or otherwise
30 * render an object appropriately. Usually this is used for locale changes
31 * for objects such as Date and floating point numbers... You can either
32 * have an object that is sensitive to the locale or have a different object
33 * per locale.
34 *
35 * Each template may have a renderer for each object type or can default
36 * to the group's renderer or the super group's renderer if the group doesn't
37 * have one.
38 *
39 * The toString(Object,String) method is used when the user uses the
40 * format option: $o; format="f"$. It checks the formatName and applies the
41 * appropriate formatting. If the format string passed to the renderer is
42 * not recognized then simply call toString(). @since 3.1
43 */
44 public interface AttributeRenderer {
45 public String toString(Object o);
46 public String toString(Object o, String formatName);
47 }
0 /*
1 [The "BSD licence"]
2 Copyright (c) 2003-2005 Terence Parr
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package org.antlr.stringtemplate;
28
29 import java.io.IOException;
30 import java.io.Writer;
31 import java.util.ArrayList;
32 import java.util.List;
33
34 /** Essentially a char filter that knows how to auto-indent output
35 * by maintaining a stack of indent levels. I set a flag upon newline
36 * and then next nonwhitespace char resets flag and spits out indention.
37 * The indent stack is a stack of strings so we can repeat original indent
38 * not just the same number of columns (don't have to worry about tabs vs
39 * spaces then).
40 *
41 * Anchors are char positions (tabs won't work) that indicate where all
42 * future wraps should justify to. The wrap position is actually the
43 * larger of either the last anchor or the indentation level.
44 *
45 * This is a filter on a Writer.
46 *
47 * \n is the proper way to say newline for options and templates.
48 * Templates can mix them but use \n for sure and options like
49 * wrap="\n". ST will generate the right thing. Override the default (locale)
50 * newline by passing in a string to the constructor.
51 */
52 public class AutoIndentWriter implements StringTemplateWriter {
53 /** stack of indents; use List as it's much faster than Stack. Grows
54 * from 0..n-1. List<String>
55 */
56 protected List indents = new ArrayList();
57
58 /** Stack of integer anchors (char positions in line); avoid Integer
59 * creation overhead.
60 */
61 protected int[] anchors = new int[10];
62 protected int anchors_sp = -1;
63
64 /** \n or \r\n? */
65 protected String newline;
66
67 protected Writer out = null;
68 protected boolean atStartOfLine = true;
69
70 /** Track char position in the line (later we can think about tabs).
71 * Indexed from 0. We want to keep charPosition <= lineWidth.
72 * This is the position we are *about* to write not the position
73 * last written to.
74 */
75 protected int charPosition = 0;
76 protected int lineWidth = NO_WRAP;
77
78 protected int charPositionOfStartOfExpr = 0;
79
80 public AutoIndentWriter(Writer out, String newline) {
81 this.out = out;
82 indents.add(null); // s oftart with no indent
83 this.newline = newline;
84 }
85
86 public AutoIndentWriter(Writer out) {
87 this(out, System.getProperty("line.separator"));
88 }
89
90 public void setLineWidth(int lineWidth) {
91 this.lineWidth = lineWidth;
92 }
93
94 /** Push even blank (null) indents as they are like scopes; must
95 * be able to pop them back off stack.
96 *
97 * To deal with combined anchors and indentation, force indents to
98 * include any current anchor point. If current anchor is beyond
99 * current indent width, add the difference to the indent to be added.
100 *
101 * This prevents a check later to deal with anchors when starting new line.
102 */
103 public void pushIndentation(String indent) {
104 int lastAnchor = 0;
105 int indentWidth = getIndentationWidth();
106 // If current anchor is beyond current indent width, add in difference
107 if ( anchors_sp>=0 && anchors[anchors_sp]>indentWidth ) {
108 lastAnchor = anchors[anchors_sp];
109 StringBuffer buf = getIndentString(lastAnchor-indentWidth);
110 if ( indent!=null ) buf.append(indent); // don't add if null
111 indents.add(buf.toString());
112 return;
113 }
114 indents.add(indent);
115 }
116
117 public String popIndentation() {
118 return (String)indents.remove(indents.size()-1);
119 }
120
121 public void pushAnchorPoint() {
122 if ( (anchors_sp +1)>=anchors.length ) {
123 int[] a = new int[anchors.length*2];
124 System.arraycopy(anchors, 0, a, 0, anchors.length-1);
125 anchors = a;
126 }
127 anchors_sp++;
128 anchors[anchors_sp] = charPosition;
129 }
130
131 public void popAnchorPoint() {
132 anchors_sp--;
133 }
134
135 public int getIndentationWidth() {
136 int n = 0;
137 for (int i=0; i<indents.size(); i++) {
138 String ind = (String)indents.get(i);
139 if ( ind!=null ) {
140 n+=ind.length();
141 }
142 }
143 return n;
144 }
145
146 /** Write out a string literal or attribute expression or expression element.*/
147 public int write(String str) throws IOException {
148 int n = 0;
149 for (int i=0; i<str.length(); i++) {
150 char c = str.charAt(i);
151 // found \n or \r\n newline?
152 if ( c=='\r' || c=='\n' ) {
153 atStartOfLine = true;
154 charPosition = -1; // set so the write below sets to 0
155 n += newline.length();
156 out.write(newline);
157 charPosition += n; // wrote n more char
158 // skip an extra char upon \r\n
159 if ( (c=='\r' && (i+1)<str.length() && str.charAt(i+1)=='\n') ) {
160 i++; // loop iteration i++ takes care of skipping 2nd char
161 }
162 continue;
163 }
164 // normal character
165 // check to see if we are at the start of a line; need indent if so
166 if ( atStartOfLine ) {
167 n+=indent();
168 atStartOfLine = false;
169 }
170 n++;
171 out.write(c);
172 charPosition++;
173 }
174 return n;
175 }
176
177 public int writeSeparator(String str) throws IOException {
178 return write(str);
179 }
180
181 /** Write out a string literal or attribute expression or expression element.
182 *
183 * If doing line wrap, then check wrap before emitting this str. If
184 * at or beyond desired line width then emit a \n and any indentation
185 * before spitting out this str.
186 */
187 public int write(String str, String wrap) throws IOException {
188 int n = writeWrapSeparator(wrap);
189 return n + write(str);
190 }
191
192 public int writeWrapSeparator(String wrap) throws IOException {
193 int n = 0;
194 // if want wrap and not already at start of line (last char was \n)
195 // and we have hit or exceeded the threshold
196 if ( lineWidth!=NO_WRAP && wrap!=null && !atStartOfLine &&
197 charPosition >= lineWidth )
198 {
199 // ok to wrap
200 // Walk wrap string and look for A\nB. Spit out A\n
201 // then spit indent or anchor, whichever is larger
202 // then spit out B.
203 for (int i=0; i<wrap.length(); i++) {
204 char c = wrap.charAt(i);
205 if ( c=='\n' ) {
206 n++;
207 out.write(c);
208 charPosition = 0;
209 n+=indent();
210 // continue writing any chars out
211 }
212 else { // write A or B part
213 n++;
214 out.write(c);
215 charPosition++;
216 }
217 }
218 }
219 return n;
220 }
221
222 public int indent() throws IOException {
223 int n = 0;
224 for (int i=0; i<indents.size(); i++) {
225 String ind = (String)indents.get(i);
226 if ( ind!=null ) {
227 n+=ind.length();
228 out.write(ind);
229 }
230 }
231 charPosition += n;
232 return n;
233 }
234
235 public int indent(int spaces) throws IOException {
236 for (int i=1; i<=spaces; i++) {
237 out.write(' ');
238 }
239 charPosition += spaces;
240 return spaces;
241 }
242
243 protected StringBuffer getIndentString(int spaces) {
244 StringBuffer buf = new StringBuffer();
245 for (int i=1; i<=spaces; i++) {
246 buf.append(' ');
247 }
248 return buf;
249 }
250 }
0 package org.antlr.stringtemplate;
1
2 import java.io.*;
3
4 /** A simple loader that looks only in the directory(ies) you
5 * specify in the ctor, but it uses the classpath rather than
6 * absolute dirs so it can be used when the ST application is jar'd up.
7 * You may specify the char encoding.
8 */
9 public class CommonGroupLoader extends PathGroupLoader {
10
11 public CommonGroupLoader(StringTemplateErrorListener errors) {
12 super(errors);
13 }
14
15 /** Pass a single dir or multiple dirs separated by colons from which
16 * to load groups/interfaces. These are interpreted as relative
17 * paths to be used with CLASSPATH to locate groups. E.g.,
18 * If you pass in "org/antlr/codegen/templates" and ask to load
19 * group "foo" it will try to load via classpath as
20 * "org/antlr/codegen/templates/foo".
21 */
22 public CommonGroupLoader(String dirStr, StringTemplateErrorListener errors) {
23 super(dirStr,errors);
24 }
25
26 /** Look in each relative directory for the file called 'name'.
27 * Load via classpath.
28 */
29 protected BufferedReader locate(String name) throws IOException {
30 for (int i = 0; i < dirs.size(); i++) {
31 String dir = (String) dirs.get(i);
32 String fileName = dir+"/"+name;
33 //System.out.println("trying "+fileName);
34 ClassLoader cl = Thread.currentThread().getContextClassLoader();
35 InputStream is = cl.getResourceAsStream(fileName);
36 if ( is==null ) {
37 cl = this.getClass().getClassLoader();
38 is = cl.getResourceAsStream(fileName);
39 }
40 if ( is!=null ) {
41 return new BufferedReader(getInputStreamReader(is));
42 }
43 }
44 return null;
45 }
46
47 }
0 /*
1 [The "BSD licence"]
2 Copyright (c) 2003-2005 Terence Parr
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package org.antlr.stringtemplate;
28
29 import java.io.Writer;
30 import java.io.IOException;
31
32 /** Just pass through the text */
33 public class NoIndentWriter extends AutoIndentWriter {
34 public NoIndentWriter(Writer out) {
35 super(out);
36 }
37
38 public int write(String str) throws IOException {
39 out.write(str);
40 return str.length();
41 }
42 }
0 package org.antlr.stringtemplate;
1
2 import org.antlr.stringtemplate.language.AngleBracketTemplateLexer;
3
4 import java.io.*;
5 import java.util.ArrayList;
6 import java.util.List;
7 import java.util.StringTokenizer;
8
9 /** A brain dead loader that looks only in the directory(ies) you
10 * specify in the ctor.
11 * You may specify the char encoding.
12 * NOTE: this does not work when you jar things up! Use
13 * CommonGroupLoader instead in that case
14 */
15 public class PathGroupLoader implements StringTemplateGroupLoader {
16 /** List of ':' separated dirs to pull groups from */
17 protected List dirs = null;
18
19 protected StringTemplateErrorListener errors = null;
20
21 /** How are the files encoded (ascii, UTF8, ...)? You might want to read
22 * UTF8 for example on an ascii machine.
23 */
24 String fileCharEncoding = System.getProperty("file.encoding");
25
26 public PathGroupLoader(StringTemplateErrorListener errors) {
27 this.errors = errors;
28 }
29
30 /** Pass a single dir or multiple dirs separated by colons from which
31 * to load groups/interfaces.
32 */
33 public PathGroupLoader(String dirStr, StringTemplateErrorListener errors) {
34 this.errors = errors;
35 StringTokenizer tokenizer = new StringTokenizer(dirStr, ":", false);
36 while (tokenizer.hasMoreElements()) {
37 String dir = (String) tokenizer.nextElement();
38 if ( dirs==null ) {
39 dirs = new ArrayList();
40 }
41 dirs.add(dir);
42 }
43 }
44
45 /** Load a group with a specified superGroup. Groups with
46 * region definitions must know their supergroup to find templates
47 * during parsing.
48 */
49 public StringTemplateGroup loadGroup(String groupName,
50 Class templateLexer,
51 StringTemplateGroup superGroup)
52 {
53 StringTemplateGroup group = null;
54 BufferedReader br = null;
55 // group file format defaults to <...>
56 Class lexer = AngleBracketTemplateLexer.class;
57 if ( templateLexer!=null ) {
58 lexer = templateLexer;
59 }
60 try {
61 br = locate(groupName+".stg");
62 if ( br==null ) {
63 error("no such group file "+groupName+".stg");
64 return null;
65 }
66 group = new StringTemplateGroup(br, lexer, errors, superGroup);
67 br.close();
68 br = null;
69 }
70 catch (IOException ioe) {
71 error("can't load group "+groupName, ioe);
72 }
73 finally {
74 if ( br!=null ) {
75 try {
76 br.close();
77 }
78 catch (IOException ioe2) {
79 error("Cannot close template group file: "+groupName+".stg", ioe2);
80 }
81 }
82 }
83 return group;
84 }
85
86 public StringTemplateGroup loadGroup(String groupName,
87 StringTemplateGroup superGroup)
88 {
89 return loadGroup(groupName, null, superGroup);
90 }
91
92 public StringTemplateGroup loadGroup(String groupName) {
93 return loadGroup(groupName, null);
94 }
95
96 public StringTemplateGroupInterface loadInterface(String interfaceName) {
97 StringTemplateGroupInterface I = null;
98 try {
99 BufferedReader br = locate(interfaceName+".sti");
100 if ( br==null ) {
101 error("no such interface file "+interfaceName+".sti");
102 return null;
103 }
104 I = new StringTemplateGroupInterface(br, errors);
105 }
106 catch (IOException ioe) {
107 error("can't load interface "+interfaceName, ioe);
108 }
109 return I;
110 }
111
112 /** Look in each directory for the file called 'name'. */
113 protected BufferedReader locate(String name) throws IOException {
114 for (int i = 0; i < dirs.size(); i++) {
115 String dir = (String) dirs.get(i);
116 String fileName = dir+"/"+name;
117 if ( new File(fileName).exists() ) {
118 FileInputStream fis = new FileInputStream(fileName);
119 InputStreamReader isr = getInputStreamReader(fis);
120 return new BufferedReader(isr);
121 }
122 }
123 return null;
124 }
125
126 protected InputStreamReader getInputStreamReader(InputStream in) {
127 InputStreamReader isr = null;
128 try {
129 isr = new InputStreamReader(in, fileCharEncoding);
130 }
131 catch (UnsupportedEncodingException uee) {
132 error("Invalid file character encoding: "+fileCharEncoding);
133 }
134 return isr;
135 }
136
137 public String getFileCharEncoding() {
138 return fileCharEncoding;
139 }
140
141 public void setFileCharEncoding(String fileCharEncoding) {
142 this.fileCharEncoding = fileCharEncoding;
143 }
144
145 public void error(String msg) {
146 error(msg, null);
147 }
148
149 public void error(String msg, Exception e) {
150 if ( errors!=null ) {
151 errors.error(msg,e);
152 }
153 else {
154 System.err.println("StringTemplate: "+msg);
155 if ( e!=null ) {
156 e.printStackTrace();
157 }
158 }
159 }
160 }
0 /*
1 [The "BSD licence"]
2 Copyright (c) 2003-2005 Terence Parr
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package org.antlr.stringtemplate;
28
29 import java.io.*;
30 import java.util.*;
31 import java.lang.reflect.Constructor;
32 import java.lang.reflect.InvocationTargetException;
33
34 import org.antlr.stringtemplate.language.*;
35 import antlr.*;
36 import antlr.collections.AST;
37 import antlr.collections.ASTEnumeration;
38
39 /** A <TT>StringTemplate</TT> is a "document" with holes in it where you can stick
40 * values. <TT>StringTemplate</TT> breaks up your template into chunks of text and
41 * attribute expressions. <TT>StringTemplate</TT> ignores everything outside
42 * of attribute expressions, treating it as just text to spit
43 * out when you call <TT>StringTemplate.toString()</TT>.
44 *
45 */
46 public class StringTemplate {
47 public static final String VERSION = "3.2.1"; // September 22, 2009
48
49 /** <@r()> */
50 public static final int REGION_IMPLICIT = 1;
51 /** <@r>...<@end> */
52 public static final int REGION_EMBEDDED = 2;
53 /** @t.r() ::= "..." defined manually by coder */
54 public static final int REGION_EXPLICIT = 3;
55
56 /** An automatically created aggregate of properties.
57 *
58 * I often have lists of things that need to be formatted, but the list
59 * items are actually pieces of data that are not already in an object. I
60 * need ST to do something like:
61 *
62 * Ter=3432
63 * Tom=32234
64 * ....
65 *
66 * using template:
67 *
68 * $items:{it.name$=$it.type$}$
69 *
70 * This example will call getName() on the objects in items attribute, but
71 * what if they aren't objects? I have perhaps two parallel arrays
72 * instead of a single array of objects containing two fields. One
73 * solution is allow Maps to be handled like properties so that it.name
74 * would fail getName() but then see that it's a Map and do
75 * it.get("name") instead.
76 *
77 * This very clean approach is espoused by some, but the problem is that
78 * it's a hole in my separation rules. People can put the logic in the
79 * view because you could say: "go get bob's data" in the view:
80 *
81 * Bob's Phone: $db.bob.phone$
82 *
83 * A view should not be part of the program and hence should never be able
84 * to go ask for a specific person's data.
85 *
86 * After much thought, I finally decided on a simple solution. I've
87 * added setAttribute variants that pass in multiple property values,
88 * with the property names specified as part of the name using a special
89 * attribute name syntax: "name.{propName1,propName2,...}". This
90 * object is a special kind of HashMap that hopefully prevents people
91 * from passing a subclass or other variant that they have created as
92 * it would be a loophole. Anyway, the ASTExpr.getObjectProperty()
93 * method looks for Aggregate as a special case and does a get() instead
94 * of getPropertyName.
95 */
96 public static final class Aggregate {
97 protected HashMap properties = new HashMap();
98 /** Allow StringTemplate to add values, but prevent the end
99 * user from doing so.
100 */
101 protected void put(String propName, Object propValue) {
102 properties.put(propName, propValue);
103 }
104 public Object get(String propName) {
105 return properties.get(propName);
106 }
107 public String toString() {
108 return properties.toString();
109 }
110 }
111
112 /** Just an alias for ArrayList, but this way I can track whether a
113 * list is something ST created or it's an incoming list.
114 */
115 public static final class STAttributeList extends ArrayList {
116 public STAttributeList(int size) { super(size); }
117 public STAttributeList() { super(); }
118 }
119
120 public static final String ANONYMOUS_ST_NAME = "anonymous";
121
122 /** track probable issues like setting attribute that is not referenced. */
123 static boolean lintMode = false;
124
125 protected List referencedAttributes = null;
126
127 /** What's the name of this template? */
128 protected String name = ANONYMOUS_ST_NAME;
129
130 private static int templateCounter=0;
131 private static synchronized int getNextTemplateCounter() {
132 templateCounter++;
133 return templateCounter;
134 }
135 /** reset the template ID counter to 0; public so that testing routine
136 * can access but not really of interest to the user.
137 */
138 public static void resetTemplateCounter() {
139 templateCounter = 0;
140 }
141
142 protected int templateID = getNextTemplateCounter();
143
144 /** Enclosing instance if I'm embedded within another template.
145 * IF-subtemplates are considered embedded as well.
146 */
147 protected StringTemplate enclosingInstance = null;
148
149 /** If this template is an embedded template such as when you apply
150 * a template to an attribute, then the arguments passed to this
151 * template represent the argument context--a set of values
152 * computed by walking the argument assignment list. For example,
153 * <name:bold(item=name, foo="x")> would result in an
154 * argument context of {[item=name], [foo="x"]} for this
155 * template. This template would be the bold() template and
156 * the enclosingInstance would point at the template that held
157 * that <name:bold(...)> template call. When you want to get
158 * an attribute value, you first check the attributes for the
159 * 'self' template then the arg context then the enclosingInstance
160 * like resolving variables in pascal-like language with nested
161 * procedures.
162 *
163 * With multi-valued attributes such as <faqList:briefFAQDisplay()>
164 * attribute "i" is set to 1..n.
165 */
166 protected Map argumentContext = null;
167
168 /** If this template is embedded in another template, the arguments
169 * must be evaluated just before each application when applying
170 * template to a list of values. The "it" attribute must change
171 * with each application so that $names:bold(item=it)$ works. If
172 * you evaluate once before starting the application loop then it
173 * has a single fixed value. Eval.g saves the AST rather than evaluating
174 * before invoking applyListOfAlternatingTemplates(). Each iteration
175 * of a template application to a multi-valued attribute, these args
176 * are re-evaluated with an initial context of {[it=...], [i=...]}.
177 */
178 protected StringTemplateAST argumentsAST = null;
179
180 /** When templates are defined in a group file format, the attribute
181 * list is provided including information about attribute cardinality
182 * such as present, optional, ... When this information is available,
183 * rawSetAttribute should do a quick existence check as should the
184 * invocation of other templates. So if you ref bold(item="foo") but
185 * item is not defined in bold(), then an exception should be thrown.
186 * When actually rendering the template, the cardinality is checked.
187 * This is a Map<String,FormalArgument>.
188 */
189 protected LinkedHashMap formalArguments = FormalArgument.UNKNOWN;
190
191 /** How many formal arguments to this template have default values
192 * specified?
193 */
194 protected int numberOfDefaultArgumentValues = 0;
195
196 /** Normally, formal parameters hide any attributes inherited from the
197 * enclosing template with the same name. This is normally what you
198 * want, but makes it hard to invoke another template passing in all
199 * the data. Use notation now: <otherTemplate(...)> to say "pass in
200 * all data". Works great. Can also say <otherTemplate(foo="xxx",...)>
201 */
202 protected boolean passThroughAttributes = false;
203
204 /** What group originally defined the prototype for this template?
205 * This affects the set of templates I can refer to. super.t() must
206 * always refer to the super of the original group.
207 *
208 * group base;
209 * t ::= "base";
210 *
211 * group sub;
212 * t ::= "super.t()2"
213 *
214 * group subsub;
215 * t ::= "super.t()3"
216 */
217 protected StringTemplateGroup nativeGroup;
218
219 /** This template was created as part of what group? Even if this
220 * template was created from a prototype in a supergroup, its group
221 * will be the subgroup. That's the way polymorphism works.
222 */
223 protected StringTemplateGroup group;
224
225
226 /** If this template is defined within a group file, what line number? */
227 protected int groupFileLine;
228
229 /** Where to report errors */
230 StringTemplateErrorListener listener = null;
231
232 /** The original, immutable pattern/language (not really used again after
233 * initial "compilation", setup/parsing).
234 */
235 protected String pattern;
236
237 /** Map an attribute name to its value(s). These values are set by outside
238 * code via st.setAttribute(name, value). StringTemplate is like self in
239 * that a template is both the "class def" and "instance". When you
240 * create a StringTemplate or setTemplate, the text is broken up into chunks
241 * (i.e., compiled down into a series of chunks that can be evaluated later).
242 * You can have multiple
243 */
244 protected Map attributes;
245
246 /** A Map<Class,Object> that allows people to register a renderer for
247 * a particular kind of object to be displayed in this template. This
248 * overrides any renderer set for this template's group.
249 *
250 * Most of the time this map is not used because the StringTemplateGroup
251 * has the general renderer map for all templates in that group.
252 * Sometimes though you want to override the group's renderers.
253 */
254 protected Map attributeRenderers;
255
256 /** A list of alternating string and ASTExpr references.
257 * This is compiled to when the template is loaded/defined and walked to
258 * write out a template instance.
259 */
260 protected List chunks;
261
262 /** If someone refs <@r()> in template t, an implicit
263 *
264 * @t.r() ::= ""
265 *
266 * is defined, but you can overwrite this def by defining your
267 * own. We need to prevent more than one manual def though. Between
268 * this var and isEmbeddedRegion we can determine these cases.
269 */
270 protected int regionDefType;
271
272 /** Does this template come from a <@region>...<@end> embedded in
273 * another template?
274 */
275 protected boolean isRegion;
276
277 /** Set of implicit and embedded regions for this template */
278 protected Set regions;
279
280 public static StringTemplateGroup defaultGroup =
281 new StringTemplateGroup("defaultGroup", ".");
282
283 /** Create a blank template with no pattern and no attributes */
284 public StringTemplate() {
285 group = defaultGroup; // make sure has a group even if default
286 }
287
288 /** Create an anonymous template. It has no name just
289 * chunks (which point to this anonymous template) and attributes.
290 */
291 public StringTemplate(String template) {
292 this(null, template);
293 }
294
295 public StringTemplate(String template, Class lexer) {
296 this();
297 setGroup(new StringTemplateGroup("defaultGroup", lexer));
298 setTemplate(template);
299 }
300
301 /** Create an anonymous template with no name, but with a group */
302 public StringTemplate(StringTemplateGroup group, String template) {
303 this();
304 if ( group!=null ) {
305 setGroup(group);
306 }
307 setTemplate(template);
308 }
309
310 public StringTemplate(StringTemplateGroup group,
311 String template,
312 HashMap attributes)
313 {
314 this(group,template);
315 this.attributes = attributes;
316 }
317
318 /** Make the 'to' template look exactly like the 'from' template
319 * except for the attributes. This is like creating an instance
320 * of a class in that the executable code is the same (the template
321 * chunks), but the instance data is blank (the attributes). Do
322 * not copy the enclosingInstance pointer since you will want this
323 * template to eval in a context different from the examplar.
324 */
325 protected void dup(StringTemplate from, StringTemplate to) {
326 to.attributeRenderers = from.attributeRenderers;
327 to.pattern = from.pattern;
328 to.chunks = from.chunks;
329 to.formalArguments = from.formalArguments;
330 to.numberOfDefaultArgumentValues = from.numberOfDefaultArgumentValues;
331 to.name = from.name;
332 to.group = from.group;
333 to.nativeGroup = from.nativeGroup;
334 to.listener = from.listener;
335 to.regions = from.regions;
336 to.isRegion = from.isRegion;
337 to.regionDefType = from.regionDefType;
338 }
339
340 /** Make an instance of this template; it contains an exact copy of
341 * everything (except the attributes and enclosing instance pointer).
342 * So the new template refers to the previously compiled chunks of this
343 * template but does not have any attribute values.
344 */
345 public StringTemplate getInstanceOf() {
346 StringTemplate t = null;
347 if ( nativeGroup!=null ) {
348 // create a template using the native group for this template
349 // but it's "group" is set to this.group by dup after creation so
350 // polymorphism still works.
351 t = nativeGroup.createStringTemplate();
352 }
353 else {
354 t = group.createStringTemplate();
355 }
356 dup(this, t);
357 return t;
358 }
359
360 public StringTemplate getEnclosingInstance() {
361 return enclosingInstance;
362 }
363
364 public StringTemplate getOutermostEnclosingInstance() {
365 if ( enclosingInstance!=null ) {
366 return enclosingInstance.getOutermostEnclosingInstance();
367 }
368 return this;
369 }
370
371 public void setEnclosingInstance(StringTemplate enclosingInstance) {
372 if ( this==enclosingInstance ) {
373 throw new IllegalArgumentException("cannot embed template "+getName()+" in itself");
374 }
375 // set the parent for this template
376 this.enclosingInstance = enclosingInstance;
377 }
378
379 public Map getArgumentContext() {
380 return argumentContext;
381 }
382
383 public void setArgumentContext(Map ac) {
384 argumentContext = ac;
385 }
386
387 public StringTemplateAST getArgumentsAST() {
388 return argumentsAST;
389 }
390
391 public void setArgumentsAST(StringTemplateAST argumentsAST) {
392 this.argumentsAST = argumentsAST;
393 }
394
395 public String getName() {
396 return name;
397 }
398
399 public String getOutermostName() {
400 if ( enclosingInstance!=null ) {
401 return enclosingInstance.getOutermostName();
402 }
403 return getName();
404 }
405
406 public void setName(String name) {
407 this.name = name;
408 }
409
410 public StringTemplateGroup getGroup() {
411 return group;
412 }
413
414 public void setGroup(StringTemplateGroup group) {
415 this.group = group;
416 }
417
418 public StringTemplateGroup getNativeGroup() {
419 return nativeGroup;
420 }
421
422 public void setNativeGroup(StringTemplateGroup nativeGroup) {
423 this.nativeGroup = nativeGroup;
424 }
425
426 /** Return the outermost template's group file line number */
427 public int getGroupFileLine() {
428 if ( enclosingInstance!=null ) {
429 return enclosingInstance.getGroupFileLine();
430 }
431 return groupFileLine;
432 }
433
434 public void setGroupFileLine(int groupFileLine) {
435 this.groupFileLine = groupFileLine;
436 }
437
438 public void setTemplate(String template) {
439 this.pattern = template;
440 breakTemplateIntoChunks();
441 }
442
443 public String getTemplate() {
444 return pattern;
445 }
446
447 public void setErrorListener(StringTemplateErrorListener listener) {
448 this.listener = listener;
449 }
450
451 public StringTemplateErrorListener getErrorListener() {
452 if ( listener==null ) {
453 return group.getErrorListener();
454 }
455 return listener;
456 }
457
458 public void reset() {
459 attributes = new HashMap(); // just throw out table and make new one
460 }
461
462 public void setPredefinedAttributes() {
463 if ( !inLintMode() ) {
464 return; // only do this method so far in lint mode
465 }
466 }
467
468 public void removeAttribute(String name) {
469 if ( attributes!=null ) attributes.remove(name);
470 }
471
472 /** Set an attribute for this template. If you set the same
473 * attribute more than once, you get a multi-valued attribute.
474 * If you send in a StringTemplate object as a value, it's
475 * enclosing instance (where it will inherit values from) is
476 * set to 'this'. This would be the normal case, though you
477 * can set it back to null after this call if you want.
478 * If you send in a List plus other values to the same
479 * attribute, they all get flattened into one List of values.
480 * This will be a new list object so that incoming objects are
481 * not altered.
482 * If you send in an array, it is converted to an ArrayIterator.
483 */
484 public void setAttribute(String name, Object value) {
485 if ( value==null || name==null ) {
486 return;
487 }
488 if ( name.indexOf('.')>=0 ) {
489 throw new IllegalArgumentException("cannot have '.' in attribute names");
490 }
491 if ( attributes==null ) {
492 attributes = new HashMap();
493 }
494
495 if ( value instanceof StringTemplate ) {
496 ((StringTemplate)value).setEnclosingInstance(this);
497 }
498 else {
499 // convert value if array
500 value = ASTExpr.convertArrayToList(value);
501 }
502
503 // convert plain collections
504 // get exactly in this scope (no enclosing)
505 Object o = this.attributes.get(name);
506 if ( o==null ) { // new attribute
507 rawSetAttribute(this.attributes, name, value);
508 return;
509 }
510 // it will be a multi-value attribute
511 //System.out.println("exists: "+name+"="+o);
512 STAttributeList v = null;
513 if ( o.getClass() == STAttributeList.class ) { // already a list made by ST
514 v = (STAttributeList)o;
515 }
516 else if ( o instanceof List ) { // existing attribute is non-ST List
517 // must copy to an ST-managed list before adding new attribute
518 List listAttr = (List)o;
519 v = new STAttributeList(listAttr.size());
520 v.addAll(listAttr);
521 rawSetAttribute(this.attributes, name, v); // replace attribute w/list
522 }
523 else {
524 // non-list second attribute, must convert existing to ArrayList
525 v = new STAttributeList(); // make list to hold multiple values
526 // make it point to list now
527 rawSetAttribute(this.attributes, name, v); // replace attribute w/list
528 v.add(o); // add previous single-valued attribute
529 }
530 if ( value instanceof List ) {
531 // flatten incoming list into existing
532 if ( v!=value ) { // avoid weird cyclic add
533 v.addAll((List)value);
534 }
535 }
536 else {
537 v.add(value);
538 }
539 }
540
541 /** Convenience method to box ints */
542 public void setAttribute(String name, int value) {
543 setAttribute(name, new Integer(value));
544 }
545
546 /** Set an aggregate attribute with two values. The attribute name
547 * must have the format: "name.{propName1,propName2}".
548 */
549 public void setAttribute(String aggrSpec, Object v1, Object v2) {
550 setAttribute(aggrSpec, new Object[] {v1,v2});
551 }
552
553 public void setAttribute(String aggrSpec, Object v1, Object v2, Object v3) {
554 setAttribute(aggrSpec, new Object[] {v1,v2,v3});
555 }
556
557 public void setAttribute(String aggrSpec, Object v1, Object v2, Object v3, Object v4) {
558 setAttribute(aggrSpec, new Object[] {v1,v2,v3,v4});
559 }
560
561 public void setAttribute(String aggrSpec, Object v1, Object v2, Object v3, Object v4, Object v5) {
562 setAttribute(aggrSpec, new Object[] {v1,v2,v3,v4,v5});
563 }
564
565 /** Create an aggregate from the list of properties in aggrSpec and fill
566 * with values from values array. This is not publically visible because
567 * it conflicts semantically with setAttribute("foo",new Object[] {...});
568 */
569 protected void setAttribute(String aggrSpec, Object[] values) {
570 List properties = new ArrayList();
571 String aggrName = parseAggregateAttributeSpec(aggrSpec, properties);
572 if ( values==null || properties.size()==0 ) {
573 throw new IllegalArgumentException("missing properties or values for '"+aggrSpec+"'");
574 }
575 if ( values.length != properties.size() ) {
576 throw new IllegalArgumentException("number of properties in '"+aggrSpec+"' != number of values");
577 }
578 Aggregate aggr = new Aggregate();
579 for (int i = 0; i < values.length; i++) {
580 Object value = values[i];
581 if ( value instanceof StringTemplate ) {
582 ((StringTemplate)value).setEnclosingInstance(this);
583 }
584 else {
585 value = ASTExpr.convertArrayToList(value);
586 }
587 aggr.put((String)properties.get(i), value);
588 }
589 setAttribute(aggrName, aggr);
590 }
591
592 /** Split "aggrName.{propName1,propName2}" into list [propName1,propName2]
593 * and the aggrName. Space is allowed around ','.
594 */
595 protected String parseAggregateAttributeSpec(String aggrSpec, List properties) {
596 int dot = aggrSpec.indexOf('.');
597 if ( dot<=0 ) {
598 throw new IllegalArgumentException("invalid aggregate attribute format: "+
599 aggrSpec);
600 }
601 String aggrName = aggrSpec.substring(0, dot);
602 String propString = aggrSpec.substring(dot+1, aggrSpec.length());
603 boolean error = true;
604 StringTokenizer tokenizer = new StringTokenizer(propString, "{,}", true);
605 match:
606 if ( tokenizer.hasMoreTokens() ) {
607 String token = tokenizer.nextToken(); // advance to {
608 token = token.trim();
609 if ( token.equals("{") ) {
610 token = tokenizer.nextToken(); // advance to first prop name
611 token = token.trim();
612 properties.add(token);
613 token = tokenizer.nextToken(); // advance to a comma
614 token = token.trim();
615 while ( token.equals(",") ) {
616 token = tokenizer.nextToken(); // advance to a prop name
617 token = token.trim();
618 properties.add(token);
619 token = tokenizer.nextToken(); // advance to a "," or "}"
620 token = token.trim();
621 }
622 if ( token.equals("}") ) {
623 error = false;
624 }
625 }
626 }
627 if ( error ) {
628 throw new IllegalArgumentException("invalid aggregate attribute format: "+
629 aggrSpec);
630 }
631 return aggrName;
632 }
633
634 /** Map a value to a named attribute. Throw NoSuchElementException if
635 * the named attribute is not formally defined in self's specific template
636 * and a formal argument list exists.
637 */
638 protected void rawSetAttribute(Map attributes,
639 String name,
640 Object value)
641 {
642 if ( formalArguments!=FormalArgument.UNKNOWN &&
643 getFormalArgument(name)==null )
644 {
645 // a normal call to setAttribute with unknown attribute
646 throw new NoSuchElementException("no such attribute: "+name+
647 " in template context "+
648 getEnclosingInstanceStackString());
649 }
650 if ( value == null ) {
651 return;
652 }
653 attributes.put(name, value);
654 }
655
656 /** Argument evaluation such as foo(x=y), x must
657 * be checked against foo's argument list not this's (which is
658 * the enclosing context). So far, only eval.g uses arg self as
659 * something other than "this".
660 */
661 public void rawSetArgumentAttribute(StringTemplate embedded,
662 Map attributes,
663 String name,
664 Object value)
665 {
666 if ( embedded.formalArguments!=FormalArgument.UNKNOWN &&
667 embedded.getFormalArgument(name)==null )
668 {
669 throw new NoSuchElementException("template "+embedded.getName()+
670 " has no such attribute: "+name+
671 " in template context "+
672 getEnclosingInstanceStackString());
673 }
674 if ( value == null ) {
675 return;
676 }
677 attributes.put(name, value);
678 }
679
680 public Object getAttribute(String name) {
681 Object v = get(this,name);
682 if ( v==null ) {
683 checkNullAttributeAgainstFormalArguments(this, name);
684 }
685 return v;
686 }
687
688 /** Walk the chunks, asking them to write themselves out according
689 * to attribute values of 'this.attributes'. This is like evaluating or
690 * interpreting the StringTemplate as a program using the
691 * attributes. The chunks will be identical (point at same list)
692 * for all instances of this template.
693 */
694 public int write(StringTemplateWriter out) throws IOException {
695 if ( group.debugTemplateOutput ) {
696 group.emitTemplateStartDebugString(this,out);
697 }
698 int n = 0;
699 boolean missing = true;
700 setPredefinedAttributes();
701 setDefaultArgumentValues();
702 for (int i=0; chunks!=null && i<chunks.size(); i++) {
703 Expr a = (Expr)chunks.get(i);
704 int chunkN = a.write(this, out);
705 // expr-on-first-line-with-no-output NEWLINE => NEWLINE
706 if ( chunkN<=0 && i==0 && (i+1)<chunks.size() &&
707 chunks.get(i+1) instanceof NewlineRef )
708 {
709 //System.out.println("found pure first-line-blank \\n pattern");
710 i++; // skip next NEWLINE;
711 continue;
712 }
713 // NEWLINE expr-with-no-output NEWLINE => NEWLINE
714 // Indented $...$ have the indent stored with the ASTExpr
715 // so the indent does not come out as a StringRef
716 if ( chunkN<=0 &&
717 (i-1)>=0 && chunks.get(i-1) instanceof NewlineRef &&
718 (i+1)<chunks.size() && chunks.get(i+1) instanceof NewlineRef )
719 {
720 //System.out.println("found pure \\n blank \\n pattern");
721 i++; // make it skip over the next chunk, the NEWLINE
722 }
723 if ( chunkN!=ASTExpr.MISSING ) {
724 n += chunkN;
725 missing = false;
726 }
727 }
728 if ( group.debugTemplateOutput ) {
729 group.emitTemplateStopDebugString(this,out);
730 }
731 if ( lintMode ) checkForTrouble();
732 if ( missing && chunks!=null && chunks.size()>0 ) return ASTExpr.MISSING;
733 return n;
734 }
735
736 /** Resolve an attribute reference. It can be in four possible places:
737 *
738 * 1. the attribute list for the current template
739 * 2. if self is an embedded template, somebody invoked us possibly
740 * with arguments--check the argument context
741 * 3. if self is an embedded template, the attribute list for the enclosing
742 * instance (recursively up the enclosing instance chain)
743 * 4. if nothing is found in the enclosing instance chain, then it might
744 * be a map defined in the group or the its supergroup etc...
745 *
746 * Attribute references are checked for validity. If an attribute has
747 * a value, its validity was checked before template rendering.
748 * If the attribute has no value, then we must check to ensure it is a
749 * valid reference. Somebody could reference any random value like $xyz$;
750 * formal arg checks before rendering cannot detect this--only the ref
751 * can initiate a validity check. So, if no value, walk up the enclosed
752 * template tree again, this time checking formal parameters not
753 * attributes Map. The formal definition must exist even if no value.
754 *
755 * To avoid infinite recursion in toString(), we have another condition
756 * to check regarding attribute values. If your template has a formal
757 * argument, foo, then foo will hide any value available from "above"
758 * in order to prevent infinite recursion.
759 *
760 * This method is not static so people can override functionality.
761 */
762 public Object get(StringTemplate self, String attribute) {
763 /*
764 System.out.println("### get("+self.getEnclosingInstanceStackString()+", "+attribute+")");
765 System.out.println("attributes="+(self.attributes!=null?self.attributes.keySet().toString():"none"));
766 */
767 if ( self==null ) {
768 return null;
769 }
770
771 if ( lintMode ) {
772 self.trackAttributeReference(attribute);
773 }
774
775 // is it here?
776 Object o = null;
777 if ( self.attributes!=null ) {
778 o = self.attributes.get(attribute);
779 }
780
781 // nope, check argument context in case embedded
782 if ( o==null ) {
783 Map argContext = self.getArgumentContext();
784 if ( argContext!=null ) {
785 o = argContext.get(attribute);
786 }
787 }
788
789 if ( o==null &&
790 !self.passThroughAttributes &&
791 self.getFormalArgument(attribute)!=null )
792 {
793 // if you've defined attribute as formal arg for this
794 // template and it has no value, do not look up the
795 // enclosing dynamic scopes. This avoids potential infinite
796 // recursion.
797 return null;
798 }
799
800 // not locally defined, check enclosingInstance if embedded
801 if ( o==null && self.enclosingInstance!=null ) {
802 /*
803 System.out.println("looking for "+getName()+"."+attribute+" in super="+
804 enclosingInstance.getName());
805 */
806 Object valueFromEnclosing = get(self.enclosingInstance, attribute);
807 /*
808 if ( valueFromEnclosing==null ) {
809 checkNullAttributeAgainstFormalArguments(self, attribute);
810 }
811 */
812 o = valueFromEnclosing;
813 }
814
815 // not found and no enclosing instance to look at
816 else if ( o==null && self.enclosingInstance==null ) {
817 // It might be a map in the group or supergroup...
818 o = self.group.getMap(attribute);
819 }
820
821 return o;
822 }
823
824 /** Walk a template, breaking it into a list of
825 * chunks: Strings and actions/expressions.
826 */
827 protected void breakTemplateIntoChunks() {
828 //System.out.println("parsing template: "+pattern);
829 if ( pattern==null ) {
830 return;
831 }
832 try {
833 // instead of creating a specific template lexer, use
834 // an instance of the class specified by the user.
835 // The default is DefaultTemplateLexer.
836 // The only constraint is that you use an ANTLR lexer
837 // so I can use the special ChunkToken.
838 Class lexerClass = group.getTemplateLexerClass();
839 Constructor ctor =
840 lexerClass.getConstructor(
841 new Class[] {StringTemplate.class,Reader.class}
842 );
843 CharScanner chunkStream =
844 (CharScanner) ctor.newInstance(
845 new Object[] {this,new StringReader(pattern)}
846 );
847 chunkStream.setTokenObjectClass("org.antlr.stringtemplate.language.ChunkToken");
848 TemplateParser chunkifier = new TemplateParser(chunkStream);
849 chunkifier.template(this);
850 //System.out.println("chunks="+chunks);
851 }
852 catch (Exception e) {
853 String name = "<unknown>";
854 String outerName = getOutermostName();
855 if ( getName()!=null ) {
856 name = getName();
857 }
858 if ( outerName!=null && !name.equals(outerName) ) {
859 name = name+" nested in "+outerName;
860 }
861 error("problem parsing template '"+name+"'", e);
862 }
863 }
864
865 public ASTExpr parseAction(String action) {
866 //System.out.println("parse action "+action);
867 ActionLexer lexer =
868 new ActionLexer(new StringReader(action.toString()));
869 ActionParser parser =
870 new ActionParser(lexer, this);
871 parser.setASTNodeClass("org.antlr.stringtemplate.language.StringTemplateAST");
872 lexer.setTokenObjectClass("org.antlr.stringtemplate.language.StringTemplateToken");
873 ASTExpr a = null;
874 try {
875 Map options = parser.action();
876 AST tree = parser.getAST();
877 if ( tree!=null ) {
878 if ( tree.getType()==ActionParser.CONDITIONAL ) {
879 a = new ConditionalExpr(this,tree);
880 }
881 else {
882 a = new ASTExpr(this,tree,options);
883 }
884 }
885 }
886 catch (RecognitionException re) {
887 error("Can't parse chunk: "+action.toString(), re);
888 }
889 catch (TokenStreamException tse) {
890 error("Can't parse chunk: "+action.toString(), tse);
891 }
892 return a;
893 }
894
895 public int getTemplateID() {
896 return templateID;
897 }
898
899 public Map getAttributes() {
900 return attributes;
901 }
902
903 /** Get a list of the strings and subtemplates and attribute
904 * refs in a template.
905 */
906 public List getChunks() {
907 return chunks;
908 }
909
910 public void addChunk(Expr e) {
911 if ( chunks==null ) {
912 chunks = new ArrayList();
913 }
914 chunks.add(e);
915 }
916
917 public void setAttributes(Map attributes) {
918 this.attributes = attributes;
919 }
920
921 // F o r m a l A r g S t u f f
922
923 public Map getFormalArguments() {
924 return formalArguments;
925 }
926
927 public void setFormalArguments(LinkedHashMap args) {
928 formalArguments = args;
929 }
930
931 /** Set any default argument values that were not set by the
932 * invoking template or by setAttribute directly. Note
933 * that the default values may be templates. Their evaluation
934 * context is the template itself and, hence, can see attributes
935 * within the template, any arguments, and any values inherited
936 * by the template.
937 *
938 * Default values are stored in the argument context rather than
939 * the template attributes table just for consistency's sake.
940 */
941 public void setDefaultArgumentValues() {
942 //System.out.println("setDefaultArgumentValues; "+name+": argctx="+argumentContext+", n="+numberOfDefaultArgumentValues);
943 if ( numberOfDefaultArgumentValues==0 ) {
944 return;
945 }
946 if ( argumentContext==null ) {
947 argumentContext = new HashMap();
948 }
949 if ( formalArguments!=FormalArgument.UNKNOWN ) {
950 //System.out.println("formal args="+formalArguments.keySet());
951 Set argNames = formalArguments.keySet();
952 for (Iterator it = argNames.iterator(); it.hasNext();) {
953 String argName = (String) it.next();
954 // use the default value then
955 FormalArgument arg =
956 (FormalArgument)formalArguments.get(argName);
957 if ( arg.defaultValueST!=null ) {
958 //System.out.println("default value="+arg.defaultValueST.chunks);
959 //System.out.println(getEnclosingInstanceStackString()+": get "+argName+" argctx="+argumentContext);
960 Object existingValue = getAttribute(argName);
961 //System.out.println("existing value="+existingValue);
962 if ( existingValue==null ) { // value unset?
963 Object defaultValue = arg.defaultValueST;
964 // if no value for attribute, set arg context
965 // to the default value. We don't need an instance
966 // here because no attributes can be set in
967 // the arg templates by the user.
968 int nchunks = arg.defaultValueST.chunks.size();
969 if ( nchunks==1 ) {
970 // If default arg is template with single expression
971 // wrapped in parens, x={<(...)>}, then eval to string
972 // rather than setting x to the template for later
973 // eval.
974 Object a = arg.defaultValueST.chunks.get(0);
975 if ( a instanceof ASTExpr ) {
976 ASTExpr e = (ASTExpr)a;
977 if ( e.getAST().getType()==ActionEvaluator.VALUE ) {
978 defaultValue = e.evaluateExpression(this, e.getAST());
979 }
980 }
981 }
982 argumentContext.put(argName, defaultValue);
983 }
984 }
985 }
986 }
987 }
988
989 /** From this template upward in the enclosing template tree,
990 * recursively look for the formal parameter.
991 */
992 public FormalArgument lookupFormalArgument(String name) {
993 FormalArgument arg = getFormalArgument(name);
994 if ( arg==null && enclosingInstance!=null ) {
995 arg = enclosingInstance.lookupFormalArgument(name);
996 }
997 return arg;
998 }
999
1000 public FormalArgument getFormalArgument(String name) {
1001 return (FormalArgument)formalArguments.get(name);
1002 }
1003
1004 public void defineEmptyFormalArgumentList() {
1005 setFormalArguments(new LinkedHashMap());
1006 }
1007
1008 public void defineFormalArgument(String name) {
1009 defineFormalArgument(name,null);
1010 }
1011
1012 public void defineFormalArguments(List names) {
1013 if ( names==null ) {
1014 return;
1015 }
1016 for (int i = 0; i < names.size(); i++) {
1017 String name = (String) names.get(i);
1018 defineFormalArgument(name);
1019 }
1020 }
1021
1022 public void defineFormalArgument(String name, StringTemplate defaultValue) {
1023 /*
1024 System.out.println("define formal arg "+this.name+"."+name+
1025 ", def value="+(defaultValue!=null?defaultValue.chunks:"null"));
1026 */
1027 if ( defaultValue!=null ) {
1028 numberOfDefaultArgumentValues++;
1029 }
1030 FormalArgument a = new FormalArgument(name,defaultValue);
1031 if ( formalArguments==FormalArgument.UNKNOWN ) {
1032 formalArguments = new LinkedHashMap();
1033 }
1034 formalArguments.put(name, a);
1035 }
1036
1037 /** Normally if you call template y from x, y cannot see any attributes
1038 * of x that are defined as formal parameters of y. Setting this
1039 * passThroughAttributes to true, will override that and allow a
1040 * template to see through the formal arg list to inherited values.
1041 */
1042 public void setPassThroughAttributes(boolean passThroughAttributes) {
1043 this.passThroughAttributes = passThroughAttributes;
1044 }
1045
1046 /** Specify a complete map of what object classes should map to which
1047 * renderer objects.
1048 */
1049 public void setAttributeRenderers(Map renderers) {
1050 this.attributeRenderers = renderers;
1051 }
1052
1053 /** Register a renderer for all objects of a particular type. This
1054 * overrides any renderer set in the group for this class type.
1055 */
1056 public void registerRenderer(Class attributeClassType, AttributeRenderer renderer) {
1057 if ( attributeRenderers==null ) {
1058 attributeRenderers = new HashMap();
1059 }
1060 attributeRenderers.put(attributeClassType, renderer);
1061 }
1062
1063 /** What renderer is registered for this attributeClassType for
1064 * this template. If not found, the template's group is queried.
1065 */
1066 public AttributeRenderer getAttributeRenderer(Class attributeClassType) {
1067 AttributeRenderer renderer = null;
1068 if ( attributeRenderers!=null ) {
1069 renderer = (AttributeRenderer)attributeRenderers.get(attributeClassType);
1070 }
1071 if ( renderer!=null ) {
1072 // found it!
1073 return renderer;
1074 }
1075
1076 // we have no renderer overrides for the template or none for class arg
1077 // check parent template if we are embedded
1078 if ( enclosingInstance!=null ) {
1079 return enclosingInstance.getAttributeRenderer(attributeClassType);
1080 }
1081 // else check group
1082 return group.getAttributeRenderer(attributeClassType);
1083 }
1084
1085 // U T I L I T Y R O U T I N E S
1086
1087 public void error(String msg) {
1088 error(msg, null);
1089 }
1090
1091 public void warning(String msg) {
1092 if ( getErrorListener()!=null ) {
1093 getErrorListener().warning(msg);
1094 }
1095 else {
1096 System.err.println("StringTemplate: warning: "+msg);
1097 }
1098 }
1099
1100 public void error(String msg, Throwable e) {
1101 if ( getErrorListener()!=null ) {
1102 getErrorListener().error(msg,e);
1103 }
1104 else {
1105 if ( e!=null ) {
1106 System.err.println("StringTemplate: error: "+msg+": "+e.toString());
1107 if ( e instanceof InvocationTargetException ) {
1108 e = ((InvocationTargetException)e).getTargetException();
1109 }
1110 e.printStackTrace(System.err);
1111 }
1112 else {
1113 System.err.println("StringTemplate: error: "+msg);
1114 }
1115 }
1116 }
1117
1118 /** Make StringTemplate check your work as it evaluates templates.
1119 * Problems are sent to error listener. Currently warns when
1120 * you set attributes that are not used.
1121 */
1122 public static void setLintMode(boolean lint) {
1123 StringTemplate.lintMode = lint;
1124 }
1125
1126 public static boolean inLintMode() {
1127 return lintMode;
1128 }
1129
1130 /** Indicates that 'name' has been referenced in this template. */
1131 protected void trackAttributeReference(String name) {
1132 if ( referencedAttributes==null ) {
1133 referencedAttributes = new ArrayList();
1134 }
1135 referencedAttributes.add(name);
1136 }
1137
1138 /** Look up the enclosing instance chain (and include this) to see
1139 * if st is a template already in the enclosing instance chain.
1140 */
1141 public static boolean isRecursiveEnclosingInstance(StringTemplate st) {
1142 if ( st==null ) {
1143 return false;
1144 }
1145 StringTemplate p = st.enclosingInstance;
1146 if ( p==st ) {
1147 return true; // self-recursive
1148 }
1149 // now look for indirect recursion
1150 while ( p!=null ) {
1151 if ( p==st ) {
1152 return true;
1153 }
1154 p = p.enclosingInstance;
1155 }
1156 return false;
1157 }
1158
1159 public String getEnclosingInstanceStackTrace() {
1160 StringBuffer buf = new StringBuffer();
1161 Set seen = new HashSet();
1162 StringTemplate p = this;
1163 while ( p!=null ) {
1164 if ( seen.contains(p) ) {
1165 buf.append(p.getTemplateDeclaratorString());
1166 buf.append(" (start of recursive cycle)");
1167 buf.append("\n");
1168 buf.append("...");
1169 break;
1170 }
1171 seen.add(p);
1172 buf.append(p.getTemplateDeclaratorString());
1173 if ( p.attributes!=null ) {
1174 buf.append(", attributes=[");
1175 int i = 0;
1176 for (Iterator iter = p.attributes.keySet().iterator(); iter.hasNext();) {
1177 String attrName = (String) iter.next();
1178 if ( i>0 ) {
1179 buf.append(", ");
1180 }
1181 i++;
1182 buf.append(attrName);
1183 Object o = p.attributes.get(attrName);
1184 if ( o instanceof StringTemplate ) {
1185 StringTemplate st = (StringTemplate)o;
1186 buf.append("=");
1187 buf.append("<");
1188 buf.append(st.getName());
1189 buf.append("()@");
1190 buf.append(String.valueOf(st.getTemplateID()));
1191 buf.append(">");
1192 }
1193 else if ( o instanceof List ) {
1194 buf.append("=List[..");
1195 List list = (List)o;
1196 int n=0;
1197 for (int j = 0; j < list.size(); j++) {
1198 Object listValue = list.get(j);
1199 if ( listValue instanceof StringTemplate ) {
1200 if ( n>0 ) {
1201 buf.append(", ");
1202 }
1203 n++;
1204 StringTemplate st = (StringTemplate)listValue;
1205 buf.append("<");
1206 buf.append(st.getName());
1207 buf.append("()@");
1208 buf.append(String.valueOf(st.getTemplateID()));
1209 buf.append(">");
1210 }
1211 }
1212 buf.append("..]");
1213 }
1214 }
1215 buf.append("]");
1216 }
1217 if ( p.referencedAttributes!=null ) {
1218 buf.append(", references=");
1219 buf.append(p.referencedAttributes);
1220 }
1221 buf.append(">\n");
1222 p = p.enclosingInstance;
1223 }
1224 /*
1225 if ( enclosingInstance!=null ) {
1226 buf.append(enclosingInstance.getEnclosingInstanceStackTrace());
1227 }
1228 */
1229 return buf.toString();
1230 }
1231
1232 public String getTemplateDeclaratorString() {
1233 StringBuffer buf = new StringBuffer();
1234 buf.append("<");
1235 buf.append(getName());
1236 buf.append("(");
1237 buf.append(formalArguments.keySet());
1238 buf.append(")@");
1239 buf.append(String.valueOf(getTemplateID()));
1240 buf.append(">");
1241 return buf.toString();
1242 }
1243
1244 protected String getTemplateHeaderString(boolean showAttributes) {
1245 if ( showAttributes ) {
1246 StringBuffer buf = new StringBuffer();
1247 buf.append(getName());
1248 if ( attributes!=null ) {
1249 buf.append(attributes.keySet());
1250 }
1251 return buf.toString();
1252 }
1253 return getName();
1254 }
1255
1256 /** Find "missing attribute" and "cardinality mismatch" errors.
1257 * Excecuted before a template writes its chunks out.
1258 * When you find a problem, throw an IllegalArgumentException.
1259 * We must check the attributes as well as the incoming arguments
1260 * in argumentContext.
1261 protected void checkAttributesAgainstFormalArguments() {
1262 Set args = formalArguments.keySet();
1263 /*
1264 if ( (attributes==null||attributes.size()==0) &&
1265 (argumentContext==null||argumentContext.size()==0) &&
1266 formalArguments.size()!=0 )
1267 {
1268 throw new IllegalArgumentException("missing argument(s): "+args+" in template "+getName());
1269 }
1270 Iterator iter = args.iterator();
1271 while ( iter.hasNext() ) {
1272 String argName = (String)iter.next();
1273 FormalArgument arg = getFormalArgument(argName);
1274 int expectedCardinality = arg.getCardinality();
1275 Object value = getAttribute(argName);
1276 int actualCardinality = getActualArgumentCardinality(value);
1277 // if intersection of expected and actual is empty, mismatch
1278 if ( (expectedCardinality&actualCardinality)==0 ) {
1279 throw new IllegalArgumentException("cardinality mismatch: "+
1280 argName+"; expected "+
1281 FormalArgument.getCardinalityName(expectedCardinality)+
1282 " found cardinality="+getObjectLength(value));
1283 }
1284 }
1285 }
1286 */
1287
1288 /** A reference to an attribute with no value, must be compared against
1289 * the formal parameter to see if it exists; if it exists all is well,
1290 * but if not, throw an exception.
1291 *
1292 * Don't do the check if no formal parameters exist for this template;
1293 * ask enclosing.
1294 */
1295 protected void checkNullAttributeAgainstFormalArguments(
1296 StringTemplate self,
1297 String attribute)
1298 {
1299 if ( self.getFormalArguments()==FormalArgument.UNKNOWN ) {
1300 // bypass unknown arg lists
1301 if ( self.enclosingInstance!=null ) {
1302 checkNullAttributeAgainstFormalArguments(
1303 self.enclosingInstance,
1304 attribute);
1305 }
1306 return;
1307 }
1308 FormalArgument formalArg = self.lookupFormalArgument(attribute);
1309 if ( formalArg == null ) {
1310 throw new NoSuchElementException("no such attribute: "+attribute+
1311 " in template context "+getEnclosingInstanceStackString());
1312 }
1313 }
1314
1315 /** Executed after evaluating a template. For now, checks for setting
1316 * of attributes not reference.
1317 */
1318 protected void checkForTrouble() {
1319 // we have table of set values and list of values referenced
1320 // compare, looking for SET BUT NOT REFERENCED ATTRIBUTES
1321 if ( attributes==null ) {
1322 return;
1323 }
1324 Set names = attributes.keySet();
1325 Iterator iter = names.iterator();
1326 // if in names and not in referenced attributes, trouble
1327 while ( iter.hasNext() ) {
1328 String name = (String)iter.next();
1329 if ( referencedAttributes!=null &&
1330 !referencedAttributes.contains(name) )
1331 {
1332 warning(getName()+": set but not used: "+name);
1333 }
1334 }
1335 // can do the reverse, but will have lots of false warnings :(
1336 }
1337
1338 /** If an instance of x is enclosed in a y which is in a z, return
1339 * a String of these instance names in order from topmost to lowest;
1340 * here that would be "[z y x]".
1341 */
1342 public String getEnclosingInstanceStackString() {
1343 List names = new LinkedList();
1344 StringTemplate p = this;
1345 while ( p!=null ) {
1346 String name = p.getName();
1347 names.add(0,name+(p.passThroughAttributes?"(...)":""));
1348 p = p.enclosingInstance;
1349 }
1350 return names.toString().replaceAll(",","");
1351 }
1352
1353 public boolean isRegion() {
1354 return isRegion;
1355 }
1356
1357 public void setIsRegion(boolean isRegion) {
1358 this.isRegion = isRegion;
1359 }
1360
1361 public void addRegionName(String name) {
1362 if ( regions==null ) {
1363 regions = new HashSet();
1364 }
1365 regions.add(name);
1366 }
1367
1368 /** Does this template ref or embed region name? */
1369 public boolean containsRegionName(String name) {
1370 if ( regions==null ) {
1371 return false;
1372 }
1373 return regions.contains(name);
1374 }
1375
1376 public int getRegionDefType() {
1377 return regionDefType;
1378 }
1379
1380 public void setRegionDefType(int regionDefType) {
1381 this.regionDefType = regionDefType;
1382 }
1383
1384 public String toDebugString() {
1385 StringBuffer buf = new StringBuffer();
1386 buf.append("template-"+getTemplateDeclaratorString()+":");
1387 buf.append("chunks=");
1388 if ( chunks!=null ) {
1389 buf.append(chunks.toString());
1390 }
1391 buf.append("attributes=[");
1392 if ( attributes!=null ) {
1393 Set attrNames = attributes.keySet();
1394 int n=0;
1395 for (Iterator iter = attrNames.iterator(); iter.hasNext();) {
1396 if ( n>0 ) {
1397 buf.append(',');
1398 }
1399 String name = (String) iter.next();
1400 buf.append(name+"=");
1401 Object value = attributes.get(name);
1402 if ( value instanceof StringTemplate ) {
1403 buf.append(((StringTemplate)value).toDebugString());
1404 }
1405 else {
1406 buf.append(value);
1407 }
1408 n++;
1409 }
1410 buf.append("]");
1411 }
1412 return buf.toString();
1413 }
1414
1415 /** Don't print values, just report the nested structure with attribute names.
1416 * Follow (nest) attributes that are templates only.
1417 */
1418 public String toStructureString() {
1419 return toStructureString(0);
1420 }
1421
1422 public String toStructureString(int indent) {
1423 StringBuffer buf = new StringBuffer();
1424 for (int i=1; i<=indent; i++) { // indent
1425 buf.append(" ");
1426 }
1427 buf.append(getName());
1428 buf.append(attributes.keySet());
1429 buf.append(":\n");
1430 if ( attributes!=null ) {
1431 Set attrNames = attributes.keySet();
1432 for (Iterator iter = attrNames.iterator(); iter.hasNext();) {
1433 String name = (String) iter.next();
1434 Object value = attributes.get(name);
1435 if ( value instanceof StringTemplate ) { // descend
1436 buf.append(((StringTemplate)value).toStructureString(indent+1));
1437 }
1438 else {
1439 if ( value instanceof List ) {
1440 List alist = (List)value;
1441 for (int i = 0; i < alist.size(); i++) {
1442 Object o = (Object) alist.get(i);
1443 if ( o instanceof StringTemplate ) { // descend
1444 buf.append(((StringTemplate)o).toStructureString(indent+1));
1445 }
1446 }
1447 }
1448 else if ( value instanceof Map ) {
1449 Map m = (Map)value;
1450 Collection mvalues = m.values();
1451 for (Iterator iterator = mvalues.iterator(); iterator.hasNext();) {
1452 Object o = (Object) iterator.next();
1453 if ( o instanceof StringTemplate ) { // descend
1454 buf.append(((StringTemplate)o).toStructureString(indent+1));
1455 }
1456 }
1457 }
1458 }
1459 }
1460 }
1461 return buf.toString();
1462 }
1463
1464 /*
1465 public String getDOTForDependencyGraph(boolean showAttributes) {
1466 StringBuffer buf = new StringBuffer();
1467 buf.append("digraph prof {\n");
1468 HashMap edges = new HashMap();
1469 this.getDependencyGraph(edges, showAttributes);
1470 Set sourceNodes = edges.keySet();
1471 // for each source template
1472 for (Iterator it = sourceNodes.iterator(); it.hasNext();) {
1473 String src = (String) it.next();
1474 Set targetNodes = (Set)edges.get(src);
1475 // for each target template
1476 for (Iterator it2 = targetNodes.iterator(); it2.hasNext();) {
1477 String trg = (String) it2.next();
1478 buf.append('"');
1479 buf.append(src);
1480 buf.append('"');
1481 buf.append("->");
1482 buf.append('"');
1483 buf.append(trg);
1484 buf.append("\"\n");
1485 }
1486 }
1487 buf.append("}");
1488 return buf.toString();
1489 }
1490 */
1491
1492 /** Generate a DOT file for displaying the template enclosure graph; e.g.,
1493 digraph prof {
1494 "t1" -> "t2"
1495 "t1" -> "t3"
1496 "t4" -> "t5"
1497 }
1498 */
1499 public StringTemplate getDOTForDependencyGraph(boolean showAttributes) {
1500 String structure =
1501 "digraph StringTemplateDependencyGraph {\n" +
1502 "node [shape=$shape$, $if(width)$width=$width$,$endif$" +
1503 " $if(height)$height=$height$,$endif$ fontsize=$fontsize$];\n" +
1504 "$edges:{e|\"$e.src$\" -> \"$e.trg$\"\n}$" +
1505 "}\n";
1506 StringTemplate graphST = new StringTemplate(structure);
1507 HashMap edges = new HashMap();
1508 this.getDependencyGraph(edges, showAttributes);
1509 Set sourceNodes = edges.keySet();
1510 // for each source template
1511 for (Iterator it = sourceNodes.iterator(); it.hasNext();) {
1512 String src = (String) it.next();
1513 Set targetNodes = (Set)edges.get(src);
1514 // for each target template
1515 for (Iterator it2 = targetNodes.iterator(); it2.hasNext();) {
1516 String trg = (String) it2.next();
1517 graphST.setAttribute("edges.{src,trg}", src, trg);
1518 }
1519 }
1520 graphST.setAttribute("shape", "none");
1521 graphST.setAttribute("fontsize", "11");
1522 graphST.setAttribute("height", "0"); // make height
1523 return graphST;
1524 }
1525
1526 /** Get a list of n->m edges where template n contains template m.
1527 * The map you pass in is filled with edges: key->value. Useful
1528 * for having DOT print out an enclosing template graph. It
1529 * finds all direct template invocations too like <foo()> but not
1530 * indirect ones like <(name)()>.
1531 *
1532 * Ack, I just realized that this is done statically and hence
1533 * cannot see runtime arg values on statically included templates.
1534 * Hmm...someday figure out to do this dynamically as if we were
1535 * evaluating the templates. There will be extra nodes in the tree
1536 * because we are static like method and method[...] with args.
1537 */
1538 public void getDependencyGraph(Map edges, boolean showAttributes) {
1539 String srcNode = this.getTemplateHeaderString(showAttributes);
1540 if ( attributes!=null ) {
1541 Set attrNames = attributes.keySet();
1542 for (Iterator iter = attrNames.iterator(); iter.hasNext();) {
1543 String name = (String) iter.next();
1544 Object value = attributes.get(name);
1545 if ( value instanceof StringTemplate ) {
1546 String targetNode =
1547 ((StringTemplate)value).getTemplateHeaderString(showAttributes);
1548 putToMultiValuedMap(edges,srcNode,targetNode);
1549 ((StringTemplate)value).getDependencyGraph(edges,showAttributes); // descend
1550 }
1551 else {
1552 if ( value instanceof List ) {
1553 List alist = (List)value;
1554 for (int i = 0; i < alist.size(); i++) {
1555 Object o = (Object) alist.get(i);
1556 if ( o instanceof StringTemplate ) {
1557 String targetNode =
1558 ((StringTemplate)o).getTemplateHeaderString(showAttributes);
1559 putToMultiValuedMap(edges,srcNode,targetNode);
1560 ((StringTemplate)o).getDependencyGraph(edges,showAttributes); // descend
1561 }
1562 }
1563 }
1564 else if ( value instanceof Map ) {
1565 Map m = (Map)value;
1566 Collection mvalues = m.values();
1567 for (Iterator iterator = mvalues.iterator(); iterator.hasNext();) {
1568 Object o = (Object) iterator.next();
1569 if ( o instanceof StringTemplate ) {
1570 String targetNode =
1571 ((StringTemplate)o).getTemplateHeaderString(showAttributes);
1572 putToMultiValuedMap(edges,srcNode,targetNode);
1573 ((StringTemplate)o).getDependencyGraph(edges,showAttributes); // descend
1574 }
1575 }
1576 }
1577 }
1578 }
1579 }
1580 // look in chunks too for template refs
1581 for (int i = 0; chunks!=null && i < chunks.size(); i++) {
1582 Expr expr = (Expr) chunks.get(i);
1583 if ( expr instanceof ASTExpr ) {
1584 ASTExpr e = (ASTExpr)expr;
1585 AST tree = e.getAST();
1586 AST includeAST =
1587 new CommonAST(new CommonToken(ActionEvaluator.INCLUDE,"include"));
1588 ASTEnumeration it = tree.findAllPartial(includeAST);
1589 while (it.hasMoreNodes()) {
1590 AST t = (AST) it.nextNode();
1591 String templateInclude = t.getFirstChild().getText();
1592 System.out.println("found include "+templateInclude);
1593 putToMultiValuedMap(edges,srcNode,templateInclude);
1594 StringTemplateGroup group = getGroup();
1595 if ( group!=null ) {
1596 StringTemplate st = group.getInstanceOf(templateInclude);
1597 // descend into the reference template
1598 st.getDependencyGraph(edges, showAttributes);
1599 }
1600 }
1601 }
1602 }
1603 }
1604
1605 /** Manage a hash table like it has multiple unique values. Map<Object,Set>. */
1606 protected void putToMultiValuedMap(Map map, Object key, Object value) {
1607 HashSet bag = (HashSet)map.get(key);
1608 if ( bag==null ) {
1609 bag = new HashSet();
1610 map.put(key, bag);
1611 }
1612 bag.add(value);
1613 }
1614
1615 public void printDebugString() {
1616 System.out.println("template-"+getName()+":");
1617 System.out.print("chunks=");
1618 System.out.println(chunks.toString());
1619 if ( attributes==null ) {
1620 return;
1621 }
1622 System.out.print("attributes=[");
1623 Set attrNames = attributes.keySet();
1624 int n=0;
1625 for (Iterator iter = attrNames.iterator(); iter.hasNext();) {
1626 if ( n>0 ) {
1627 System.out.print(',');
1628 }
1629 String name = (String) iter.next();
1630 Object value = attributes.get(name);
1631 if ( value instanceof StringTemplate ) {
1632 System.out.print(name+"=");
1633 ((StringTemplate)value).printDebugString();
1634 }
1635 else {
1636 if ( value instanceof List ) {
1637 ArrayList alist = (ArrayList)value;
1638 for (int i = 0; i < alist.size(); i++) {
1639 Object o = (Object) alist.get(i);
1640 System.out.print(name+"["+i+"] is "+o.getClass().getName()+"=");
1641 if ( o instanceof StringTemplate ) {
1642 ((StringTemplate)o).printDebugString();
1643 }
1644 else {
1645 System.out.println(o);
1646 }
1647 }
1648 }
1649 else {
1650 System.out.print(name+"=");
1651 System.out.println(value);
1652 }
1653 }
1654 n++;
1655 }
1656 System.out.print("]\n");
1657 }
1658
1659 public String toString() {
1660 return toString(StringTemplateWriter.NO_WRAP);
1661 }
1662
1663 public String toString(int lineWidth) {
1664 StringWriter out = new StringWriter();
1665 // Write the output to a StringWriter
1666 StringTemplateWriter wr = group.getStringTemplateWriter(out);
1667 wr.setLineWidth(lineWidth);
1668 try {
1669 write(wr);
1670 }
1671 catch (IOException io) {
1672 error("Got IOException writing to writer "+wr.getClass().getName());
1673 }
1674 // reset so next toString() does not wrap; normally this is a new writer
1675 // each time, but just in case they override the group to reuse the
1676 // writer.
1677 wr.setLineWidth(StringTemplateWriter.NO_WRAP);
1678 return out.toString();
1679 }
1680
1681 }
0 /*
1 [The "BSD licence"]
2 Copyright (c) 2003-2005 Terence Parr
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package org.antlr.stringtemplate;
28
29 /** Lets you specify where errors, warnings go. Warning: debug is useful at
30 * the moment.
31 */
32 public interface StringTemplateErrorListener {
33 public void error(String msg, Throwable e);
34 public void warning(String msg);
35 }
0 /*
1 [The "BSD licence"]
2 Copyright (c) 2003-2005 Terence Parr
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package org.antlr.stringtemplate;
28
29 import org.antlr.stringtemplate.language.DefaultTemplateLexer;
30 import org.antlr.stringtemplate.language.GroupLexer;
31 import org.antlr.stringtemplate.language.GroupParser;
32 import org.antlr.stringtemplate.language.AngleBracketTemplateLexer;
33
34 import java.util.*;
35 import java.io.*;
36 import java.lang.reflect.Constructor;
37
38 /** Manages a group of named mutually-referential StringTemplate objects.
39 * Currently the templates must all live under a directory so that you
40 * can reference them as foo.st or gutter/header.st. To refresh a
41 * group of templates, just create a new StringTemplateGroup and start
42 * pulling templates from there. Or, set the refresh interval.
43 *
44 * Use getInstanceOf(template-name) to get a string template
45 * to fill in.
46 *
47 * The name of a template is the file name minus ".st" ending if present
48 * unless you name it as you load it.
49 *
50 * You can use the group file format also to define a group of templates
51 * (this works better for code gen than for html page gen). You must give
52 * a Reader to the ctor for it to load the group; this is general and
53 * distinguishes it from the ctors for the old-style "load template files
54 * from the disk".
55 *
56 * 10/2005 I am adding a StringTemplateGroupLoader concept so people can define supergroups
57 * within a group and have it load that group automatically.
58 */
59 public class StringTemplateGroup {
60 /** What is the group name */
61 protected String name;
62
63 /** Maps template name to StringTemplate object */
64 protected Map templates = new HashMap();
65
66 /** Maps map names to HashMap objects. This is the list of maps
67 * defined by the user like typeInitMap ::= ["int":"0"]
68 */
69 protected Map maps = new HashMap();
70
71 /** How to pull apart a template into chunks? */
72 protected Class templateLexerClass = null;
73
74 /** You can set the lexer once if you know all of your groups use the
75 * same separator. If the instance has templateLexerClass set
76 * then it is used as an override.
77 */
78 protected static Class defaultTemplateLexerClass = DefaultTemplateLexer.class;
79
80 /** Under what directory should I look for templates? If null,
81 * to look into the CLASSPATH for templates as resources.
82 */
83 protected String rootDir = null;
84
85 /** Track all groups by name; maps name to StringTemplateGroup */
86 protected static Map nameToGroupMap = Collections.synchronizedMap(new HashMap());
87
88 /** Track all interfaces by name; maps name to StringTemplateGroupInterface */
89 protected static Map nameToInterfaceMap = Collections.synchronizedMap(new HashMap());
90
91 /** Are we derived from another group? Templates not found in this group
92 * will be searched for in the superGroup recursively.
93 */
94 protected StringTemplateGroup superGroup = null;
95
96 /** Keep track of all interfaces implemented by this group. */
97 protected List interfaces = null;
98
99 /** When templates are files on the disk, the refresh interval is used
100 * to know when to reload. When a Reader is passed to the ctor,
101 * it is a stream full of template definitions. The former is used
102 * for web development, but the latter is most likely used for source
103 * code generation for translators; a refresh is unlikely. Anyway,
104 * I decided to track the source of templates in case such info is useful
105 * in other situations than just turning off refresh interval. I just
106 * found another: don't ever look on the disk for individual templates
107 * if this group is a group file...immediately look into any super group.
108 * If not in the super group, report no such template.
109 */
110 protected boolean templatesDefinedInGroupFile = false;
111
112 /** Normally AutoIndentWriter is used to filter output, but user can
113 * specify a new one.
114 */
115 protected Class userSpecifiedWriter;
116
117 protected boolean debugTemplateOutput = false;
118
119 /** The set of templates to ignore when dumping start/stop debug strings */
120 protected Set noDebugStartStopStrings;
121
122 /** A Map<Class,Object> that allows people to register a renderer for
123 * a particular kind of object to be displayed for any template in this
124 * group. For example, a date should be formatted differently depending
125 * on the locale. You can set Date.class to an object whose
126 * toString(Object) method properly formats a Date attribute
127 * according to locale. Or you can have a different renderer object
128 * for each locale.
129 *
130 * These render objects are used way down in the evaluation chain
131 * right before an attribute's toString() method would normally be
132 * called in ASTExpr.write().
133 *
134 * Synchronized at creation time.
135 */
136 protected Map attributeRenderers;
137
138 /** Maps obj.prop to a value to avoid reflection costs; track one
139 * set of all class.property -> Member mappings for all ST usage in VM.
140 protected static Map classPropertyCache = new HashMap();
141
142 public static class ClassPropCacheKey {
143 Class c;
144 String propertyName;
145 public ClassPropCacheKey(Class c, String propertyName) {
146 this.c=c;
147 this.propertyName=propertyName;
148 }
149
150 public boolean equals(Object other) {
151 ClassPropCacheKey otherKey = (ClassPropCacheKey)other;
152 return c.equals(otherKey.c) &&
153 propertyName.equals(otherKey.propertyName);
154 }
155
156 public int hashCode() {
157 return c.hashCode()+propertyName.hashCode();
158 }
159 }
160 */
161
162 /** If a group file indicates it derives from a supergroup, how do we
163 * find it? Shall we make it so the initial StringTemplateGroup file
164 * can be loaded via this loader? Right now we pass a Reader to ctor
165 * to distinguish from the other variety.
166 */
167 private static StringTemplateGroupLoader groupLoader = null;
168
169 /** Where to report errors. All string templates in this group
170 * use this error handler by default.
171 */
172 protected StringTemplateErrorListener listener = DEFAULT_ERROR_LISTENER;
173
174 public static StringTemplateErrorListener DEFAULT_ERROR_LISTENER =
175 new StringTemplateErrorListener() {
176 public void error(String s, Throwable e) {
177 System.err.println(s);
178 if ( e!=null ) {
179 e.printStackTrace(System.err);
180 }
181 }
182 public void warning(String s) {
183 System.out.println(s);
184 }
185 };
186
187 /** Used to indicate that the template doesn't exist.
188 * We don't have to check disk for it; we know it's not there.
189 */
190 protected static final StringTemplate NOT_FOUND_ST =
191 new StringTemplate();
192
193 /** How long before tossing out all templates in seconds. */
194 protected int refreshIntervalInSeconds = Integer.MAX_VALUE/1000; // default: no refreshing from disk
195 protected long lastCheckedDisk = 0L;
196
197 /** How are the files encoded (ascii, UTF8, ...)? You might want to read
198 * UTF8 for example on an ascii machine.
199 */
200 String fileCharEncoding = System.getProperty("file.encoding");
201
202 /** Create a group manager for some templates, all of which are
203 * at or below the indicated directory.
204 */
205 public StringTemplateGroup(String name, String rootDir) {
206 this(name,rootDir,DefaultTemplateLexer.class);
207 }
208
209 public StringTemplateGroup(String name, String rootDir, Class lexer) {
210 this.name = name;
211 this.rootDir = rootDir;
212 lastCheckedDisk = System.currentTimeMillis();
213 nameToGroupMap.put(name, this);
214 this.templateLexerClass = lexer;
215 }
216
217 /** Create a group manager for some templates, all of which are
218 * loaded as resources via the classloader.
219 */
220 public StringTemplateGroup(String name) {
221 this(name,null,null);
222 }
223
224 public StringTemplateGroup(String name, Class lexer) {
225 this(name,null,lexer);
226 }
227
228 /** Create a group from the template group defined by a input stream.
229 * The name is pulled from the file. The format is
230 *
231 * group name;
232 *
233 * t1(args) ::= "..."
234 * t2() ::= <<
235 * >>
236 * ...
237 */
238 public StringTemplateGroup(Reader r) {
239 this(r,AngleBracketTemplateLexer.class,DEFAULT_ERROR_LISTENER,(StringTemplateGroup)null);
240 }
241
242 public StringTemplateGroup(Reader r, StringTemplateErrorListener errors) {
243 this(r,AngleBracketTemplateLexer.class,errors,(StringTemplateGroup)null);
244 }
245
246 public StringTemplateGroup(Reader r, Class lexer) {
247 this(r,lexer,null,(StringTemplateGroup)null);
248 }
249
250 public StringTemplateGroup(Reader r, Class lexer, StringTemplateErrorListener errors) {
251 this(r,lexer,errors,(StringTemplateGroup)null);
252 }
253
254 /** Create a group from the input stream, but use a nondefault lexer
255 * to break the templates up into chunks. This is usefor changing
256 * the delimiter from the default $...$ to <...>, for example.
257 */
258 public StringTemplateGroup(Reader r,
259 Class lexer,
260 StringTemplateErrorListener errors,
261 StringTemplateGroup superGroup)
262 {
263 this.templatesDefinedInGroupFile = true;
264 // if no lexer specified, then assume <...> when loading from group file
265 if ( lexer==null ) {
266 lexer = AngleBracketTemplateLexer.class;
267 }
268 this.templateLexerClass = lexer;
269 if ( errors!=null ) { // always have to have a listener
270 this.listener = errors;
271 }
272 setSuperGroup(superGroup);
273 parseGroup(r);
274 nameToGroupMap.put(name, this);
275 verifyInterfaceImplementations();
276 }
277
278 /** What lexer class to use to break up templates. If not lexer set
279 * for this group, use static default.
280 */
281 public Class getTemplateLexerClass() {
282 if ( templateLexerClass!=null ) {
283 return templateLexerClass;
284 }
285 return defaultTemplateLexerClass;
286 }
287
288 public String getName() {
289 return name;
290 }
291
292 public void setName(String name) {
293 this.name = name;
294 }
295
296 public void setSuperGroup(StringTemplateGroup superGroup) {
297 this.superGroup = superGroup;
298 }
299
300 /** Called by group parser when ": supergroupname" is found.
301 * This method forces the supergroup's lexer to be same as lexer
302 * for this (sub) group.
303 */
304 public void setSuperGroup(String superGroupName) {
305 StringTemplateGroup superGroup =
306 (StringTemplateGroup)nameToGroupMap.get(superGroupName);
307 if ( superGroup !=null ) { // we've seen before; just use it
308 setSuperGroup(superGroup);
309 return;
310 }
311 // else load it using this group's template lexer
312 superGroup = loadGroup(superGroupName, this.templateLexerClass, null);
313 if ( superGroup !=null ) {
314 nameToGroupMap.put(superGroupName, superGroup);
315 setSuperGroup(superGroup);
316 }
317 else {
318 if ( groupLoader==null ) {
319 listener.error("no group loader registered", null);
320 }
321 }
322 }
323
324 /** Just track the new interface; check later. Allows dups, but no biggie. */
325 public void implementInterface(StringTemplateGroupInterface I) {
326 if ( interfaces==null ) {
327 interfaces = new ArrayList();
328 }
329 interfaces.add(I);
330 }
331
332 /** Indicate that this group implements this interface; load if necessary
333 * if not in the nameToInterfaceMap.
334 */
335 public void implementInterface(String interfaceName) {
336 StringTemplateGroupInterface I =
337 (StringTemplateGroupInterface)nameToInterfaceMap.get(interfaceName);
338 if ( I!=null ) { // we've seen before; just use it
339 implementInterface(I);
340 return;
341 }
342 I = loadInterface(interfaceName); // else load it
343 if ( I!=null ) {
344 nameToInterfaceMap.put(interfaceName, I);
345 implementInterface(I);
346 }
347 else {
348 if ( groupLoader==null ) {
349 listener.error("no group loader registered", null);
350 }
351 }
352 }
353
354 public StringTemplateGroup getSuperGroup() {
355 return superGroup;
356 }
357
358 /** Walk up group hierarchy and show top down to this group */
359 public String getGroupHierarchyStackString() {
360 List groupNames = new LinkedList();
361 StringTemplateGroup p = this;
362 while ( p!=null ) {
363 groupNames.add(0,p.name);
364 p = p.superGroup;
365 }
366 return groupNames.toString().replaceAll(",","");
367 }
368
369 public String getRootDir() {
370 return rootDir;
371 }
372
373 public void setRootDir(String rootDir) {
374 this.rootDir = rootDir;
375 }
376
377 /** StringTemplate object factory; each group can have its own. */
378 public StringTemplate createStringTemplate() {
379 StringTemplate st = new StringTemplate();
380 return st;
381 }
382
383 /** A support routine that gets an instance of name knowing which
384 * ST encloses it for error messages.
385 */
386 protected StringTemplate getInstanceOf(StringTemplate enclosingInstance,
387 String name)
388 throws IllegalArgumentException
389 {
390 //System.out.println("getInstanceOf("+getName()+"::"+name+")");
391 StringTemplate st = lookupTemplate(enclosingInstance,name);
392 if ( st!=null ) {
393 StringTemplate instanceST = st.getInstanceOf();
394 return instanceST;
395 }
396 return null;
397 }
398
399 /** The primary means of getting an instance of a template from this
400 * group.
401 */
402 public StringTemplate getInstanceOf(String name) {
403 return getInstanceOf(null, name);
404 }
405
406 /** The primary means of getting an instance of a template from this
407 * group when you have a predefined set of attributes you want to
408 * use.
409 */
410 public StringTemplate getInstanceOf(String name, Map attributes) {
411 StringTemplate st = getInstanceOf(name);
412 st.attributes = attributes;
413 return st;
414 }
415
416 public StringTemplate getEmbeddedInstanceOf(StringTemplate enclosingInstance,
417 String name)
418 throws IllegalArgumentException
419 {
420 /*
421 System.out.println("surrounding group is "+
422 enclosingInstance.getGroup().getName()+
423 " with native group "+enclosingInstance.getNativeGroup().getName());
424 */
425 StringTemplate st = null;
426 // TODO: seems like this should go into lookupTemplate
427 if ( name.startsWith("super.") ) {
428 // for super.foo() refs, ensure that we look at the native
429 // group for the embedded instance not the current evaluation
430 // group (which is always pulled down to the original group
431 // from which somebody did group.getInstanceOf("foo");
432 st = enclosingInstance.getNativeGroup().getInstanceOf(enclosingInstance, name);
433 }
434 else {
435 st = getInstanceOf(enclosingInstance, name);
436 }
437 // make sure all embedded templates have the same group as enclosing
438 // so that polymorphic refs will start looking at the original group
439 st.setGroup(this);
440 st.setEnclosingInstance(enclosingInstance);
441 return st;
442 }
443
444 /** Get the template called 'name' from the group. If not found,
445 * attempt to load. If not found on disk, then try the superGroup
446 * if any. If not even there, then record that it's
447 * NOT_FOUND so we don't waste time looking again later. If we've gone
448 * past refresh interval, flush and look again.
449 *
450 * If I find a template in a super group, copy an instance down here
451 */
452 public synchronized StringTemplate lookupTemplate(StringTemplate enclosingInstance,
453 String name)
454 throws IllegalArgumentException
455 {
456 //System.out.println("look up "+getName()+"::"+name);
457 if ( name.startsWith("super.") ) {
458 if ( superGroup!=null ) {
459 int dot = name.indexOf('.');
460 name = name.substring(dot+1,name.length());
461 StringTemplate superScopeST =
462 superGroup.lookupTemplate(enclosingInstance,name);
463 /*
464 System.out.println("superScopeST is "+
465 superScopeST.getGroup().getName()+"::"+name+
466 " with native group "+superScopeST.getNativeGroup().getName());
467 */
468 return superScopeST;
469 }
470 throw new IllegalArgumentException(getName()+
471 " has no super group; invalid template: "+name);
472 }
473 checkRefreshInterval();
474 StringTemplate st = (StringTemplate)templates.get(name);
475 if ( st==null ) {
476 // not there? Attempt to load
477 if ( !templatesDefinedInGroupFile ) {
478 // only check the disk for individual template
479 st = loadTemplateFromBeneathRootDirOrCLASSPATH(getFileNameFromTemplateName(name));
480 }
481 if ( st==null && superGroup!=null ) {
482 // try to resolve in super group
483 st = superGroup.getInstanceOf(name);
484 // make sure that when we inherit a template, that it's
485 // group is reset; it's nativeGroup will remain where it was
486 if ( st!=null ) {
487 st.setGroup(this);
488 }
489 }
490 if ( st!=null ) { // found in superGroup
491 // insert into this group; refresh will allow super
492 // to change it's def later or this group to add
493 // an override.
494 templates.put(name, st);
495 }
496 else {
497 // not found; remember that this sucker doesn't exist
498 templates.put(name, NOT_FOUND_ST);
499 String context = "";
500 if ( enclosingInstance!=null ) {
501 context = "; context is "+
502 enclosingInstance.getEnclosingInstanceStackString();
503 }
504 String hier = getGroupHierarchyStackString();
505 context += "; group hierarchy is "+hier;
506 throw new IllegalArgumentException("Can't find template "+
507 getFileNameFromTemplateName(name)+
508 context);
509 }
510 }
511 else if ( st==NOT_FOUND_ST ) {
512 return null;
513 }
514 //System.out.println("lookup found "+st.getGroup().getName()+"::"+st.getName());
515 return st;
516 }
517
518 public StringTemplate lookupTemplate(String name) {
519 return lookupTemplate(null, name);
520 }
521
522 protected void checkRefreshInterval() {
523 if ( templatesDefinedInGroupFile ) {
524 return;
525 }
526 boolean timeToFlush=refreshIntervalInSeconds==0 ||
527 (System.currentTimeMillis()-lastCheckedDisk)>=refreshIntervalInSeconds*1000;
528 if ( timeToFlush ) {
529 // throw away all pre-compiled references
530 templates.clear();
531 lastCheckedDisk = System.currentTimeMillis();
532 }
533 }
534
535 protected StringTemplate loadTemplate(String name, BufferedReader r)
536 throws IOException
537 {
538 String line;
539 String nl = System.getProperty("line.separator");
540 StringBuffer buf = new StringBuffer(300);
541 while ((line = r.readLine()) != null) {
542 buf.append(line);
543 buf.append(nl);
544 }
545 // strip newlines etc.. from front/back since filesystem
546 // may add newlines etc...
547 String pattern = buf.toString().trim();
548 if ( pattern.length()==0 ) {
549 error("no text in template '"+name+"'");
550 return null;
551 }
552 return defineTemplate(name, pattern);
553 }
554
555 /** Load a template whose name is derived from the template filename.
556 * If there is no root directory, try to load the template from
557 * the classpath. If there is a rootDir, try to load the file
558 * from there.
559 */
560 protected StringTemplate loadTemplateFromBeneathRootDirOrCLASSPATH(String fileName)
561 {
562 StringTemplate template = null;
563 String name = getTemplateNameFromFileName(fileName);
564 // if no rootDir, try to load as a resource in CLASSPATH
565 if ( rootDir==null ) {
566 ClassLoader cl = Thread.currentThread().getContextClassLoader();
567 InputStream is = cl.getResourceAsStream(fileName);
568 if ( is==null ) {
569 cl = this.getClass().getClassLoader();
570 is = cl.getResourceAsStream(fileName);
571 }
572 if ( is==null ) {
573 return null;
574 }
575 BufferedReader br = null;
576 try {
577 br = new BufferedReader(getInputStreamReader(is));
578 template = loadTemplate(name, br);
579 }
580 catch (IOException ioe) {
581 error("Problem reading template file: "+fileName,ioe);
582 }
583 finally {
584 if ( br!=null ) {
585 try {
586 br.close();
587 }
588 catch (IOException ioe2) {
589 error("Cannot close template file: "+fileName, ioe2);
590 }
591 }
592 }
593 return template;
594 }
595 // load via rootDir
596 template = loadTemplate(name, rootDir+"/"+fileName);
597 return template;
598 }
599
600 /** (public so that people can override behavior; not a general
601 * purpose method)
602 */
603 public String getFileNameFromTemplateName(String templateName) {
604 return templateName+".st";
605 }
606
607 /** Convert a filename relativePath/name.st to relativePath/name.
608 * (public so that people can override behavior; not a general
609 * purpose method)
610 */
611 public String getTemplateNameFromFileName(String fileName) {
612 String name = fileName;
613 int suffix = name.lastIndexOf(".st");
614 if ( suffix>=0 ) {
615 name = name.substring(0, suffix);
616 }
617 return name;
618 }
619
620 protected StringTemplate loadTemplate(String name, String fileName)
621 {
622 BufferedReader br = null;
623 StringTemplate template = null;
624 try {
625 InputStream fin = new FileInputStream(fileName);
626 InputStreamReader isr = getInputStreamReader(fin);
627 br = new BufferedReader(isr);
628 template = loadTemplate(name, br);
629 br.close();
630 br = null;
631 }
632 catch (IOException ioe) {
633 if ( br!=null ) {
634 try {
635 br.close();
636 }
637 catch (IOException ioe2) {
638 error("Cannot close template file: "+fileName);
639 }
640 }
641 }
642 return template;
643 }
644
645 protected InputStreamReader getInputStreamReader(InputStream in) {
646 InputStreamReader isr = null;
647 try {
648 isr = new InputStreamReader(in, fileCharEncoding);
649 }
650 catch (UnsupportedEncodingException uee) {
651 error("Invalid file character encoding: "+fileCharEncoding);
652 }
653 return isr;
654 }
655
656 public String getFileCharEncoding() {
657 return fileCharEncoding;
658 }
659
660 public void setFileCharEncoding(String fileCharEncoding) {
661 this.fileCharEncoding = fileCharEncoding;
662 }
663
664 /** Define an examplar template; precompiled and stored
665 * with no attributes. Remove any previous definition.
666 */
667 public synchronized StringTemplate defineTemplate(String name,
668 String template)
669 {
670 //System.out.println("defineTemplate "+getName()+"::"+name);
671 if ( name!=null && name.indexOf('.')>=0 ) {
672 throw new IllegalArgumentException("cannot have '.' in template names");
673 }
674 StringTemplate st = createStringTemplate();
675 st.setName(name);
676 st.setGroup(this);
677 st.setNativeGroup(this);
678 st.setTemplate(template);
679 st.setErrorListener(listener);
680 templates.put(name, st);
681 return st;
682 }
683
684 /** Track all references to regions <@foo>...<@end> or <@foo()>. */
685 public StringTemplate defineRegionTemplate(String enclosingTemplateName,
686 String regionName,
687 String template,
688 int type)
689 {
690 String mangledName =
691 getMangledRegionName(enclosingTemplateName,regionName);
692 StringTemplate regionST = defineTemplate(mangledName, template);
693 regionST.setIsRegion(true);
694 regionST.setRegionDefType(type);
695 return regionST;
696 }
697
698 /** Track all references to regions <@foo>...<@end> or <@foo()>. */
699 public StringTemplate defineRegionTemplate(StringTemplate enclosingTemplate,
700 String regionName,
701 String template,
702 int type)
703 {
704 StringTemplate regionST =
705 defineRegionTemplate(enclosingTemplate.getOutermostName(),
706 regionName,
707 template,
708 type);
709 enclosingTemplate.getOutermostEnclosingInstance().addRegionName(regionName);
710 return regionST;
711 }
712
713 /** Track all references to regions <@foo()>. We automatically
714 * define as
715 *
716 * @enclosingtemplate.foo() ::= ""
717 *
718 * You cannot set these manually in the same group; you have to subgroup
719 * to override.
720 */
721 public StringTemplate defineImplicitRegionTemplate(StringTemplate enclosingTemplate,
722 String name)
723 {
724 return defineRegionTemplate(enclosingTemplate,
725 name,
726 "",
727 StringTemplate.REGION_IMPLICIT);
728
729 }
730
731 /** The "foo" of t() ::= "<@foo()>" is mangled to "region#t#foo" */
732 public String getMangledRegionName(String enclosingTemplateName,
733 String name)
734 {
735 return "region__"+enclosingTemplateName+"__"+name;
736 }
737
738 /** Return "t" from "region__t__foo" */
739 public String getUnMangledTemplateName(String mangledName)
740 {
741 return mangledName.substring("region__".length(),
742 mangledName.lastIndexOf("__"));
743 }
744
745 /** Make name and alias for target. Replace any previous def of name */
746 public synchronized StringTemplate defineTemplateAlias(String name, String target) {
747 StringTemplate targetST=getTemplateDefinition(target);
748 if ( targetST==null ){
749 error("cannot alias "+name+" to undefined template: "+target);
750 return null;
751 }
752 templates.put(name, targetST);
753 return targetST;
754 }
755
756 public synchronized boolean isDefinedInThisGroup(String name) {
757 StringTemplate st = (StringTemplate)templates.get(name);
758 if ( st!=null ) {
759 if ( st.isRegion() ) {
760 // don't allow redef of @t.r() ::= "..." or <@r>...<@end>
761 if ( st.getRegionDefType()==StringTemplate.REGION_IMPLICIT ) {
762 return false;
763 }
764 }
765 return true;
766 }
767 return false;
768 }
769
770 /** Get the ST for 'name' in this group only */
771 public synchronized StringTemplate getTemplateDefinition(String name) {
772 return (StringTemplate)templates.get(name);
773 }
774
775 /** Is there *any* definition for template 'name' in this template
776 * or above it in the group hierarchy?
777 */
778 public boolean isDefined(String name) {
779 try {
780 return lookupTemplate(name)!=null;
781 }
782 catch (IllegalArgumentException iae) {
783 return false;
784 }
785 }
786
787 protected void parseGroup(Reader r) {
788 try {
789 GroupLexer lexer = new GroupLexer(r);
790 GroupParser parser = new GroupParser(lexer);
791 parser.group(this);
792 //System.out.println("read group\n"+this.toString());
793 }
794 catch (Exception e) {
795 String name = "<unknown>";
796 if ( getName()!=null ) {
797 name = getName();
798 }
799 error("problem parsing group "+name+": "+e, e);
800 }
801 }
802
803 /** verify that this group satisfies its interfaces */
804 protected void verifyInterfaceImplementations() {
805 for (int i = 0; interfaces!=null && i < interfaces.size(); i++) {
806 StringTemplateGroupInterface I =
807 (StringTemplateGroupInterface)interfaces.get(i);
808 List missing = I.getMissingTemplates(this);
809 List mismatched = I.getMismatchedTemplates(this);
810 if ( missing!=null ) {
811 error("group "+getName()+" does not satisfy interface "+
812 I.getName()+": missing templates "+missing);
813 }
814 if ( mismatched!=null ) {
815 error("group "+getName()+" does not satisfy interface "+
816 I.getName()+": mismatched arguments on these templates "+mismatched);
817 }
818 }
819 }
820
821 public int getRefreshInterval() {
822 return refreshIntervalInSeconds;
823 }
824
825 /** How often to refresh all templates from disk. This is a crude
826 * mechanism at the moment--just tosses everything out at this
827 * frequency. Set interval to 0 to refresh constantly (no caching).
828 * Set interval to a huge number like MAX_INT to have no refreshing
829 * at all (DEFAULT); it will cache stuff.
830 */
831 public void setRefreshInterval(int refreshInterval) {
832 this.refreshIntervalInSeconds = refreshInterval;
833 }
834
835 public void setErrorListener(StringTemplateErrorListener listener) {
836 this.listener = listener;
837 }
838
839 public StringTemplateErrorListener getErrorListener() {
840 return listener;
841 }
842
843 /** Specify a StringTemplateWriter implementing class to use for
844 * filtering output
845 */
846 public void setStringTemplateWriter(Class c) {
847 userSpecifiedWriter = c;
848 }
849
850 /** return an instance of a StringTemplateWriter that spits output to w.
851 * If a writer is specified, use it instead of the default.
852 */
853 public StringTemplateWriter getStringTemplateWriter(Writer w) {
854 StringTemplateWriter stw = null;
855 if ( userSpecifiedWriter!=null ) {
856 try {
857 Constructor ctor =
858 userSpecifiedWriter.getConstructor(new Class[] {Writer.class});
859 stw = (StringTemplateWriter) ctor.newInstance(new Object[] {w});
860 }
861 catch (Exception e) {
862 error("problems getting StringTemplateWriter",e);
863 }
864 }
865 if ( stw==null ) {
866 stw = new AutoIndentWriter(w);
867 }
868 return stw;
869 }
870
871 /** Specify a complete map of what object classes should map to which
872 * renderer objects for every template in this group (that doesn't
873 * override it per template).
874 */
875 public void setAttributeRenderers(Map renderers) {
876 this.attributeRenderers = renderers;
877 }
878
879 /** Register a renderer for all objects of a particular type for all
880 * templates in this group.
881 */
882 public void registerRenderer(Class attributeClassType, Object renderer) {
883 if ( attributeRenderers==null ) {
884 attributeRenderers = Collections.synchronizedMap(new HashMap());
885 }
886 attributeRenderers.put(attributeClassType, renderer);
887 }
888
889 /** What renderer is registered for this attributeClassType for
890 * this group? If not found, as superGroup if it has one.
891 */
892 public AttributeRenderer getAttributeRenderer(Class attributeClassType) {
893 if ( attributeRenderers==null ) {
894 if ( superGroup==null ) {
895 return null; // no renderers and no parent? Stop.
896 }
897 // no renderers; consult super group
898 return superGroup.getAttributeRenderer(attributeClassType);
899 }
900
901 AttributeRenderer renderer =
902 (AttributeRenderer)attributeRenderers.get(attributeClassType);
903 if ( renderer==null ) {
904 if ( superGroup!=null ) {
905 // no renderer registered for this class, check super group
906 renderer = superGroup.getAttributeRenderer(attributeClassType);
907 }
908 }
909 return renderer;
910 }
911
912 /*
913 public void cacheClassProperty(Class c, String propertyName, Member member) {
914 Object key = new ClassPropCacheKey(c,propertyName);
915 classPropertyCache.put(key,member);
916 }
917
918 public Member getCachedClassProperty(Class c, String propertyName) {
919 Object key = new ClassPropCacheKey(c,propertyName);
920 return (Member)classPropertyCache.get(key);
921 }
922 */
923
924 public Map getMap(String name) {
925 if ( maps==null ) {
926 if ( superGroup==null ) {
927 return null;
928 }
929 return superGroup.getMap(name);
930 }
931 Map m = (Map)maps.get(name);
932 if ( m==null && superGroup!=null ) {
933 m = superGroup.getMap(name);
934 }
935 return m;
936 }
937
938 /** Define a map for this group; not thread safe...do not keep adding
939 * these while you reference them.
940 */
941 public void defineMap(String name, Map mapping) {
942 maps.put(name, mapping);
943 }
944
945 public static void registerDefaultLexer(Class lexerClass) {
946 defaultTemplateLexerClass = lexerClass;
947 }
948
949 public static void registerGroupLoader(StringTemplateGroupLoader loader) {
950 groupLoader = loader;
951 }
952
953 public static StringTemplateGroup loadGroup(String name) {
954 return loadGroup(name, null, null);
955 }
956
957 public static StringTemplateGroup loadGroup(String name,
958 StringTemplateGroup superGroup)
959 {
960 return loadGroup(name, null, superGroup);
961 }
962
963 public static StringTemplateGroup loadGroup(String name,
964 Class lexer,
965 StringTemplateGroup superGroup)
966 {
967 if ( groupLoader!=null ) {
968 return groupLoader.loadGroup(name, lexer, superGroup);
969 }
970 return null;
971 }
972
973 public static StringTemplateGroupInterface loadInterface(String name) {
974 if ( groupLoader!=null ) {
975 return groupLoader.loadInterface(name);
976 }
977 return null;
978 }
979
980 public void error(String msg) {
981 error(msg, null);
982 }
983
984 public void error(String msg, Exception e) {
985 if ( listener!=null ) {
986 listener.error(msg,e);
987 }
988 else {
989 System.err.println("StringTemplate: "+msg);
990 if ( e!=null ) {
991 e.printStackTrace();
992 }
993 }
994 }
995
996 public synchronized Set getTemplateNames() {
997 return templates.keySet();
998 }
999
1000 /** Indicate whether ST should emit <templatename>...</templatename>
1001 * strings for debugging around output for templates from this group.
1002 */
1003 public void emitDebugStartStopStrings(boolean emit) {
1004 this.debugTemplateOutput = emit;
1005 }
1006
1007 public void doNotEmitDebugStringsForTemplate(String templateName) {
1008 if ( noDebugStartStopStrings==null ) {
1009 noDebugStartStopStrings = new HashSet();
1010 }
1011 noDebugStartStopStrings.add(templateName);
1012 }
1013
1014 public void emitTemplateStartDebugString(StringTemplate st,
1015 StringTemplateWriter out)
1016 throws IOException
1017 {
1018 if ( noDebugStartStopStrings==null ||
1019 !noDebugStartStopStrings.contains(st.getName()) )
1020 {
1021 String groupPrefix = "";
1022 if ( !st.getName().startsWith("if") && !st.getName().startsWith("else") ) {
1023 if ( st.getNativeGroup()!=null ) {
1024 groupPrefix = st.getNativeGroup().getName()+".";
1025 }
1026 else {
1027 groupPrefix = st.getGroup().getName()+".";
1028 }
1029 }
1030 out.write("<"+groupPrefix +st.getName()+">");
1031 }
1032 }
1033
1034 public void emitTemplateStopDebugString(StringTemplate st,
1035 StringTemplateWriter out)
1036 throws IOException
1037 {
1038 if ( noDebugStartStopStrings==null ||
1039 !noDebugStartStopStrings.contains(st.getName()) )
1040 {
1041 String groupPrefix = "";
1042 if ( !st.getName().startsWith("if") && !st.getName().startsWith("else") ) {
1043 if ( st.getNativeGroup()!=null ) {
1044 groupPrefix = st.getNativeGroup().getName()+".";
1045 }
1046 else {
1047 groupPrefix = st.getGroup().getName()+".";
1048 }
1049 }
1050 out.write("</"+groupPrefix+st.getName()+">");
1051 }
1052 }
1053
1054 public String toString() {
1055 return toString(true);
1056 }
1057
1058 public String toString(boolean showTemplatePatterns) {
1059 StringBuffer buf = new StringBuffer();
1060 Set templateNameSet = templates.keySet();
1061 List sortedNames = new ArrayList(templateNameSet);
1062 Collections.sort(sortedNames);
1063 Iterator iter = sortedNames.iterator();
1064 buf.append("group "+getName()+";\n");
1065 StringTemplate formalArgs = new StringTemplate("$args;separator=\",\"$");
1066 while (iter.hasNext()) {
1067 String tname = (String) iter.next();
1068 StringTemplate st = (StringTemplate)templates.get(tname);
1069 if ( st!=NOT_FOUND_ST ) {
1070 formalArgs = formalArgs.getInstanceOf();
1071 formalArgs.setAttribute("args", st.getFormalArguments());
1072 buf.append(tname+"("+formalArgs+")");
1073 if ( showTemplatePatterns ) {
1074 buf.append(" ::= <<");
1075 buf.append(st.getTemplate());
1076 buf.append(">>\n");
1077 }
1078 else {
1079 buf.append('\n');
1080 }
1081 }
1082 }
1083 return buf.toString();
1084 }
1085 }
0 package org.antlr.stringtemplate;
1
2 import org.antlr.stringtemplate.language.*;
3
4 import java.util.*;
5 import java.io.Reader;
6
7 /** A group interface is like a group without the template implementations;
8 * there are just template names/argument-lists like this:
9 *
10 * interface foo;
11 * class(name,fields);
12 * method(name,args,body);
13 *
14 */
15 public class StringTemplateGroupInterface {
16 /** What is the group name */
17 protected String name;
18
19 /** Maps template name to TemplateDefinition object */
20 protected Map templates = new LinkedHashMap();
21
22 /** Are we derived from another group? Templates not found in this group
23 * will be searched for in the superGroup recursively.
24 */
25 protected StringTemplateGroupInterface superInterface = null;
26
27 /** Where to report errors. All string templates in this group
28 * use this error handler by default.
29 */
30 protected StringTemplateErrorListener listener = DEFAULT_ERROR_LISTENER;
31
32 public static StringTemplateErrorListener DEFAULT_ERROR_LISTENER =
33 new StringTemplateErrorListener() {
34 public void error(String s, Throwable e) {
35 System.err.println(s);
36 if ( e!=null ) {
37 e.printStackTrace(System.err);
38 }
39 }
40 public void warning(String s) {
41 System.out.println(s);
42 }
43 };
44
45 /** All the info we need to track for a template defined in an interface */
46 static class TemplateDefinition {
47 public String name;
48 public LinkedHashMap formalArgs; // LinkedHashMap<FormalArgument>
49 public boolean optional = false;
50 public TemplateDefinition(String name, LinkedHashMap formalArgs, boolean optional) {
51 this.name = name;
52 this.formalArgs = formalArgs;
53 this.optional = optional;
54 }
55 }
56
57 public StringTemplateGroupInterface(Reader r) {
58 this(r,DEFAULT_ERROR_LISTENER,(StringTemplateGroupInterface)null);
59 }
60
61 public StringTemplateGroupInterface(Reader r, StringTemplateErrorListener errors) {
62 this(r,errors,(StringTemplateGroupInterface)null);
63 }
64
65 /** Create an interface from the input stream */
66 public StringTemplateGroupInterface(Reader r,
67 StringTemplateErrorListener errors,
68 StringTemplateGroupInterface superInterface)
69 {
70 this.listener = errors;
71 setSuperInterface(superInterface);
72 parseInterface(r);
73 }
74
75 public StringTemplateGroupInterface getSuperInterface() {
76 return superInterface;
77 }
78
79 public void setSuperInterface(StringTemplateGroupInterface superInterface) {
80 this.superInterface = superInterface;
81 }
82
83 protected void parseInterface(Reader r) {
84 try {
85 InterfaceLexer lexer = new InterfaceLexer(r);
86 InterfaceParser parser = new InterfaceParser(lexer);
87 parser.groupInterface(this);
88 //System.out.println("read interface\n"+this.toString());
89 }
90 catch (Exception e) {
91 String name = "<unknown>";
92 if ( getName()!=null ) {
93 name = getName();
94 }
95 error("problem parsing group "+name+": "+e, e);
96 }
97 }
98
99 public void defineTemplate(String name, LinkedHashMap formalArgs, boolean optional) {
100 TemplateDefinition d = new TemplateDefinition(name,formalArgs,optional);
101 templates.put(d.name,d);
102 }
103
104 /** Return a list of all template names missing from group that are defined
105 * in this interface. Return null if all is well.
106 */
107 public List getMissingTemplates(StringTemplateGroup group) {
108 List missing = new ArrayList();
109 for (Iterator it = templates.keySet().iterator(); it.hasNext();) {
110 String name = (String)it.next();
111 TemplateDefinition d = (TemplateDefinition)templates.get(name);
112 if ( !d.optional && !group.isDefined(d.name) ) {
113 missing.add(d.name);
114 }
115 }
116 if ( missing.size()==0 ) {
117 missing = null;
118 }
119 return missing;
120 }
121
122 /** Return a list of all template sigs that are present in the group, but
123 * that have wrong formal argument lists. Return null if all is well.
124 */
125 public List getMismatchedTemplates(StringTemplateGroup group) {
126 List mismatched = new ArrayList();
127 for (Iterator it = templates.keySet().iterator(); it.hasNext();) {
128 String name = (String)it.next();
129 TemplateDefinition d = (TemplateDefinition)templates.get(name);
130 if ( group.isDefined(d.name) ) {
131 StringTemplate defST = group.getTemplateDefinition(d.name);
132 Map formalArgs = defST.getFormalArguments();
133 boolean ack = false;
134 if ( (d.formalArgs!=null && formalArgs==null) ||
135 (d.formalArgs==null && formalArgs!=null) ||
136 d.formalArgs.size() != formalArgs.size() )
137 {
138 ack=true;
139 }
140 if ( !ack ) {
141 for (Iterator it2 = formalArgs.keySet().iterator();
142 it2.hasNext();)
143 {
144 String argName = (String)it2.next();
145 if ( d.formalArgs.get(argName)==null ) {
146 ack=true;
147 break;
148 }
149 }
150 }
151 if ( ack ) {
152 //System.out.println(d.formalArgs+"!="+formalArgs);
153 mismatched.add(getTemplateSignature(d));
154 }
155 }
156 }
157 if ( mismatched.size()==0 ) {
158 mismatched = null;
159 }
160 return mismatched;
161 }
162
163 public String getName() {
164 return name;
165 }
166
167 public void setName(String name) {
168 this.name = name;
169 }
170
171 public void error(String msg) {
172 error(msg, null);
173 }
174
175 public void error(String msg, Exception e) {
176 if ( listener!=null ) {
177 listener.error(msg,e);
178 }
179 else {
180 System.err.println("StringTemplate: "+msg);
181 if ( e!=null ) {
182 e.printStackTrace();
183 }
184 }
185 }
186
187 public String toString() {
188 StringBuffer buf = new StringBuffer();
189 buf.append("interface ");
190 buf.append(getName());
191 buf.append(";\n");
192 for (Iterator it = templates.keySet().iterator(); it.hasNext();) {
193 String name = (String)it.next();
194 TemplateDefinition d = (TemplateDefinition)templates.get(name);
195 buf.append( getTemplateSignature(d) );
196 buf.append(";\n");
197 }
198 return buf.toString();
199 }
200
201 protected String getTemplateSignature(TemplateDefinition d) {
202 StringBuffer buf = new StringBuffer();
203 if ( d.optional ) {
204 buf.append("optional ");
205 }
206 buf.append(d.name);
207 if ( d.formalArgs!=null ) {
208 StringBuffer args = new StringBuffer();
209 args.append('(');
210 int i=1;
211 for (Iterator it = d.formalArgs.keySet().iterator(); it.hasNext();) {
212 String name = (String) it.next();
213 if ( i>1 ) {
214 args.append(", ");
215 }
216 args.append(name);
217 i++;
218 }
219 args.append(')');
220 buf.append(args);
221 }
222 else {
223 buf.append("()");
224 }
225 return buf.toString();
226 }
227 }
0 package org.antlr.stringtemplate;
1
2 /** When group files derive from another group, we have to know how to
3 * load that group and its supergroups. This interface also knows how
4 * to load interfaces.
5 */
6 public interface StringTemplateGroupLoader {
7 /** Load the group called groupName from somewhere. Return null
8 * if no group is found.
9 */
10 public StringTemplateGroup loadGroup(String groupName);
11
12 /** Load a group with a specified superGroup. Groups with
13 * region definitions must know their supergroup to find templates
14 * during parsing.
15 */
16 public StringTemplateGroup loadGroup(String groupName,
17 StringTemplateGroup superGroup);
18
19
20 /** Specify the template lexer to use for parsing templates. If null,
21 * it assumes angle brackets <...>.
22 */
23 public StringTemplateGroup loadGroup(String groupName,
24 Class templateLexer,
25 StringTemplateGroup superGroup);
26
27 /** Load the interface called interfaceName from somewhere. Return null
28 * if no interface is found.
29 */
30 public StringTemplateGroupInterface loadInterface(String interfaceName);
31 }
0 /*
1 [The "BSD licence"]
2 Copyright (c) 2003-2005 Terence Parr
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package org.antlr.stringtemplate;
28
29 import java.io.IOException;
30
31 /** Generic StringTemplate output writer filter.
32 *
33 * Literals and the elements of expressions are emitted via write().
34 * Separators are emitted via writeSeparator() because they must be
35 * handled specially when wrapping lines (we don't want to wrap
36 * in between an element and it's separator).
37 */
38 public interface StringTemplateWriter {
39 public static final int NO_WRAP = -1;
40
41 void pushIndentation(String indent);
42
43 String popIndentation();
44
45 void pushAnchorPoint();
46
47 void popAnchorPoint();
48
49 void setLineWidth(int lineWidth);
50
51 /** Write the string and return how many actual chars were written.
52 * With autoindentation and wrapping, more chars than length(str)
53 * can be emitted. No wrapping is done.
54 */
55 int write(String str) throws IOException;
56
57 /** Same as write, but wrap lines using the indicated string as the
58 * wrap character (such as "\n").
59 */
60 int write(String str, String wrap) throws IOException;
61
62 /** Because we might need to wrap at a non-atomic string boundary
63 * (such as when we wrap in between template applications
64 * <data:{v|[<v>]}; wrap>) we need to expose the wrap string
65 * writing just like for the separator.
66 */
67 public int writeWrapSeparator(String wrap) throws IOException;
68
69 /** Write a separator. Same as write() except that a \n cannot
70 * be inserted before emitting a separator.
71 */
72 int writeSeparator(String str) throws IOException;
73 }
0 /*
1 [The "BSD licence"]
2 Copyright (c) 2003-2005 Terence Parr
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package org.antlr.stringtemplate.language;
28
29 import antlr.RecognitionException;
30 import antlr.collections.AST;
31 import org.antlr.stringtemplate.AttributeRenderer;
32 import org.antlr.stringtemplate.StringTemplate;
33 import org.antlr.stringtemplate.StringTemplateGroup;
34 import org.antlr.stringtemplate.StringTemplateWriter;
35
36 import java.io.IOException;
37 import java.io.StringWriter;
38 import java.lang.reflect.Field;
39 import java.lang.reflect.InvocationTargetException;
40 import java.lang.reflect.Method;
41 import java.util.*;
42
43 /** A single string template expression enclosed in $...; separator=...$
44 * parsed into an AST chunk to be evaluated.
45 */
46 public class ASTExpr extends Expr {
47 public static final int MISSING = -1; // writing -1 char means missing not empty
48 public static final String DEFAULT_ATTRIBUTE_NAME = "it";
49 public static final String DEFAULT_ATTRIBUTE_NAME_DEPRECATED = "attr";
50 public static final String DEFAULT_INDEX_VARIABLE_NAME = "i";
51 public static final String DEFAULT_INDEX0_VARIABLE_NAME = "i0";
52 public static final String DEFAULT_MAP_VALUE_NAME = "_default_";
53 public static final String DEFAULT_MAP_KEY_NAME = "key";
54
55 /** Used to indicate "default:key" in maps within groups */
56 public static final StringTemplate MAP_KEY_VALUE = new StringTemplate();
57
58 /** Using an expr option w/o value, makes options table hold EMPTY_OPTION
59 * value for that key.
60 */
61 public static final String EMPTY_OPTION = "empty expr option";
62
63 public static final Map defaultOptionValues = new HashMap() {
64 {
65 put("anchor", new StringTemplateAST(ActionEvaluator.STRING,"true"));
66 put("wrap", new StringTemplateAST(ActionEvaluator.STRING,"\n"));
67 }
68 };
69
70 /** John Snyders gave me an example implementation for this checking */
71 public static final Set supportedOptions = new HashSet() {
72 {
73 add("anchor");
74 add("format");
75 add("null");
76 add("separator");
77 add("wrap");
78 }
79 };
80
81 AST exprTree = null;
82
83 /** store separator etc... */
84 Map options = null;
85
86 /** A cached value of wrap=expr from the <...> expression.
87 * Computed in write(StringTemplate, StringTemplateWriter) and used
88 * in writeAttribute.
89 */
90 String wrapString = null;
91
92 /** For null values in iterated attributes and single attributes that
93 * are null, use this value instead of skipping. For single valued
94 * attributes like <name; null="n/a"> it's a shorthand for
95 * <if(name)><name><else>n/a<endif>
96 * For iterated values <values; null="0", separator=",">, you get 0 for
97 * for null list values. Works for template application like:
98 * <values:{v| <v>}; null="0"> also.
99 */
100 String nullValue = null;
101
102 /** A cached value of separator=expr from the <...> expression.
103 * Computed in write(StringTemplate, StringTemplateWriter) and used
104 * in writeAttribute.
105 */
106 String separatorString = null;
107
108 /** A cached value of option format=expr */
109 String formatString = null;
110
111 public ASTExpr(StringTemplate enclosingTemplate, AST exprTree, Map options) {
112 super(enclosingTemplate);
113 this.exprTree = exprTree;
114 this.options = options;
115 }
116
117 /** Return the tree interpreted when this template is written out. */
118 public AST getAST() {
119 return exprTree;
120 }
121
122 /** To write out the value of an ASTExpr, invoke the evaluator in eval.g
123 * to walk the tree writing out the values. For efficiency, don't
124 * compute a bunch of strings and then pack them together. Write out directly.
125 *
126 * Compute separator and wrap expressions, save as strings so we don't
127 * recompute for each value in a multi-valued attribute or expression.
128 *
129 * If they set anchor option, then inform the writer to push current
130 * char position.
131 */
132 public int write(StringTemplate self, StringTemplateWriter out) throws IOException {
133 if ( exprTree==null || self==null || out==null ) {
134 return 0;
135 }
136 // handle options, anchor, wrap, separator...
137 StringTemplateAST anchorAST = (StringTemplateAST)getOption("anchor");
138 if ( anchorAST!=null ) { // any non-empty expr means true; check presence
139 out.pushAnchorPoint();
140 }
141 out.pushIndentation(getIndentation());
142 handleExprOptions(self);
143 //System.out.println("evaluating tree: "+exprTree.toStringList());
144 ActionEvaluator eval =
145 new ActionEvaluator(self,this,out);
146 int n = 0;
147 try {
148 n = eval.action(exprTree); // eval and write out tree
149 }
150 catch (RecognitionException re) {
151 self.error("can't evaluate tree: "+exprTree.toStringList(), re);
152 }
153 out.popIndentation();
154 if ( anchorAST!=null ) {
155 out.popAnchorPoint();
156 }
157 return n;
158 }
159
160 /** Grab and cache options; verify options are valid */
161 protected void handleExprOptions(StringTemplate self) {
162 // make sure options don't use format / renderer. They are usually
163 // strings which might invoke a string renderer etc...
164 formatString = null;
165 StringTemplateAST wrapAST = (StringTemplateAST)getOption("wrap");
166 if ( wrapAST!=null ) {
167 wrapString = evaluateExpression(self,wrapAST);
168 }
169 StringTemplateAST nullValueAST = (StringTemplateAST)getOption("null");
170 if ( nullValueAST!=null ) {
171 nullValue = evaluateExpression(self,nullValueAST);
172 }
173 StringTemplateAST separatorAST = (StringTemplateAST)getOption("separator");
174 if ( separatorAST!=null ) {
175 separatorString = evaluateExpression(self, separatorAST);
176 }
177 // following addition inspired by John Snyders
178 StringTemplateAST formatAST =
179 (StringTemplateAST)getOption("format");
180 if ( formatAST!=null ) {
181 formatString = evaluateExpression(self, formatAST);
182 }
183
184 // Check that option is valid
185 if ( options != null ) {
186 Iterator it = options.keySet().iterator();
187 while ( it.hasNext() ) {
188 String option = (String)it.next();
189 if (!supportedOptions.contains(option)) {
190 self.warning("ignoring unsupported option: "+option);
191 }
192 }
193 }
194 }
195
196 // HELP ROUTINES CALLED BY EVALUATOR TREE WALKER
197
198 /** For <names,phones:{n,p | ...}> treat the names, phones as lists
199 * to be walked in lock step as n=names[i], p=phones[i].
200 */
201 public Object applyTemplateToListOfAttributes(StringTemplate self,
202 List attributes,
203 StringTemplate templateToApply)
204 {
205 if ( attributes==null || templateToApply==null || attributes.size()==0 ) {
206 return null; // do not apply if missing templates or empty values
207 }
208 Map argumentContext = null;
209 // indicate it's an ST-created list
210 List results = new StringTemplate.STAttributeList();
211
212 // convert all attributes to iterators even if just one value
213 for (int a = 0; a < attributes.size(); a++) {
214 Object o = (Object) attributes.get(a);
215 if ( o!=null ) {
216 o = convertAnythingToIterator(o);
217 attributes.set(a, o); // alter the list in place
218 }
219 }
220
221 int numAttributes = attributes.size();
222
223 // ensure arguments line up
224 Map formalArguments = templateToApply.getFormalArguments();
225 if ( formalArguments==null || formalArguments.size()==0 ) {
226 self.error("missing arguments in anonymous"+
227 " template in context "+self.getEnclosingInstanceStackString());
228 return null;
229 }
230 Object[] formalArgumentNames = formalArguments.keySet().toArray();
231 if ( formalArgumentNames.length!=numAttributes ) {
232 self.error("number of arguments "+formalArguments.keySet()+
233 " mismatch between attribute list and anonymous"+
234 " template in context "+self.getEnclosingInstanceStackString());
235 // truncate arg list to match smaller size
236 int shorterSize = Math.min(formalArgumentNames.length, numAttributes);
237 numAttributes = shorterSize;
238 Object[] newFormalArgumentNames = new Object[shorterSize];
239 System.arraycopy(formalArgumentNames, 0,
240 newFormalArgumentNames, 0,
241 shorterSize);
242 formalArgumentNames = newFormalArgumentNames;
243 }
244
245 // keep walking while at least one attribute has values
246 int i = 0; // iteration number from 0
247 while ( true ) {
248 argumentContext = new HashMap();
249 // get a value for each attribute in list; put into arg context
250 // to simulate template invocation of anonymous template
251 int numEmpty = 0;
252 for (int a = 0; a < numAttributes; a++) {
253 Iterator it = (Iterator) attributes.get(a);
254 if ( it!=null && it.hasNext() ) {
255 String argName = (String)formalArgumentNames[a];
256 Object iteratedValue = it.next();
257 argumentContext.put(argName, iteratedValue);
258 }
259 else {
260 numEmpty++;
261 }
262 }
263 if ( numEmpty==numAttributes ) {
264 break;
265 }
266 argumentContext.put(DEFAULT_INDEX_VARIABLE_NAME, new Integer(i+1));
267 argumentContext.put(DEFAULT_INDEX0_VARIABLE_NAME, new Integer(i));
268 StringTemplate embedded = templateToApply.getInstanceOf();
269 embedded.setEnclosingInstance(self);
270 embedded.setArgumentContext(argumentContext);
271 results.add(embedded);
272 i++;
273 }
274
275 return results;
276 }
277
278 public Object applyListOfAlternatingTemplates(StringTemplate self,
279 Object attributeValue,
280 List templatesToApply)
281 {
282 if ( attributeValue==null || templatesToApply==null || templatesToApply.size()==0 ) {
283 return null; // do not apply if missing templates or empty value
284 }
285 StringTemplate embedded = null;
286 Map argumentContext = null;
287
288 // normalize collections and such to use iterators
289 // anything iteratable can be used for "APPLY"
290 attributeValue = convertArrayToList(attributeValue);
291 attributeValue = convertAnythingIteratableToIterator(attributeValue);
292
293 if ( attributeValue instanceof Iterator ) {
294 // results can be treated list an attribute, indicate ST created list
295 List resultVector = new StringTemplate.STAttributeList();
296 Iterator iter = (Iterator)attributeValue;
297 int i = 0;
298 while ( iter.hasNext() ) {
299 Object ithValue = iter.next();
300 if ( ithValue==null ) {
301 if ( nullValue==null ) {
302 continue;
303 }
304 ithValue = nullValue;
305 }
306 int templateIndex = i % templatesToApply.size(); // rotate through
307 embedded = (StringTemplate)templatesToApply.get(templateIndex);
308 // template to apply is an actual StringTemplate (created in
309 // eval.g), but that is used as the examplar. We must create
310 // a new instance of the embedded template to apply each time
311 // to get new attribute sets etc...
312 StringTemplateAST args = embedded.getArgumentsAST();
313 embedded = embedded.getInstanceOf(); // make new instance
314 embedded.setEnclosingInstance(self);
315 embedded.setArgumentsAST(args);
316 argumentContext = new HashMap();
317 Map formalArgs = embedded.getFormalArguments();
318 boolean isAnonymous =
319 embedded.getName() == StringTemplate.ANONYMOUS_ST_NAME;
320 setSoleFormalArgumentToIthValue(embedded, argumentContext, ithValue);
321 // if it's an anonymous template with a formal arg, don't set it/attr
322 if ( !(isAnonymous && formalArgs!=null && formalArgs.size()>0) ) {
323 argumentContext.put(DEFAULT_ATTRIBUTE_NAME, ithValue);
324 argumentContext.put(DEFAULT_ATTRIBUTE_NAME_DEPRECATED, ithValue);
325 }
326 argumentContext.put(DEFAULT_INDEX_VARIABLE_NAME, new Integer(i+1));
327 argumentContext.put(DEFAULT_INDEX0_VARIABLE_NAME, new Integer(i));
328 embedded.setArgumentContext(argumentContext);
329 evaluateArguments(embedded);
330 /*
331 System.err.println("i="+i+": applyTemplate("+embedded.getName()+
332 ", args="+argumentContext+
333 " to attribute value "+ithValue);
334 */
335 resultVector.add(embedded);
336 i++;
337 }
338 if ( resultVector.size()==0 ) {
339 resultVector = null;
340 }
341 return resultVector;
342 }
343 else {
344 /*
345 System.out.println("setting attribute "+DEFAULT_ATTRIBUTE_NAME+" in arg context of "+
346 embedded.getName()+
347 " to "+attributeValue);
348 */
349 embedded = (StringTemplate)templatesToApply.get(0);
350 argumentContext = new HashMap();
351 Map formalArgs = embedded.getFormalArguments();
352 StringTemplateAST args = embedded.getArgumentsAST();
353 setSoleFormalArgumentToIthValue(embedded, argumentContext, attributeValue);
354 boolean isAnonymous =
355 embedded.getName() == StringTemplate.ANONYMOUS_ST_NAME;
356 // if it's an anonymous template with a formal arg, don't set it/attr
357 if ( !(isAnonymous && formalArgs!=null && formalArgs.size()>0) ) {
358 argumentContext.put(DEFAULT_ATTRIBUTE_NAME, attributeValue);
359 argumentContext.put(DEFAULT_ATTRIBUTE_NAME_DEPRECATED, attributeValue);
360 }
361 argumentContext.put(DEFAULT_INDEX_VARIABLE_NAME, new Integer(1));
362 argumentContext.put(DEFAULT_INDEX0_VARIABLE_NAME, new Integer(0));
363 embedded.setArgumentContext(argumentContext);
364 evaluateArguments(embedded);
365 return embedded;
366 }
367 }
368
369 protected void setSoleFormalArgumentToIthValue(StringTemplate embedded, Map argumentContext, Object ithValue) {
370 Map formalArgs = embedded.getFormalArguments();
371 if ( formalArgs!=null ) {
372 String soleArgName = null;
373 boolean isAnonymous =
374 embedded.getName() == StringTemplate.ANONYMOUS_ST_NAME;
375 if ( formalArgs.size()==1 || (isAnonymous&&formalArgs.size()>0) ) {
376 if ( isAnonymous && formalArgs.size()>1 ) {
377 embedded.error("too many arguments on {...} template: "+formalArgs);
378 }
379 // if exactly 1 arg or anonymous, give that the value of
380 // "it" as a convenience like they said
381 // $list:template(arg=it)$
382 Set argNames = formalArgs.keySet();
383 soleArgName = (String)argNames.toArray()[0];
384 argumentContext.put(soleArgName, ithValue);
385 }
386 }
387 }
388
389 /** Return o.getPropertyName() given o and propertyName. If o is
390 * a stringtemplate then access it's attributes looking for propertyName
391 * instead (don't check any of the enclosing scopes; look directly into
392 * that object). Also try isXXX() for booleans. Allow Map
393 * as special case (grab value for key).
394 *
395 * Cache repeated requests for obj.prop within same group.
396 */
397 public Object getObjectProperty(StringTemplate self,
398 final Object o,
399 final Object propertyName) {
400 if ( o==null || propertyName==null ) {
401 return null;
402 }
403 /*
404 // see if property is cached in group's cache
405 Object cachedValue =
406 self.getGroup().getCachedObjectProperty(o,propertyName);
407 if ( cachedValue!=null ) {
408 return cachedValue;
409 }
410 Object value = rawGetObjectProperty(self, o, propertyName);
411 // take care of array properties...convert to a List so we can
412 // apply templates to the elements etc...
413 value = convertArrayToList(value);
414 self.getGroup().cacheObjectProperty(o,propertyName,value);
415 */
416 Object value = rawGetObjectProperty(self, o, propertyName);
417 // take care of array properties...convert to a List so we can
418 // apply templates to the elements etc...
419 value = convertArrayToList(value);
420 return value;
421 }
422
423 protected Object rawGetObjectProperty(StringTemplate self, Object o, Object property) {
424 Class c = o.getClass();
425 Object value = null;
426
427 // Special case: our automatically created Aggregates via
428 // attribute name: "{obj.{prop1,prop2}}"
429 if ( c==StringTemplate.Aggregate.class ) {
430 String propertyName = (String)property;
431 value = ((StringTemplate.Aggregate)o).get((String)propertyName);
432 return value;
433 }
434
435 // Special case: if it's a template, pull property from
436 // it's attribute table.
437 // TODO: TJP just asked himself why we can't do inherited attr here?
438 else if ( c==StringTemplate.class ) {
439 Map attributes = ((StringTemplate)o).getAttributes();
440 if ( attributes!=null ) {
441 String propertyName = (String)property;
442 value = attributes.get(propertyName);
443 return value;
444 }
445 }
446
447 // Special case: if it's a Map then pull using
448 // key not the property method.
449 if ( o instanceof Map ) {
450 Map map = (Map)o;
451 if ( property.equals("keys") ) {
452 value = map.keySet();
453 }
454 else if ( property.equals("values") ) {
455 value = map.values();
456 }
457 else if ( map.containsKey(property) ) {
458 value = map.get(property);
459 }
460 else if ( map.containsKey(property.toString()) ) {
461 // if we can't find the key, toString it
462 value = map.get(property.toString());
463 }
464 else {
465 if ( map.containsKey(DEFAULT_MAP_VALUE_NAME) ) {
466 value = map.get(DEFAULT_MAP_VALUE_NAME);
467 }
468 }
469 if ( value == MAP_KEY_VALUE ) {
470 value = property;
471 }
472 return value;
473 }
474
475 // try getXXX and isXXX properties
476
477 // check cache
478 Method m = null;
479 /*
480 Member cachedMember =
481 self.getGroup().getCachedClassProperty(c,propertyName);
482 if ( cachedMember!=null ) {
483 try {
484 if ( cachedMember instanceof Method ) {
485 m = (Method)cachedMember;
486 value = invokeMethod(m, o, value);
487 }
488 else {
489 // must be a field
490 Field f = (Field)cachedMember;
491 value = accessField(f, o, value);
492 }
493 }
494 catch (Exception e) {
495 self.error("Can't get property "+propertyName+
496 " from "+c.getName()+" instance", e);
497 }
498 return value;
499 }
500 */
501
502 // must look up using reflection
503 String propertyName = (String)property;
504 String methodSuffix = Character.toUpperCase(propertyName.charAt(0))+
505 propertyName.substring(1,propertyName.length());
506 m = getMethod(c,"get"+methodSuffix);
507 if ( m==null ) {
508 m = getMethod(c, "is"+methodSuffix);
509 }
510 if ( m != null ) {
511 // save to avoid lookup later
512 //self.getGroup().cacheClassProperty(c,propertyName,m);
513 try {
514 value = invokeMethod(m, o, value);
515 }
516 catch (Exception e) {
517 self.error("Can't get property "+propertyName+" using method get/is"+methodSuffix+
518 " from "+c.getName()+" instance", e);
519 }
520 }
521 else {
522 // try for a visible field
523 try {
524 Field f = c.getField(propertyName);
525 //self.getGroup().cacheClassProperty(c,propertyName,f);
526 try {
527 value = accessField(f, o, value);
528 }
529 catch (IllegalAccessException iae) {
530 self.error("Can't access property "+propertyName+" using method get/is"+methodSuffix+
531 " or direct field access from "+c.getName()+" instance", iae);
532 }
533 }
534 catch (NoSuchFieldException nsfe) {
535 self.error("Class "+c.getName()+" has no such attribute: "+propertyName+
536 " in template context "+self.getEnclosingInstanceStackString(), nsfe);
537 }
538 }
539
540 return value;
541 }
542
543 protected Object accessField(Field f, Object o, Object value) throws IllegalAccessException {
544 try {
545 // make sure it's accessible (stupid java)
546 f.setAccessible(true);
547 }
548 catch (SecurityException se) {
549 ; // oh well; security won't let us
550 }
551 value = f.get(o);
552 return value;
553 }
554
555 protected Object invokeMethod(Method m, Object o, Object value) throws IllegalAccessException, InvocationTargetException {
556 try {
557 // make sure it's accessible (stupid java)
558 m.setAccessible(true);
559 }
560 catch (SecurityException se) {
561 ; // oh well; security won't let us
562 }
563 value = m.invoke(o,(Object[])null);
564 return value;
565 }
566
567 protected Method getMethod(Class c, String methodName) {
568 Method m;
569 try {
570 m = c.getMethod(methodName, (Class[])null);
571 }
572 catch (NoSuchMethodException nsme) {
573 m = null;
574 }
575 return m;
576 }
577
578 /** Normally StringTemplate tests presence or absence of attributes
579 * for adherence to my principles of separation, but some people
580 * disagree and want to change.
581 *
582 * For 2.0, if the object is a boolean, do something special. $if(boolean)$
583 * will actually test the value. Now, this breaks my rules of entanglement
584 * listed in my paper, but it truly surprises programmers to have booleans
585 * always true. Further, the key to isolating logic in the model is avoiding
586 * operators (for which you need attribute values). But, no operator is
587 * needed to use boolean values. Well, actually I guess "!" (not) is
588 * an operator. Regardless, for practical reasons, I'm going to technically
589 * violate my rules as I currently have them defined. Perhaps for a future
590 * version of the paper I will refine the rules.
591 *
592 * Post 2.1, I added a check for non-null Iterators, Collections, ...
593 * with size==0 to return false. TJP 5/1/2005
594 */
595 public boolean testAttributeTrue(Object a) {
596 if ( a==null ) {
597 return false;
598 }
599 if ( a instanceof Boolean ) {
600 return ((Boolean)a).booleanValue();
601 }
602 if ( a instanceof Collection ) {
603 return ((Collection)a).size()>0;
604 }
605 if ( a instanceof Map ) {
606 return ((Map)a).size()>0;
607 }
608 if ( a instanceof Iterator ) {
609 return ((Iterator)a).hasNext();
610 }
611 return true; // any other non-null object, return true--it's present
612 }
613
614 /** For now, we can only add two objects as strings; convert objects to
615 * Strings then cat.
616 */
617 public Object add(Object a, Object b) {
618 if ( a==null ) { // a null value means don't do cat, just return other value
619 return b;
620 }
621 else if ( b==null ) {
622 return a;
623 }
624 return a.toString() + b.toString();
625 }
626
627 /** Call a string template with args and return result. Do not convert
628 * to a string yet. It may need attributes that will be available after
629 * this is inserted into another template.
630 */
631 public StringTemplate getTemplateInclude(StringTemplate enclosing,
632 String templateName,
633 StringTemplateAST argumentsAST)
634 {
635 //System.out.println("getTemplateInclude: look up "+enclosing.getGroup().getName()+"::"+templateName);
636 StringTemplateGroup group = enclosing.getGroup();
637 StringTemplate embedded = group.getEmbeddedInstanceOf(enclosing, templateName);
638 if ( embedded==null ) {
639 enclosing.error("cannot make embedded instance of "+templateName+
640 " in template "+enclosing.getName());
641 return null;
642 }
643 embedded.setArgumentsAST(argumentsAST);
644 evaluateArguments(embedded);
645 return embedded;
646 }
647
648 /** How to spit out an object. If it's not a StringTemplate nor a
649 * List, just do o.toString(). If it's a StringTemplate,
650 * do o.write(out). If it's a Vector, do a write(out,
651 * o.elementAt(i)) for all elements. Note that if you do
652 * something weird like set the values of a multivalued tag
653 * to be vectors, it will effectively flatten it.
654 *
655 * If self is an embedded template, you might have specified
656 * a separator arg; used when is a vector.
657 */
658 public int writeAttribute(StringTemplate self, Object o, StringTemplateWriter out) {
659 return write(self,o,out);
660 }
661
662 /* Write o relative to self to out.
663 *
664 * John Snyders fixes here for formatString. Basically, any time
665 * you are about to write a value, check formatting.
666 */
667 protected int write(StringTemplate self,
668 Object o,
669 StringTemplateWriter out)
670 {
671 if ( o==null ) {
672 if ( nullValue==null ) {
673 return MISSING;
674 }
675 o = nullValue; // continue with null option if specified
676 }
677 int n = 0;
678 try {
679 if ( o instanceof StringTemplate ) return writeTemplate(self, o, out);
680 o = convertAnythingIteratableToIterator(o); // normalize
681 if ( o instanceof Iterator ) return writeIterableValue(self, o, out);
682 return writePOJO(self, o, out);
683 }
684 catch (IOException io) {
685 self.error("problem writing object: "+o, io);
686 }
687 return n;
688 }
689
690 protected int writePOJO(StringTemplate self, Object o, StringTemplateWriter out) throws IOException {
691 int n = 0;
692 AttributeRenderer renderer =
693 self.getAttributeRenderer(o.getClass());
694 String v = null;
695 if ( renderer!=null ) {
696 if ( formatString != null ) v = renderer.toString(o, formatString);
697 else v = renderer.toString(o);
698 }
699 else v = o.toString();
700 if ( wrapString!=null ) n = out.write(v, wrapString);
701 else n = out.write( v );
702 return n;
703 }
704
705 protected int writeTemplate(StringTemplate self, Object o, StringTemplateWriter out) throws IOException {
706 int n = 0;
707 StringTemplate stToWrite = (StringTemplate)o;
708 // failsafe: perhaps enclosing instance not set
709 // Or, it could be set to another context! This occurs
710 // when you store a template instance as an attribute of more
711 // than one template (like both a header file and C file when
712 // generating C code). It must execute within the context of
713 // the enclosing template.
714 stToWrite.setEnclosingInstance(self);
715 // if self is found up the enclosing instance chain, then
716 // infinite recursion
717 if ( StringTemplate.inLintMode() &&
718 StringTemplate.isRecursiveEnclosingInstance(stToWrite) )
719 {
720 // throw exception since sometimes eval keeps going
721 // even after I ignore this write of o.
722 throw new IllegalStateException("infinite recursion to "+
723 stToWrite.getTemplateDeclaratorString()+" referenced in "+
724 stToWrite.getEnclosingInstance().getTemplateDeclaratorString()+
725 "; stack trace:\n"+stToWrite.getEnclosingInstanceStackTrace());
726 }
727 else {
728 // if we have a wrap string, then inform writer it
729 // might need to wrap
730 if ( wrapString!=null ) {
731 n = out.writeWrapSeparator(wrapString);
732 }
733 // check if formatting needs to be applied to the stToWrite
734 if ( formatString != null ) {
735 AttributeRenderer renderer =
736 self.getAttributeRenderer(String.class);
737 if ( renderer != null ) {
738 // you pay a penalty for applying format option to a template
739 // because the template must be written to a temp StringWriter so it can
740 // be formatted before being written to the real output.
741 StringWriter buf = new StringWriter();
742 StringTemplateWriter sw =
743 self.getGroup().getStringTemplateWriter(buf);
744 stToWrite.write(sw);
745 n = out.write(renderer.toString(buf.toString(), formatString));
746 return n;
747 }
748 }
749 n = stToWrite.write(out);
750 }
751 return n;
752 }
753
754 protected int writeIterableValue(StringTemplate self,
755 Object o,
756 StringTemplateWriter out)
757 throws IOException
758 {
759 int n = 0;
760 Iterator iter = (Iterator)o;
761 boolean seenAValue = false;
762 while ( iter.hasNext() ) {
763 Object iterValue = iter.next();
764 if ( iterValue==null ) iterValue = nullValue;
765 if ( iterValue!=null ) {
766 // if no separator or separator but iterValue isn't
767 // a single IF condition template
768 if ( separatorString==null ) {
769 // if no separator, don't waste time writing to
770 // temp buffer
771 int nw = write(self, iterValue, out);
772 if ( nw!=MISSING ) n += nw;
773 continue;
774 }
775 // if value to emit is a template, only buffer its
776 // value if it's nullable (can eval to missing).
777 // Only a sequence of IF can eval to missing.
778 if ( iterValue instanceof StringTemplate ) {
779 StringTemplate st = (StringTemplate)iterValue;
780 int nchunks = st.getChunks()!=null ? st.getChunks().size() : 0;
781 boolean nullable = true;
782 for (int i=0; i<nchunks; i++) {
783 Expr a = (Expr)st.getChunks().get(i);
784 if ( !(a instanceof ConditionalExpr) ) nullable = false;
785 }
786 // if not all IF, not nullable, spit out w/o buffering
787 if ( !nullable) {
788 if ( seenAValue && separatorString!=null ) {
789 n += out.writeSeparator(separatorString);
790 }
791 int nw = write(self, iterValue, out);
792 n += nw;
793 seenAValue = true;
794 continue;
795 }
796 }
797
798 if ( !(iterValue instanceof StringTemplate) &&
799 !(iterValue instanceof Iterator))
800 {
801 // if not possible to be missing, don't waste time
802 // writing to temp buffer; might need separator though
803 if ( seenAValue && separatorString!=null ) {
804 n += out.writeSeparator(separatorString);
805 }
806 int nw = write(self, iterValue, out);
807 seenAValue = true;
808 n += nw;
809 continue;
810 }
811
812 // if separator exists, write iterated value to a
813 // tmp buffer in case we don't need a separator.
814 // Can't generate separator then test next expr value
815 // as we can't undo separator emit.
816 // Write to dummy buffer to if it is MISSING
817 // but eval/write value again to real out so
818 // we get proper autowrap etc...
819 // Ack: you pay a penalty now for a separator
820 // Later, i can optimze to check if one chunk and
821 // it's a conditional
822 StringWriter buf = new StringWriter();
823 StringTemplateWriter sw =
824 self.getGroup().getStringTemplateWriter(buf);
825 int tmpsize = write(self, iterValue, sw);
826
827 if ( tmpsize!=MISSING ) {
828 if ( seenAValue && separatorString!=null ) {
829 n += out.writeSeparator(separatorString);
830 }
831 // do it to real output stream now
832 int nw = write(self, iterValue, out);
833 n += nw;
834 seenAValue = true;
835 }
836 }
837 }
838 return n;
839 }
840
841 /** A expr is normally just a string literal, but is still an AST that
842 * we must evaluate. The expr can be any expression such as a template
843 * include or string cat expression etc... Evaluate with its own writer
844 * so that we can convert to string and then reuse, don't want to compute
845 * all the time; must precompute w/o writing to output buffer.
846 */
847 public String evaluateExpression(StringTemplate self,
848 Object expr)
849 {
850 if ( expr ==null ) {
851 return null;
852 }
853 if ( expr instanceof StringTemplateAST ) {
854 StringTemplateAST exprAST = (StringTemplateAST)expr;
855 // must evaluate, writing to a string so we can hang on to it
856 StringWriter buf = new StringWriter();
857 StringTemplateWriter sw =
858 self.getGroup().getStringTemplateWriter(buf);
859 {
860 ActionEvaluator eval =
861 new ActionEvaluator(self,this,sw);
862 try {
863 eval.action(exprAST); // eval tree
864 }
865 catch (RecognitionException re) {
866 self.error("can't evaluate tree: "+exprTree.toStringList(), re);
867 }
868 }
869 return buf.toString();
870 }
871 else {
872 // just in case we expand in the future and it's something else
873 return expr.toString();
874 }
875 }
876
877 /** Evaluate an argument list within the context of the enclosing
878 * template but store the values in the context of self, the
879 * new embedded template. For example, bold(item=item) means
880 * that bold.item should get the value of enclosing.item.
881 */
882 protected void evaluateArguments(StringTemplate self) {
883 StringTemplateAST argumentsAST = self.getArgumentsAST();
884 if ( argumentsAST==null || argumentsAST.getFirstChild()==null ) {
885 // return immediately if missing tree or no actual args
886 return;
887 }
888
889 // Evaluate args in the context of the enclosing template, but we
890 // need the predefined args like 'it', 'attr', and 'i' to be
891 // available as well so we put a dummy ST between the enclosing
892 // context and the embedded context. The dummy has the predefined
893 // context as does the embedded.
894 StringTemplate enclosing = self.getEnclosingInstance();
895 StringTemplate argContextST = new StringTemplate(self.getGroup(), "");
896 argContextST.setName("<invoke "+self.getName()+" arg context>");
897 argContextST.setEnclosingInstance(enclosing);
898 argContextST.setArgumentContext(self.getArgumentContext());
899
900 ActionEvaluator eval =
901 new ActionEvaluator(argContextST,this,null);
902 /*
903 System.out.println("eval args: "+argumentsAST.toStringList());
904 System.out.println("ctx is "+self.getArgumentContext());
905 */
906 try {
907 // using any initial argument context (such as when obj is set),
908 // evaluate the arg list like bold(item=obj). Since we pass
909 // in any existing arg context, that context gets filled with
910 // new values. With bold(item=obj), context becomes:
911 // {[obj=...],[item=...]}.
912 Map ac = eval.argList(argumentsAST, self, self.getArgumentContext());
913 self.setArgumentContext(ac);
914 }
915 catch (RecognitionException re) {
916 self.error("can't evaluate tree: "+argumentsAST.toStringList(), re);
917 }
918 }
919
920 /*
921 public static final Set arraysConvertibleToList = new HashSet() {
922 {
923 add(int[].class);
924 add(long[].class);
925 add(float[].class);
926 add(double[].class);
927 }
928 };
929 */
930
931 /** Do a standard conversion of array attributes to a List. Wrap the
932 * array instead of copying like old version. Make an
933 * ArrayWrappedInList that knows to create an ArrayIterator.
934 */
935 public static Object convertArrayToList(Object value) {
936 if ( value==null ) {
937 return null;
938 }
939 if ( value.getClass().isArray() ) {
940 if ( value.getClass().getComponentType().isPrimitive() ) {
941 return new ArrayWrappedInList(value);
942 }
943 return Arrays.asList((Object[])value);
944 }
945 return value;
946 }
947
948 protected static Object convertAnythingIteratableToIterator(Object o) {
949 Iterator iter = null;
950 if ( o instanceof Collection ) {
951 iter = ((Collection)o).iterator();
952 }
953 else if ( o instanceof Map ) {
954 iter = ((Map)o).values().iterator();
955 }
956 else if ( o instanceof Iterator ) {
957 iter = (Iterator)o;
958 }
959 if ( iter==null ) {
960 return o;
961 }
962 return iter;
963 }
964
965 protected static Iterator convertAnythingToIterator(Object o) {
966 Iterator iter = null;
967 if ( o instanceof Collection ) {
968 iter = ((Collection)o).iterator();
969 }
970 else if ( o instanceof Map ) {
971 iter = ((Map)o).values().iterator();
972 }
973 else if ( o instanceof Iterator ) {
974 iter = (Iterator)o;
975 }
976 if ( iter==null ) {
977 List singleton = new StringTemplate.STAttributeList(1);
978 singleton.add(o);
979 return singleton.iterator();
980 }
981 return iter;
982 }
983
984 /** Return the first attribute if multiple valued or the attribute
985 * itself if single-valued. Used in <names:first()>
986 */
987 public Object first(Object attribute) {
988 if ( attribute==null ) {
989 return null;
990 }
991 Object f = attribute;
992 attribute = convertAnythingIteratableToIterator(attribute);
993 if ( attribute instanceof Iterator ) {
994 Iterator it = (Iterator)attribute;
995 if ( it.hasNext() ) {
996 f = it.next();
997 }
998 }
999
1000 return f;
1001 }
1002
1003 /** Return the everything but the first attribute if multiple valued
1004 * or null if single-valued. Used in <names:rest()>.
1005 */
1006 public Object rest(Object attribute) {
1007 if ( attribute==null ) {
1008 return null;
1009 }
1010 Object theRest = attribute;
1011 attribute = convertAnythingIteratableToIterator(attribute);
1012 if ( attribute instanceof Iterator ) {
1013 List a = new ArrayList();
1014 Iterator it = (Iterator)attribute;
1015 if ( !it.hasNext() ) {
1016 return null; // if not even one value return null
1017 }
1018 it.next(); // ignore first value
1019 while (it.hasNext()) {
1020 Object o = (Object) it.next();
1021 if ( o!=null ) a.add(o);
1022 }
1023 return a;
1024 }
1025 else {
1026 theRest = null; // rest of single-valued attribute is null
1027 }
1028
1029 return theRest;
1030 }
1031
1032 /** Return the last attribute if multiple valued or the attribute
1033 * itself if single-valued. Used in <names:last()>. This is pretty
1034 * slow as it iterates until the last element. Ultimately, I could
1035 * make a special case for a List or Vector.
1036 */
1037 public Object last(Object attribute) {
1038 if ( attribute==null ) {
1039 return null;
1040 }
1041 Object last = attribute;
1042 attribute = convertAnythingIteratableToIterator(attribute);
1043 if ( attribute instanceof Iterator ) {
1044 Iterator it = (Iterator)attribute;
1045 while ( it.hasNext() ) {
1046 last = it.next();
1047 }
1048 }
1049
1050 return last;
1051 }
1052
1053 /** Return a new list w/o null values. */
1054 public Object strip(Object attribute) {
1055 if ( attribute==null ) {
1056 return null;
1057 }
1058 attribute = convertAnythingIteratableToIterator(attribute);
1059 if ( attribute instanceof Iterator ) {
1060 List a = new ArrayList();
1061 Iterator it = (Iterator)attribute;
1062 while (it.hasNext()) {
1063 Object o = (Object) it.next();
1064 if ( o!=null ) a.add(o);
1065 }
1066 return a;
1067 }
1068 return attribute; // strip(x)==x when x single-valued attribute
1069 }
1070
1071 /** Return all but the last element. trunc(x)=null if x is single-valued. */
1072 public Object trunc(Object attribute) {
1073 if ( attribute==null ) {
1074 return null;
1075 }
1076 attribute = convertAnythingIteratableToIterator(attribute);
1077 if ( attribute instanceof Iterator ) {
1078 List a = new ArrayList();
1079 Iterator it = (Iterator)attribute;
1080 while (it.hasNext()) {
1081 Object o = (Object) it.next();
1082 if ( it.hasNext() ) a.add(o); // only add if not last one
1083 }
1084 return a;
1085 }
1086 return null; // trunc(x)==null when x single-valued attribute
1087 }
1088
1089 /** Return the length of a multiple valued attribute or 1 if it is a
1090 * single attribute. If attribute is null return 0.
1091 * Special case several common collections and primitive arrays for
1092 * speed. This method by Kay Roepke.
1093 */
1094 public Object length(Object attribute) {
1095 if ( attribute == null) {
1096 return new Integer(0);
1097 }
1098 int i = 1; // we have at least one of something. Iterator and arrays might be empty.
1099 if (attribute instanceof Map) {
1100 i = ((Map)attribute).size();
1101 }
1102 else if (attribute instanceof Collection) {
1103 i = ((Collection)attribute).size();
1104 }
1105 else if ( attribute instanceof Object[] ) {
1106 Object[] list = (Object[])attribute;
1107 i = list.length;
1108 }
1109 else if ( attribute instanceof int[] ) {
1110 int[] list = (int[])attribute;
1111 i = list.length;
1112 }
1113 else if ( attribute instanceof long[] ) {
1114 long[] list = (long[])attribute;
1115 i = list.length;
1116 }
1117 else if ( attribute instanceof float[] ) {
1118 float[] list = (float[])attribute;
1119 i = list.length;
1120 }
1121 else if ( attribute instanceof double[] ) {
1122 double[] list = (double[])attribute;
1123 i = list.length;
1124 }
1125 else if ( attribute instanceof Iterator) {
1126 Iterator it = (Iterator)attribute;
1127 i = 0;
1128 while ( it.hasNext() ) {
1129 it.next();
1130 i++;
1131 }
1132 }
1133 return new Integer(i);
1134 }
1135
1136 public Object getOption(String name) {
1137 Object value = null;
1138 if ( options!=null ) {
1139 value = options.get(name);
1140 if ( value==EMPTY_OPTION ) {
1141 return defaultOptionValues.get(name);
1142 }
1143 }
1144 return value;
1145 }
1146
1147 public String toString() {
1148 return exprTree.toStringList();
1149 }
1150 }
0 package org.antlr.stringtemplate.language;
1
2 import java.util.Iterator;
3 import java.util.NoSuchElementException;
4 import java.lang.reflect.Array;
5
6 /** Iterator for an array so I don't have to copy the array to a List
7 * just to make it iteratable.
8 */
9 public class ArrayIterator implements Iterator {
10 /** Index into the data array */
11 protected int i = -1;
12 protected Object array = null;
13 /** Arrays are fixed size; precompute. */
14 protected int n;
15
16 public ArrayIterator(Object array) {
17 this.array = array;
18 n = Array.getLength(array);
19 }
20
21 public boolean hasNext() {
22 return (i+1)<n && n>0;
23 }
24
25 public Object next() {
26 i++; // move to next element
27 if ( i >= n ) {
28 throw new NoSuchElementException();
29 }
30 return Array.get(array, i);
31 }
32
33 public void remove() {
34 throw new UnsupportedOperationException();
35 }
36 }
0 package org.antlr.stringtemplate.language;
1
2 import java.util.ArrayList;
3 import java.util.Iterator;
4 import java.lang.reflect.Array;
5
6 /** Turn an array into a List; subclass ArrayList for easy development, but
7 * it really doesn't use super stuff for anything. Ensure we create
8 * ArrayIterator for this List.
9 */
10 public class ArrayWrappedInList extends ArrayList {
11 protected Object array = null;
12 /** Arrays are fixed size; precompute. */
13 protected int n;
14
15 public ArrayWrappedInList(Object array) {
16 this.array = array;
17 n = Array.getLength(array);
18 }
19
20 public Object get(int i) {
21 return Array.get(array, i);
22 }
23
24 public int size() {
25 return n;
26 }
27
28 public boolean isEmpty() {
29 return n==0;
30 }
31
32 public Object[] toArray() {
33 return (Object[])array;
34 }
35
36 public Iterator iterator() {
37 return new ArrayIterator(array);
38 }
39 }
0 package org.antlr.stringtemplate.language;
1
2 import java.util.Iterator;
3 import java.util.List;
4 import java.util.AbstractList;
5 import java.util.ArrayList;
6
7 /** Given a list of attributes, return the combined elements in a list. */
8 public class Cat extends AbstractList {
9 protected List elements;
10
11 public Iterator iterator() {
12 return super.iterator();
13 }
14
15 public Object get(int index) {
16 return elements.get(index);
17 }
18
19 public int size() {
20 return elements.size();
21 }
22
23 public Cat(List attributes) {
24 elements = new ArrayList();
25 for (int i = 0; i < attributes.size(); i++) {
26 Object attribute = (Object) attributes.get(i);
27 attribute = ASTExpr.convertAnythingIteratableToIterator(attribute);
28 if ( attribute instanceof Iterator ) {
29 Iterator it = (Iterator)attribute;
30 while (it.hasNext()) {
31 Object o = (Object) it.next();
32 elements.add(o);
33 }
34 }
35 else {
36 elements.add(attribute);
37 }
38 }
39 }
40
41 public String toString() {
42 StringBuffer buf = new StringBuffer();
43 for (int i = 0; i < elements.size(); i++) {
44 Object o = (Object) elements.get(i);
45 buf.append(o);
46 }
47 return buf.toString();
48 }
49 }
0 /*
1 [The "BSD licence"]
2 Copyright (c) 2003-2005 Terence Parr
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package org.antlr.stringtemplate.language;
28
29 import antlr.CommonToken;
30
31 /** Tracks the various string and attribute chunks discovered
32 * by the lexer. Subclassed CommonToken so that I could pass
33 * the indentation to the parser, which will add it to the
34 * ASTExpr created for the $...$ attribute reference.
35 */
36 public class ChunkToken extends CommonToken {
37 protected String indentation;
38
39 public ChunkToken() {
40 super();
41 }
42
43 public ChunkToken(int type, String text, String indentation) {
44 super(type,text);
45 setIndentation(indentation);
46 }
47
48 public String getIndentation() {
49 return indentation;
50 }
51
52 public void setIndentation(String indentation) {
53 this.indentation = indentation;
54 }
55
56 public String toString() {
57 return super.toString()+"<indent='"+indentation+"'>";
58 }
59 }
0 /*
1 [The "BSD licence"]
2 Copyright (c) 2003-2005 Terence Parr
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package org.antlr.stringtemplate.language;
28
29 import antlr.RecognitionException;
30 import antlr.collections.AST;
31 import org.antlr.stringtemplate.StringTemplate;
32 import org.antlr.stringtemplate.StringTemplateWriter;
33
34 import java.io.IOException;
35 import java.util.List;
36 import java.util.ArrayList;
37
38 /** A conditional reference to an embedded subtemplate. */
39 public class ConditionalExpr extends ASTExpr {
40 StringTemplate subtemplate = null;
41 List elseIfSubtemplates = null;
42 StringTemplate elseSubtemplate = null;
43
44 protected static class ElseIfClauseData {
45 ASTExpr expr;
46 StringTemplate st;
47 }
48
49 public ConditionalExpr(StringTemplate enclosingTemplate, AST tree) {
50 super(enclosingTemplate,tree,null);
51 }
52
53 public void setSubtemplate(StringTemplate subtemplate) {
54 this.subtemplate = subtemplate;
55 }
56
57 public void addElseIfSubtemplate(final ASTExpr conditionalTree,
58 final StringTemplate subtemplate)
59 {
60 if ( elseIfSubtemplates==null ) {
61 elseIfSubtemplates = new ArrayList();
62 }
63 ElseIfClauseData d = new ElseIfClauseData() {{
64 expr = conditionalTree;
65 st = subtemplate;
66 }};
67 elseIfSubtemplates.add(d);
68 }
69
70 public StringTemplate getSubtemplate() {
71 return subtemplate;
72 }
73
74 public StringTemplate getElseSubtemplate() {
75 return elseSubtemplate;
76 }
77
78 public void setElseSubtemplate(StringTemplate elseSubtemplate) {
79 this.elseSubtemplate = elseSubtemplate;
80 }
81
82 /** To write out the value of a condition expr, invoke the evaluator in eval.g
83 * to walk the condition tree computing the boolean value. If result
84 * is true, then write subtemplate.
85 */
86 public int write(StringTemplate self, StringTemplateWriter out) throws IOException {
87 if ( exprTree==null || self==null || out==null ) {
88 return 0;
89 }
90 // System.out.println("evaluating conditional tree: "+exprTree.toStringList());
91 ActionEvaluator eval =
92 new ActionEvaluator(self,this,out);
93 int n = 0;
94 try {
95 boolean testedTrue = false;
96 // get conditional from tree and compute result
97 AST cond = exprTree.getFirstChild();
98 boolean includeSubtemplate = eval.ifCondition(cond); // eval and write out tree
99 // System.out.println("subtemplate "+subtemplate);
100 // IF
101 if ( includeSubtemplate ) {
102 n = writeSubTemplate(self, out, subtemplate);
103 testedTrue = true;
104 }
105 // ELSEIF
106 else if ( elseIfSubtemplates!=null && elseIfSubtemplates.size()>0 ) {
107 for (int i=0; i<elseIfSubtemplates.size(); i++) {
108 ElseIfClauseData elseIfClause =
109 (ElseIfClauseData)elseIfSubtemplates.get(i);
110 includeSubtemplate = eval.ifCondition(elseIfClause.expr.exprTree);
111 if ( includeSubtemplate ) {
112 writeSubTemplate(self, out, elseIfClause.st);
113 testedTrue = true;
114 break;
115 }
116 }
117 }
118 // ELSE
119 if ( !testedTrue && elseSubtemplate!=null ) {
120 // evaluate ELSE clause if present and IF condition failed
121 StringTemplate s = elseSubtemplate.getInstanceOf();
122 s.setEnclosingInstance(self);
123 s.setGroup(self.getGroup());
124 s.setNativeGroup(self.getNativeGroup());
125 n = s.write(out);
126 }
127 // cond==false and no else => MISSING output not empty
128 if ( !testedTrue && elseSubtemplate==null ) n = MISSING;
129 }
130 catch (RecognitionException re) {
131 self.error("can't evaluate tree: "+exprTree.toStringList(), re);
132 }
133 return n;
134 }
135
136 protected int writeSubTemplate(StringTemplate self,
137 StringTemplateWriter out,
138 StringTemplate subtemplate)
139 throws IOException
140 {
141 /* To evaluate the IF chunk, make a new instance whose enclosingInstance
142 * points at 'self' so get attribute works. Otherwise, enclosingInstance
143 * points at the template used to make the precompiled code. We need a
144 * new template instance every time we exec this chunk to get the new
145 * "enclosing instance" pointer.
146 */
147 StringTemplate s = subtemplate.getInstanceOf();
148 s.setEnclosingInstance(self);
149 // make sure we evaluate in context of enclosing template's
150 // group so polymorphism works. :)
151 s.setGroup(self.getGroup());
152 s.setNativeGroup(self.getNativeGroup());
153 return s.write(out);
154 }
155 }
0 /*
1 [The "BSD licence"]
2 Copyright (c) 2003-2005 Terence Parr
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package org.antlr.stringtemplate.language;
28
29 import org.antlr.stringtemplate.StringTemplate;
30 import org.antlr.stringtemplate.StringTemplateGroup;
31 import org.antlr.stringtemplate.StringTemplateWriter;
32
33 import java.io.Writer;
34 import java.io.IOException;
35 import java.util.Hashtable;
36 import java.util.Enumeration;
37
38 /** A string template expression embedded within the template.
39 * A template is parsed into a tokenized vector of Expr objects
40 * and then executed after the user sticks in attribute values.
41 *
42 * This list of Expr objects represents a "program" for the StringTemplate
43 * evaluator.
44 */
45 abstract public class Expr {
46 /** The StringTemplate object surrounding this expr */
47 protected StringTemplate enclosingTemplate;
48
49 /** Any thing spit out as a chunk (even plain text) must be indented
50 * according to whitespace before the action that generated it. So,
51 * plain text in the outermost template is never indented, but the
52 * text and attribute references in a nested template will all be
53 * indented by the amount seen directly in front of the attribute
54 * reference that initiates construction of the nested template.
55 */
56 protected String indentation = null;
57
58 public Expr(StringTemplate enclosingTemplate) {
59 this.enclosingTemplate = enclosingTemplate;
60 }
61
62 /** How to write this node to output; return how many char written */
63 abstract public int write(StringTemplate self, StringTemplateWriter out)
64 throws IOException;
65
66 public StringTemplate getEnclosingTemplate() {
67 return enclosingTemplate;
68 }
69
70 public String getIndentation() {
71 return indentation;
72 }
73
74 public void setIndentation(String indentation) {
75 this.indentation = indentation;
76 }
77 }
0 package org.antlr.stringtemplate.language;
1
2 import org.antlr.stringtemplate.StringTemplate;
3
4 import java.util.HashMap;
5 import java.util.Map;
6 import java.util.List;
7 import java.util.LinkedHashMap;
8
9 /** Represents the name of a formal argument
10 * defined in a template:
11 *
12 * group test;
13 * test(a,b) : "$a$ $b$"
14 * t() : "blort"
15 *
16 * Each template has a set of these formal arguments or uses
17 * a placeholder object: UNKNOWN (indicating that no arguments
18 * were specified such as when a template is loaded from a file.st).
19 *
20 * Note: originally, I tracked cardinality as well as the name of an
21 * attribute. I'm leaving the code here as I suspect something may come
22 * of it later. Currently, though, cardinality is not used.
23 */
24 public class FormalArgument {
25 // the following represent bit positions emulating a cardinality bitset.
26 public static final int OPTIONAL = 1; // a?
27 public static final int REQUIRED = 2; // a
28 public static final int ZERO_OR_MORE = 4; // a*
29 public static final int ONE_OR_MORE = 8; // a+
30
31 public static final String[] suffixes = {
32 null,
33 "?",
34 "",
35 null,
36 "*",
37 null,
38 null,
39 null,
40 "+"
41 };
42
43 /** When template arguments are not available such as when the user
44 * uses "new StringTemplate(...)", then the list of formal arguments
45 * must be distinguished from the case where a template can specify
46 * args and there just aren't any such as the t() template above.
47 */
48 public static final LinkedHashMap UNKNOWN = new LinkedHashMap();
49
50 public String name;
51 //protected int cardinality = REQUIRED;
52
53 /** If they specified name="value", store the template here */
54 public StringTemplate defaultValueST;
55
56 public FormalArgument(String name) {
57 this.name = name;
58 }
59
60 public FormalArgument(String name, StringTemplate defaultValueST) {
61 this.name = name;
62 this.defaultValueST = defaultValueST;
63 }
64
65 public static String getCardinalityName(int cardinality) {
66 switch (cardinality) {
67 case OPTIONAL : return "optional";
68 case REQUIRED : return "exactly one";
69 case ZERO_OR_MORE : return "zero-or-more";
70 case ONE_OR_MORE : return "one-or-more";
71 default : return "unknown";
72 }
73 }
74
75 public boolean equals(Object o) {
76 if ( o==null || !(o instanceof FormalArgument) ) {
77 return false;
78 }
79 FormalArgument other = (FormalArgument)o;
80 if ( !this.name.equals(other.name) ) {
81 return false;
82 }
83 // only check if there is a default value; that's all
84 if ( (this.defaultValueST!=null && other.defaultValueST==null) ||
85 (this.defaultValueST==null && other.defaultValueST!=null) ) {
86 return false;
87 }
88 return true;
89 }
90
91 public String toString() {
92 if ( defaultValueST!=null ) {
93 return name+"="+defaultValueST;
94 }
95 return name;
96 }
97 }
0 /*
1 [The "BSD licence"]
2 Copyright (c) 2003-2005 Terence Parr
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package org.antlr.stringtemplate.language;
28
29 import org.antlr.stringtemplate.*;
30 import org.antlr.stringtemplate.language.Expr;
31 import org.antlr.stringtemplate.StringTemplate;
32
33 import java.io.Writer;
34 import java.io.IOException;
35
36 /** Represents a newline. Separated so I can do smart things like not
37 * spitting out newlines when the only thing on a line is an attr expr.
38 */
39 public class NewlineRef extends StringRef {
40 public NewlineRef(StringTemplate enclosingTemplate, String str) {
41 super(enclosingTemplate, str);
42 }
43 }
0 /*
1 [The "BSD licence"]
2 Copyright (c) 2003-2005 Terence Parr
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package org.antlr.stringtemplate.language;
28
29 import org.antlr.stringtemplate.StringTemplate;
30 import org.antlr.stringtemplate.StringTemplateWriter;
31
32 import java.io.IOException;
33
34 /** Represents a chunk of just simple text to spit out; nothing to "evaluate" */
35 public class StringRef extends Expr {
36 String str;
37
38 public StringRef(StringTemplate enclosingTemplate, String str) {
39 super(enclosingTemplate);
40 this.str = str;
41 }
42
43 /** Just print out the string; no reference to self because this
44 * is a literal--not sensitive to attribute values. These strings
45 * never wrap because they are not part of an <...> expression.
46 * <"foo"; wrap="\n"> should wrap though if necessary.
47 */
48 public int write(StringTemplate self, StringTemplateWriter out) throws IOException {
49 if ( str!=null ) {
50 int n = out.write(str);
51 return n;
52 }
53 return 0;
54 }
55
56 public String toString() {
57 if ( str!=null ) {
58 return str;
59 }
60 return "";
61 }
62 }
0 /*
1 [The "BSD licence"]
2 Copyright (c) 2003-2005 Terence Parr
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package org.antlr.stringtemplate.language;
28
29 import antlr.CommonAST;
30 import org.antlr.stringtemplate.StringTemplate;
31
32 public class StringTemplateAST extends CommonAST {
33 protected StringTemplate st = null; // track template for ANONYMOUS blocks
34
35 public StringTemplateAST() {;}
36
37 public StringTemplateAST(int type, String text) {
38 this.setType(type);
39 this.setText(text);
40 }
41
42 public StringTemplate getStringTemplate() {
43 return st;
44 }
45
46 public void setStringTemplate(StringTemplate st) {
47 this.st = st;
48 }
49 }
0 /*
1 [The "BSD licence"]
2 Copyright (c) 2003-2005 Terence Parr
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package org.antlr.stringtemplate.language;
28
29 import antlr.CommonToken;
30 import java.util.List;
31
32 public class StringTemplateToken extends CommonToken {
33 /** Track any args for anonymous templates like
34 * <tokens,rules:{t,r | <t> then <r>}>
35 * The lexer in action.g returns a single token ANONYMOUS_TEMPLATE
36 * and so I need to have it parse args in the lexer and make them
37 * available for when I build the anonymous template.
38 */
39 public List args;
40
41 public StringTemplateToken() {
42 super();
43 }
44
45 public StringTemplateToken(int type, String text) {
46 super(type, text);
47 }
48
49 public StringTemplateToken(String text) {
50 super(text);
51 }
52
53 public StringTemplateToken(int type, String text, List args) {
54 super(type,text);
55 this.args = args;
56 }
57
58 public String toString() {
59 return super.toString()+"; args="+args;
60 }
61 }
62
0 header {
1 /*
2 [The "BSD licence"]
3 Copyright (c) 2003-2004 Terence Parr
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 package org.antlr.stringtemplate.language;
29 import org.antlr.stringtemplate.*;
30 import java.util.*;
31 }
32
33 /** Parse the individual attribute expressions */
34 class ActionParser extends Parser;
35 options {
36 k = 2;
37 buildAST = true;
38 ASTLabelType = "org.antlr.stringtemplate.language.StringTemplateAST";
39 }
40
41 tokens {
42 APPLY; // template application
43 MULTI_APPLY; // parallel array template application
44 ARGS; // subtree is a list of (possibly empty) arguments
45 INCLUDE;// isolated template include (no attribute)
46 CONDITIONAL="if";
47 VALUE; // used for (foo): #(VALUE foo)
48 TEMPLATE;
49 FUNCTION;
50 SINGLEVALUEARG;
51 LIST; // [a,b,c]
52 NOTHING; // empty list element [a, ,c]
53 }
54
55 {
56 protected StringTemplate self = null;
57
58 public ActionParser(TokenStream lexer, StringTemplate self) {
59 this(lexer, 2);
60 this.self = self;
61 }
62
63 public void reportError(RecognitionException e) {
64 StringTemplateGroup group = self.getGroup();
65 if ( group==StringTemplate.defaultGroup ) {
66 self.error("action parse error; template context is "+self.getEnclosingInstanceStackString(), e);
67 }
68 else {
69 self.error("action parse error in group "+self.getGroup().getName()+" line "+self.getGroupFileLine()+"; template context is "+self.getEnclosingInstanceStackString(), e);
70 }
71 }
72 }
73
74 action returns [Map opts=null]
75 : templatesExpr (SEMI! opts=optionList)?
76 | "if"^ LPAREN! ifCondition RPAREN!
77 | "elseif"! LPAREN! ifCondition RPAREN! // return just conditional
78 ;
79
80 optionList! returns [Map opts=new HashMap()]
81 : option[opts] (COMMA option[opts])*
82 ;
83
84 option[Map opts]
85 {
86 Object v=null;
87 }
88 : i:ID
89 ( ASSIGN e:nonAlternatingTemplateExpr {v=#e;}
90 | {v=ASTExpr.EMPTY_OPTION;}
91 )
92 {opts.put(#i.getText(),v);}
93 ;
94
95 templatesExpr
96 : (parallelArrayTemplateApplication)=> parallelArrayTemplateApplication
97 | expr
98 ( c:COLON^ {#c.setType(APPLY);} template (COMMA! template)*
99 )*
100 ;
101
102 parallelArrayTemplateApplication
103 : expr (COMMA! expr)+ c:COLON anonymousTemplate
104 {#parallelArrayTemplateApplication =
105 #(#[MULTI_APPLY,"MULTI_APPLY"],parallelArrayTemplateApplication);}
106 ;
107
108 ifCondition
109 : ifAtom
110 | NOT^ ifAtom
111 ;
112
113 ifAtom
114 : templatesExpr
115 ;
116
117 expr: primaryExpr (PLUS^ primaryExpr)*
118 ;
119
120 primaryExpr
121 : (templateInclude)=>templateInclude // (see past parens to arglist)
122 | atom
123 ( DOT^ // ignore warning on DOT ID
124 ( ID
125 | valueExpr
126 )
127 )*
128 | function
129 ( DOT^
130 ( ID
131 | valueExpr
132 )
133 )*
134 | valueExpr
135 | list
136 ;
137
138 valueExpr
139 : eval:LPAREN^ templatesExpr RPAREN!
140 {#eval.setType(VALUE); #eval.setText("value");}
141 ;
142
143 nonAlternatingTemplateExpr
144 : expr ( c:COLON^ {#c.setType(APPLY);} template )*
145 ;
146
147 function
148 : ( "first"
149 | "rest"
150 | "last"
151 | "length"
152 | "strip"
153 | "trunc"
154 )
155 singleArg
156 {#function = #(#[FUNCTION],function);}
157 ;
158
159 template
160 : ( namedTemplate // foo()
161 | anonymousTemplate // {foo}
162 )
163 {#template = #(#[TEMPLATE],template);}
164 ;
165
166 namedTemplate
167 : ID argList
168 | "super"! DOT! qid:ID {#qid.setText("super."+#qid.getText());} argList
169 | indirectTemplate
170 ;
171
172 anonymousTemplate
173 : t:ANONYMOUS_TEMPLATE
174 {
175 StringTemplate anonymous = new StringTemplate();
176 anonymous.setGroup(self.getGroup());
177 anonymous.setEnclosingInstance(self);
178 anonymous.setTemplate(t.getText());
179 anonymous.defineFormalArguments(((StringTemplateToken)t).args);
180 #t.setStringTemplate(anonymous);
181 }
182 ;
183
184 atom: ID
185 | STRING
186 | INT
187 | ANONYMOUS_TEMPLATE
188 ;
189
190 list: lb:LBRACK^ {#lb.setType(LIST); #lb.setText("value");}
191 listElement (COMMA! listElement)*
192 RBRACK!
193 ;
194
195 listElement
196 : nonAlternatingTemplateExpr
197 | {#listElement = #[NOTHING, "NOTHING"];}
198 ;
199
200 templateInclude
201 : ( id:ID argList
202 | "super"! DOT! qid:ID {#qid.setText("super."+#qid.getText());} argList
203 | indirectTemplate
204 )
205 {#templateInclude = #(#[INCLUDE,"include"], templateInclude);}
206 ;
207
208 /** Match (foo)() and (foo+".terse")() */
209 indirectTemplate!
210 : LPAREN e:templatesExpr RPAREN args:argList
211 {#indirectTemplate = #(#[VALUE,"value"],e,args);}
212 ;
213
214 argList
215 :! LPAREN! RPAREN! {#argList = #[ARGS,"ARGS"];} // view()
216 | (singleArg)=>singleArg // bold(name)
217 | LPAREN! argumentAssignment (COMMA! argumentAssignment)* RPAREN!
218 {#argList = #(#[ARGS,"ARGS"],#argList);}
219 ;
220
221 singleArg
222 : LPAREN! nonAlternatingTemplateExpr RPAREN!
223 {#singleArg = #(#[SINGLEVALUEARG,"SINGLEVALUEARG"],#singleArg);}
224 ;
225
226 argumentAssignment
227 : ID ASSIGN^ nonAlternatingTemplateExpr
228 | DOTDOTDOT
229 ;
230
231
232 class ActionLexer extends Lexer;
233
234 options {
235 k=2;
236 charVocabulary = '\003'..'\uFFFE';
237 testLiterals=false;
238 }
239
240 ID
241 options {
242 testLiterals=true;
243 }
244 : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'/')*
245 ;
246
247 INT : ('0'..'9')+ ;
248
249 STRING
250 : '"'! (ESC_CHAR[true] | ~'"')* '"'!
251 ;
252
253 ANONYMOUS_TEMPLATE
254 {
255 List args=null;
256 StringTemplateToken t = null;
257 }
258 : '{'!
259 ( (TEMPLATE_ARGS)=> args=TEMPLATE_ARGS (options{greedy=true;}:WS_CHAR!)?
260 {
261 // create a special token to track args
262 t = new StringTemplateToken(ANONYMOUS_TEMPLATE,$getText,args);
263 $setToken(t);
264 }
265 |
266 )
267 ('\\'! '{' | '\\'! '}' | ESC_CHAR[false] | NESTED_ANONYMOUS_TEMPLATE | ~'}')*
268 {
269 if ( t!=null ) {
270 t.setText($getText);
271 }
272 }
273 '}'!
274 ;
275
276 protected
277 TEMPLATE_ARGS returns [List args=new ArrayList()]
278 :! (WS_CHAR)? a:ID {args.add(a.getText());}
279 (options{greedy=true;}:(WS_CHAR)? ',' (WS_CHAR)? a2:ID {args.add(a2.getText());})*
280 (WS_CHAR)? '|'
281 ;
282
283 protected
284 NESTED_ANONYMOUS_TEMPLATE
285 : '{' ('\\'! '{' | '\\'! '}' | ESC_CHAR[false] | NESTED_ANONYMOUS_TEMPLATE | ~'}')* '}'
286 ;
287
288 /** Match escape sequences, optionally translating them for strings, but not
289 * for templates. Do \} only when in {...} templates.
290 */
291 protected
292 ESC_CHAR[boolean doEscape]
293 : '\\'
294 ( options {generateAmbigWarnings=false;} // . ambig with others
295 : 'n' {if (doEscape) { $setText("\n"); }}
296 | 'r' {if (doEscape) { $setText("\r"); }}
297 | 't' {if (doEscape) { $setText("\t"); }}
298 | 'b' {if (doEscape) { $setText("\b"); }}
299 | 'f' {if (doEscape) { $setText("\f"); }}
300 | c:. {if (doEscape) {$setText(String.valueOf(c));}}
301 )
302 ;
303
304 LBRACK: '[' ;
305 RBRACK: ']' ;
306 LPAREN : '(' ;
307 RPAREN : ')' ;
308 COMMA : ',' ;
309 DOT : '.' ;
310 ASSIGN : '=' ;
311 COLON : ':' ;
312 PLUS : '+' ;
313 SEMI : ';' ;
314 NOT : '!' ;
315 DOTDOTDOT : "..." ;
316
317 WS : (' '|'\t'|'\r'|'\n'{newline();})+ {$setType(Token.SKIP);}
318 ;
319
320 protected
321 WS_CHAR
322 : ' '|'\t'|'\r'|'\n'{newline();}
323 ;
0 header {
1 /*
2 [The "BSD licence"]
3 Copyright (c) 2003-2004 Terence Parr
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 package org.antlr.stringtemplate.language;
29 import org.antlr.stringtemplate.*;
30 import java.io.*;
31 }
32
33 /** Break up an input text stream into chunks of either plain text
34 * or template actions in "<...>". Treat IF and ENDIF tokens
35 * specially.
36 */
37 class AngleBracketTemplateLexer extends Lexer;
38
39 options {
40 importVocab=TemplateParser;
41 k=7; // see "<endif>"
42 charVocabulary = '\u0001'..'\uFFFE';
43 }
44
45 {
46 protected String currentIndent = null;
47 protected StringTemplate self;
48
49 public AngleBracketTemplateLexer(StringTemplate self, Reader r) {
50 this(r);
51 this.self = self;
52 }
53
54 public void reportError(RecognitionException e) {
55 self.error("<...> chunk lexer error", e);
56 }
57
58 protected boolean upcomingELSE(int i) throws CharStreamException {
59 return LA(i)=='<'&&LA(i+1)=='e'&&LA(i+2)=='l'&&LA(i+3)=='s'&&LA(i+4)=='e'&&
60 LA(i+5)=='>';
61 }
62
63 protected boolean upcomingENDIF(int i) throws CharStreamException {
64 return LA(i)=='<'&&LA(i+1)=='e'&&LA(i+2)=='n'&&LA(i+3)=='d'&&LA(i+4)=='i'&&
65 LA(i+5)=='f'&&LA(i+6)=='>';
66 }
67
68 protected boolean upcomingAtEND(int i) throws CharStreamException {
69 return LA(i)=='<'&&LA(i+1)=='@'&&LA(i+2)=='e'&&LA(i+3)=='n'&&LA(i+4)=='d'&&LA(i+5)=='>';
70 }
71
72 protected boolean upcomingNewline(int i) throws CharStreamException {
73 return (LA(i)=='\r'&&LA(i+1)=='\n')||LA(i)=='\n';
74 }
75 }
76
77 LITERAL
78 : {LA(1)!='\r'&&LA(1)!='\n'}?
79 ( options { generateAmbigWarnings=false; }
80 {
81 int loopStartIndex=text.length();
82 int col=getColumn();
83 }
84 : '\\'! '<' // allow escaped delimiter
85 | '\\'! '>'
86 | '\\'! '\\' // always replace \\ with \
87 | '\\' ~('<'|'>') // otherwise ignore escape char
88 | ind:INDENT
89 {
90 if ( col==1 && LA(1)=='<' ) {
91 // store indent in ASTExpr not in a literal
92 currentIndent=ind.getText();
93 text.setLength(loopStartIndex); // reset length to wack text
94 }
95 else currentIndent=null;
96 }
97 | ~('<'|'\r'|'\n')
98 )+
99 {if (($getText).length()==0) {$setType(Token.SKIP);}} // pure indent?
100 ;
101
102 protected
103 INDENT
104 : ( options {greedy=true;}: ' ' | '\t')+
105 ;
106
107 NEWLINE
108 : ('\r')? '\n' {newline(); currentIndent=null;}
109 ;
110
111 ACTION
112 options {
113 generateAmbigWarnings=false; // <EXPR> is ambig with <!..!>
114 }
115 {
116 int startCol = getColumn();
117 }
118 : LINE_BREAK {$setType(Token.SKIP);}
119 | // Match escapes not in a string like <\n\ufea5>
120 {StringBuffer buf = new StringBuffer(); char uc = '\u0000';}
121 '<'! (uc=ESC_CHAR {buf.append(uc);} )+'>'!
122 {$setText(buf.toString()); $setType(LITERAL);}
123 | COMMENT {$setType(Token.SKIP);}
124 | (
125 options {
126 generateAmbigWarnings=false; // $EXPR$ is ambig with $endif$ etc...
127 }
128 : '<'! "if" (' '!)* "(" IF_EXPR ")" '>'! {$setType(TemplateParser.IF);}
129 ( ('\r'!)? '\n'! {newline();})? // ignore any newline right after an IF
130 | '<'! "elseif" (' '!)* "(" IF_EXPR ")" '>'! {$setType(TemplateParser.ELSEIF);}
131 ( ('\r'!)? '\n'! {newline();})? // ignore any newline right after an IF
132 | '<'! "else" '>'! {$setType(TemplateParser.ELSE);}
133 ( ('\r'!)? '\n'! {newline();})? // ignore any newline right after an ELSE
134 | '<'! "endif" '>'! {$setType(TemplateParser.ENDIF);}
135 ( {startCol==1}? ('\r'!)? '\n'! {newline();})? // ignore after ENDIF if on line by itself
136
137 | // match <@foo()> => foo
138 // match <@foo>...<@end> => foo::=...
139 '<'! '@'! (~('>'|'('))+
140 ( "()"! '>'! {$setType(TemplateParser.REGION_REF);}
141 | '>'!
142 {
143 $setType(TemplateParser.REGION_DEF);
144 String t=$getText;
145 $setText(t+"::=");
146 }
147 ( options {greedy=true;} : ('\r'!)? '\n'! {newline();})?
148 {boolean atLeft = false;}
149 (
150 options {greedy=true;} // handle greedy=false with predicate
151 : {!(upcomingAtEND(1)||(upcomingNewline(1)&&upcomingAtEND(2)))}?
152 ( ('\r')? '\n' {newline(); atLeft = true;}
153 | . {atLeft = false;}
154 )
155 )+
156 ( ('\r'!)? '\n'! {newline(); atLeft = true;} )?
157 ( "<@end>"!
158 | . {self.error("missing region "+t+" <@end> tag");}
159 )
160 ( {atLeft}? ('\r'!)? '\n'! {newline();})?
161 )
162
163 | '<'! EXPR '>'!
164 )
165 {
166 ChunkToken t = new ChunkToken(_ttype, $getText, currentIndent);
167 $setToken(t);
168 }
169 ;
170
171 protected
172 EXPR: ( ESC
173 | ('\r')? '\n' {newline();}
174 | SUBTEMPLATE
175 | ('='|'+') TEMPLATE
176 | ('='|'+') SUBTEMPLATE
177 | ('='|'+') ~('"'|'<'|'{')
178 | ~'>'
179 )+
180 ;
181
182 protected
183 TEMPLATE
184 : '"' ( ESC | ~'"' )* '"'
185 | "<<"
186 (options {greedy=true;}:('\r'!)?'\n'! {newline();})? // consume 1st \n
187 ( options {greedy=false;} // stop when you see the >>
188 : {LA(3)=='>'&&LA(4)=='>'}? '\r'! '\n'! {newline();} // kill last \r\n
189 | {LA(2)=='>'&&LA(3)=='>'}? '\n'! {newline();} // kill last \n
190 | ('\r')? '\n' {newline();} // else keep
191 | .
192 )*
193 ">>"
194 ;
195
196 protected
197 IF_EXPR:( ESC
198 | ('\r')? '\n' {newline();}
199 | SUBTEMPLATE
200 | NESTED_PARENS
201 | ~')'
202 )+
203 ;
204
205 protected
206 ESC_CHAR returns [char uc='\u0000']
207 : "\\n"! {uc = '\n';}
208 | "\\r"! {uc = '\r';}
209 | "\\t"! {uc = '\t';}
210 | "\\ "! {uc = ' ';}
211 | "\\u"! a:HEX! b:HEX! c:HEX! d:HEX!
212 {uc = (char)Integer.parseInt(a.getText()+b.getText()+c.getText()+d.getText(), 16);}
213 ;
214
215 // just used to skip stuff (not part of unicode escape stuff)
216 protected
217 ESC : '\\' . // ('<'|'>'|'n'|'t'|'"'|'\''|':'|'{'|'}'|'\\')
218 ;
219
220 protected
221 HEX : '0'..'9'|'A'..'F'|'a'..'f'
222 ;
223
224 protected
225 SUBTEMPLATE
226 : '{' (SUBTEMPLATE|ESC|~'}')* '}'
227 ;
228
229 protected
230 NESTED_PARENS
231 : '(' (options {greedy=false;}:NESTED_PARENS|ESC|~')')+ ')'
232 ;
233
234 protected
235 COMMENT
236 {
237 int startCol = getColumn();
238 }
239 : "<!"
240 ( options {greedy=false;}
241 : ('\r')? '\n' {newline();}
242 | .
243 )*
244 "!>" ( {startCol==1}? ('\r')? '\n' {newline();} )?
245 ;
246
247 protected
248 LINE_BREAK
249 : "<\\\\>" (INDENT)? ('\r')? '\n' {newline();} (INDENT)?
250 ;
0 header {
1 /*
2 [The "BSD licence"]
3 Copyright (c) 2003-2004 Terence Parr
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 package org.antlr.stringtemplate.language;
29 import org.antlr.stringtemplate.*;
30 import java.util.*;
31 import java.io.*;
32 import java.lang.reflect.*;
33 }
34
35 class ActionEvaluator extends TreeParser;
36
37 options {
38 importVocab=ActionParser;
39 ASTLabelType = "org.antlr.stringtemplate.language.StringTemplateAST";
40 }
41
42 {
43 public static class NameValuePair {
44 public String name;
45 public Object value;
46 };
47
48 protected StringTemplate self = null;
49 protected StringTemplateWriter out = null;
50 protected ASTExpr chunk = null;
51
52 /** Create an evaluator using attributes from self */
53 public ActionEvaluator(StringTemplate self, ASTExpr chunk, StringTemplateWriter out) {
54 this.self = self;
55 this.chunk = chunk;
56 this.out = out;
57 }
58
59 public void reportError(RecognitionException e) {
60 self.error("eval tree parse error", e);
61 }
62 }
63
64 action returns [int numCharsWritten=0]
65 {
66 Object e=null;
67 }
68 : e=expr {numCharsWritten = chunk.writeAttribute(self,e,out);}
69 ;
70
71 expr returns [Object value=null]
72 {
73 Object a=null, b=null, e=null;
74 Map argumentContext=null;
75 }
76 : #(PLUS a=expr b=expr {value = chunk.add(a,b);})
77 | value=templateApplication
78 | value=attribute
79 | value=templateInclude
80 | value=function
81 | value=list
82 | #(VALUE e=expr)
83 // convert to string (force early eval)
84 {
85 StringWriter buf = new StringWriter();
86 StringTemplateWriter sw =
87 self.getGroup().getStringTemplateWriter(buf);
88 int n = chunk.writeAttribute(self,e,sw);
89 if ( n > 0 ) {
90 value = buf.toString();
91 }
92 }
93 ;
94
95 /** create a new list of expressions as a new multi-value attribute */
96 list returns [Object value=null]
97 {
98 Object e = null;
99 List elements = new ArrayList();
100 }
101 : #( LIST
102 ( e=expr
103 {
104 if ( e!=null ) {
105 elements.add(e);
106 }
107 }
108 | NOTHING
109 {
110 List nullSingleton = new ArrayList() {{add(null);}};
111 elements.add(nullSingleton.iterator()); // add a blank
112 }
113 )+
114 )
115 {value = new Cat(elements);}
116 ;
117
118 templateInclude returns [Object value=null]
119 {
120 StringTemplateAST args = null;
121 String name = null;
122 Object n = null;
123 }
124 : #( INCLUDE
125 // {value = chunk.getTemplateInclude(self, name.getText(), #args);}
126 ( id:ID a1:.
127 {name=id.getText(); args=#a1;}
128
129 | #( VALUE n=expr a2:. )
130 {if (n!=null) {name=n.toString();} args=#a2;}
131
132 )
133 )
134 {
135 if ( name!=null ) {
136 value = chunk.getTemplateInclude(self, name, args);
137 }
138 }
139 ;
140
141 /** Apply template(s) to an attribute; can be applied to another apply
142 * result.
143 */
144 templateApplication returns [Object value=null]
145 {
146 Object a=null;
147 Vector templatesToApply=new Vector();
148 List attributes = new ArrayList();
149 }
150 : #( APPLY a=expr
151 (template[templatesToApply])+
152 {value = chunk.applyListOfAlternatingTemplates(self,a,templatesToApply);}
153 )
154 | #( MULTI_APPLY (a=expr {attributes.add(a);} )+ COLON
155 anon:ANONYMOUS_TEMPLATE
156 {
157 StringTemplate anonymous = anon.getStringTemplate();
158 templatesToApply.addElement(anonymous);
159 value = chunk.applyTemplateToListOfAttributes(self,
160 attributes,
161 anon.getStringTemplate());
162 }
163 )
164 ;
165
166 function returns [Object value=null]
167 {
168 Object a;
169 }
170 : #( FUNCTION
171 ( "first" a=singleFunctionArg {value=chunk.first(a);}
172 | "rest" a=singleFunctionArg {value=chunk.rest(a);}
173 | "last" a=singleFunctionArg {value=chunk.last(a);}
174 | "length" a=singleFunctionArg {value=chunk.length(a);}
175 | "strip" a=singleFunctionArg {value=chunk.strip(a);}
176 | "trunc" a=singleFunctionArg {value=chunk.trunc(a);}
177 )
178
179 )
180 ;
181
182 singleFunctionArg returns [Object value=null]
183 : #( SINGLEVALUEARG value=expr )
184 ;
185
186 template[Vector templatesToApply]
187 {
188 Map argumentContext = null;
189 Object n = null;
190 }
191 : #( TEMPLATE
192 ( t:ID args:. // don't eval argList now; must re-eval each iteration
193 {
194 String templateName = t.getText();
195 StringTemplateGroup group = self.getGroup();
196 StringTemplate embedded = group.getEmbeddedInstanceOf(self, templateName);
197 if ( embedded!=null ) {
198 embedded.setArgumentsAST(#args);
199 templatesToApply.addElement(embedded);
200 }
201 }
202
203 | anon:ANONYMOUS_TEMPLATE
204 {
205 StringTemplate anonymous = anon.getStringTemplate();
206 // to properly see overridden templates, always set
207 // anonymous' group to be self's group
208 anonymous.setGroup(self.getGroup());
209 templatesToApply.addElement(anonymous);
210 }
211
212 | #( VALUE n=expr args2:.
213 {
214 StringTemplate embedded = null;
215 if ( n!=null ) {
216 String templateName = n.toString();
217 StringTemplateGroup group = self.getGroup();
218 embedded = group.getEmbeddedInstanceOf(self, templateName);
219 if ( embedded!=null ) {
220 embedded.setArgumentsAST(#args2);
221 templatesToApply.addElement(embedded);
222 }
223 }
224 }
225 )
226 )
227 )
228 ;
229
230 ifCondition returns [boolean value=false]
231 {
232 Object a=null, b=null;
233 }
234 : a=ifAtom {value = chunk.testAttributeTrue(a);}
235 | #(NOT a=ifAtom) {value = !chunk.testAttributeTrue(a);}
236 ;
237
238 ifAtom returns [Object value=null]
239 : value=expr
240 ;
241
242 attribute returns [Object value=null]
243 {
244 Object obj = null;
245 Object propName = null;
246 Object e = null;
247 }
248 : #( DOT obj=expr
249 ( prop:ID {propName = prop.getText();}
250 // don't force early eval here in case it's a map
251 // we need the right type on the key.
252 // E.g., <aMap.keys:{k|<k>:<aMap.(k)>}>
253 // If aMap has Integer keys, can't convert k to string then lookup.
254 | #(VALUE e=expr) {if (e!=null) {propName=e;}}
255 )
256 )
257 {value = chunk.getObjectProperty(self,obj,propName);}
258
259 | i3:ID
260 {
261 value=self.getAttribute(i3.getText());
262 }
263
264 | i:INT {value=new Integer(i.getText());}
265
266 | s:STRING
267 {
268 value=s.getText();
269 }
270
271 | at:ANONYMOUS_TEMPLATE
272 {
273 value=at.getText();
274 if ( at.getText()!=null ) {
275 StringTemplate valueST =new StringTemplate(self.getGroup(), at.getText());
276 valueST.setEnclosingInstance(self);
277 valueST.setName("<anonymous template argument>");
278 value = valueST;
279 }
280 }
281 ;
282
283 /** self is assumed to be the enclosing context as foo(x=y) must find y in
284 * the template that encloses the ref to foo(x=y). We must pass in
285 * the embedded template (the one invoked) so we can check formal args
286 * in rawSetArgumentAttribute.
287 */
288 argList[StringTemplate embedded, Map initialContext]
289 returns [Map argumentContext=null]
290 {
291 argumentContext = initialContext;
292 if ( argumentContext==null ) {
293 argumentContext=new HashMap();
294 }
295 }
296 : #( ARGS (argumentAssignment[embedded,argumentContext])* )
297 | singleTemplateArg[embedded,argumentContext]
298 ;
299
300 singleTemplateArg[StringTemplate embedded, Map argumentContext]
301 {
302 Object e = null;
303 }
304 : #( SINGLEVALUEARG e=expr )
305 {
306 if ( e!=null ) {
307 String soleArgName = null;
308 // find the sole defined formal argument for embedded
309 boolean error = false;
310 Map formalArgs = embedded.getFormalArguments();
311 if ( formalArgs!=null ) {
312 Set argNames = formalArgs.keySet();
313 if ( argNames.size()==1 ) {
314 soleArgName = (String)argNames.toArray()[0];
315 //System.out.println("sole formal arg of "+embedded.getName()+" is "+soleArgName);
316 }
317 else {
318 error=true;
319 }
320 }
321 else {
322 error=true;
323 }
324 if ( error ) {
325 self.error("template "+embedded.getName()+
326 " must have exactly one formal arg in template context "+
327 self.getEnclosingInstanceStackString());
328 }
329 else {
330 self.rawSetArgumentAttribute(embedded,argumentContext,soleArgName,e);
331 }
332 }
333 }
334 ;
335
336 argumentAssignment[StringTemplate embedded, Map argumentContext]
337 {
338 Object e = null;
339 }
340 : #( ASSIGN arg:ID e=expr )
341 {
342 if ( e!=null ) {
343 self.rawSetArgumentAttribute(embedded,argumentContext,arg.getText(),e);
344 }
345 }
346 | DOTDOTDOT {embedded.setPassThroughAttributes(true);}
347 ;
348
0 header {
1 /*
2 [The "BSD licence"]
3 Copyright (c) 2003-2004 Terence Parr
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 package org.antlr.stringtemplate.language;
29 import org.antlr.stringtemplate.*;
30 import java.util.*;
31 }
32
33 /** Match a group of template definitions beginning
34 * with a group name declaration. Templates are enclosed
35 * in double-quotes or <<...>> quotes for multi-line templates.
36 * Template names have arg lists that indicate the cardinality
37 * of the attribute: present, optional, zero-or-more, one-or-more.
38 * Here is a sample group file:
39
40 group nfa;
41
42 // an NFA has edges and states
43 nfa(states,edges) ::= <<
44 digraph NFA {
45 rankdir=LR;
46 <states; separator="\\n">
47 <edges; separator="\\n">
48 }
49 >>
50
51 state(name) ::= "node [shape = circle]; <name>;"
52
53 */
54 class GroupParser extends Parser;
55
56 options {
57 k=3;
58 }
59
60 {
61 protected StringTemplateGroup group;
62
63 public void reportError(RecognitionException e) {
64 if ( group!=null ) {
65 group.error("template group parse error", e);
66 }
67 else {
68 System.err.println("template group parse error: "+e);
69 e.printStackTrace(System.err);
70 }
71 }
72 }
73
74 group[StringTemplateGroup g]
75 {
76 this.group = g;
77 }
78 : "group" name:ID {g.setName(name.getText());}
79 ( COLON s:ID {g.setSuperGroup(s.getText());} )?
80 ( "implements" i:ID {g.implementInterface(i.getText());}
81 (COMMA i2:ID {g.implementInterface(i2.getText());} )*
82 )?
83 SEMI
84 ( template[g] | mapdef[g] )+
85 ;
86
87 template[StringTemplateGroup g]
88 {
89 Map formalArgs = null;
90 StringTemplate st = null;
91 boolean ignore = false;
92 String templateName=null;
93 int line = LT(1).getLine();
94 }
95 : ( AT scope:ID DOT region:ID
96 {
97 templateName=g.getMangledRegionName(scope.getText(),region.getText());
98 if ( g.isDefinedInThisGroup(templateName) ) {
99 g.error("group "+g.getName()+" line "+line+": redefinition of template region: @"+
100 scope.getText()+"."+region.getText());
101 st = new StringTemplate(); // create bogus template to fill in
102 }
103 else {
104 boolean err = false;
105 // @template.region() ::= "..."
106 StringTemplate scopeST = g.lookupTemplate(scope.getText());
107 if ( scopeST==null ) {
108 g.error("group "+g.getName()+" line "+line+": reference to region within undefined template: "+
109 scope.getText());
110 err=true;
111 }
112 if ( !scopeST.containsRegionName(region.getText()) ) {
113 g.error("group "+g.getName()+" line "+line+": template "+scope.getText()+" has no region called "+
114 region.getText());
115 err=true;
116 }
117 if ( err ) {
118 st = new StringTemplate();
119 }
120 else {
121 st = g.defineRegionTemplate(scope.getText(),
122 region.getText(),
123 null,
124 StringTemplate.REGION_EXPLICIT);
125 }
126 }
127 }
128 | name:ID {templateName = name.getText();}
129 {
130 if ( g.isDefinedInThisGroup(templateName) ) {
131 g.error("redefinition of template: "+templateName);
132 st = new StringTemplate(); // create bogus template to fill in
133 }
134 else {
135 st = g.defineTemplate(templateName, null);
136 }
137 }
138 )
139 {if ( st!=null ) {st.setGroupFileLine(line);}}
140 LPAREN
141 (args[st]|{st.defineEmptyFormalArgumentList();})
142 RPAREN
143 DEFINED_TO_BE
144 ( t:STRING {st.setTemplate(t.getText());}
145 | bt:BIGSTRING {st.setTemplate(bt.getText());}
146 )
147
148 | alias:ID DEFINED_TO_BE target:ID
149 {g.defineTemplateAlias(alias.getText(), target.getText());}
150 ;
151
152 args[StringTemplate st]
153 : arg[st] ( COMMA arg[st] )*
154 ;
155
156 arg[StringTemplate st]
157 {
158 StringTemplate defaultValue = null;
159 }
160 : name:ID
161 ( ASSIGN s:STRING
162 {
163 defaultValue=new StringTemplate("$_val_$");
164 defaultValue.setAttribute("_val_", s.getText());
165 defaultValue.defineFormalArgument("_val_");
166 defaultValue.setName("<"+st.getName()+"'s arg "+name.getText()+" default value subtemplate>");
167 }
168 | ASSIGN bs:ANONYMOUS_TEMPLATE
169 {
170 defaultValue=new StringTemplate(st.getGroup(), bs.getText());
171 defaultValue.setName("<"+st.getName()+"'s arg "+name.getText()+" default value subtemplate>");
172 }
173 )?
174 {st.defineFormalArgument(name.getText(), defaultValue);}
175 ;
176
177 /*
178 suffix returns [int cardinality=FormalArgument.REQUIRED]
179 : OPTIONAL {cardinality=FormalArgument.OPTIONAL;}
180 | STAR {cardinality=FormalArgument.ZERO_OR_MORE;}
181 | PLUS {cardinality=FormalArgument.ONE_OR_MORE;}
182 |
183 ;
184 */
185
186 mapdef[StringTemplateGroup g]
187 {
188 Map m=null;
189 }
190 : name:ID
191 DEFINED_TO_BE m=map
192 {
193 if ( g.getMap(name.getText())!=null ) {
194 g.error("redefinition of map: "+name.getText());
195 }
196 else if ( g.isDefinedInThisGroup(name.getText()) ) {
197 g.error("redefinition of template as map: "+name.getText());
198 }
199 else {
200 g.defineMap(name.getText(), m);
201 }
202 }
203 ;
204
205 map returns [Map mapping=new HashMap()]
206 : LBRACK mapPairs[mapping] RBRACK
207 ;
208
209 mapPairs [Map mapping]
210 : keyValuePair[mapping] (COMMA keyValuePair[mapping])*
211 (COMMA defaultValuePair[mapping])?
212 | defaultValuePair[mapping]
213 ;
214
215 defaultValuePair[Map mapping]
216 {
217 StringTemplate v = null;
218 }
219 : "default" COLON v=keyValue
220 {mapping.put(ASTExpr.DEFAULT_MAP_VALUE_NAME, v);}
221 ;
222
223 keyValuePair[Map mapping]
224 {
225 StringTemplate v = null;
226 }
227 : key:STRING COLON v=keyValue {mapping.put(key.getText(), v);}
228 ;
229
230 keyValue returns [StringTemplate value=null]
231 : s1:BIGSTRING {value = new StringTemplate(group,s1.getText());}
232 | s2:STRING {value = new StringTemplate(group,s2.getText());}
233 | k:ID {k.getText().equals("key")}?
234 {value = ASTExpr.MAP_KEY_VALUE;}
235 | {value = null;}
236 ;
237
238 class GroupLexer extends Lexer;
239
240 options {
241 k=2;
242 charVocabulary = '\u0000'..'\uFFFE';
243 testLiterals=false;
244 }
245
246 ID
247 options {
248 testLiterals=true;
249 }
250 : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'-'|'_')*
251 ;
252
253 STRING
254 : '"'! ( '\\'! '"' | '\\' ~'"' | ~'"' )* '"'!
255 ;
256
257 BIGSTRING
258 : "<<"!
259 (options {greedy=true;}:('\r'!)?'\n'! {newline();})? // consume 1st \n
260 ( options {greedy=false;} // stop when you see the >>
261 : {LA(3)=='>'&&LA(4)=='>'}? '\r'! '\n'! {newline();} // kill last \r\n
262 | {LA(2)=='>'&&LA(3)=='>'}? '\n'! {newline();} // kill last \n
263 | ('\r')? '\n' {newline();} // else keep
264 | '\\'! '>' // \> escape
265 | .
266 )*
267 ">>"!
268 ;
269
270 ANONYMOUS_TEMPLATE
271 {
272 List args=null;
273 StringTemplateToken t = null;
274 }
275 : '{'!
276 ( options {greedy=false;} // stop when you see the >>
277 : ('\r')? '\n' {newline();} // else keep
278 | '\\'! '}' // \} escape
279 | .
280 )*
281 '}'!
282 ;
283
284
285 AT : '@' ;
286 LPAREN: '(' ;
287 RPAREN: ')' ;
288 LBRACK: '[' ;
289 RBRACK: ']' ;
290 COMMA: ',' ;
291 DOT: '.' ;
292 DEFINED_TO_BE: "::=" ;
293 SEMI: ';' ;
294 COLON: ':' ;
295 STAR: '*' ;
296 PLUS: '+' ;
297 ASSIGN: '=' ;
298 OPTIONAL : '?' ;
299
300 // Single-line comments
301 SL_COMMENT
302 : "//"
303 (~('\n'|'\r'))* (('\r')? '\n')?
304 {$setType(Token.SKIP); newline();}
305 ;
306
307 // multiple-line comments
308 ML_COMMENT
309 : "/*"
310 (
311 options {
312 greedy=false;
313 }
314 : ('\r')? '\n' {newline();}
315 | .
316 )*
317 "*/"
318 {$setType(Token.SKIP);}
319 ;
320
321 // Whitespace -- ignored
322 WS : ( ' '
323 | '\t'
324 | '\f'
325 | ('\r')? '\n' { newline(); }
326 )+
327 { $setType(Token.SKIP); }
328 ;
0 header {
1 /*
2 [The "BSD licence"]
3 Copyright (c) 2003-2004 Terence Parr
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 package org.antlr.stringtemplate.language;
29 import org.antlr.stringtemplate.*;
30 import java.util.*;
31 }
32
33 /** Match an ST group interface. Just a list of template names with args.
34 * Here is a sample interface file:
35 *
36 * interface nfa;
37 * nfa(states,edges);
38 * optional state(name);
39 */
40 class InterfaceParser extends Parser;
41
42 options {
43 k=3;
44 }
45
46 {
47 protected StringTemplateGroupInterface groupI;
48
49 public void reportError(RecognitionException e) {
50 if ( groupI!=null ) {
51 groupI.error("template group interface parse error", e);
52 }
53 else {
54 System.err.println("template group interface parse error: "+e);
55 e.printStackTrace(System.err);
56 }
57 }
58 }
59
60 groupInterface[StringTemplateGroupInterface groupI]
61 {this.groupI = groupI;}
62 : "interface" name:ID {groupI.setName(name.getText());} SEMI
63 ( template[groupI] )+
64 ;
65
66 template[StringTemplateGroupInterface groupI]
67 {
68 LinkedHashMap formalArgs = new LinkedHashMap(); // leave blank if no args
69 String templateName=null;
70 }
71 : (opt:"optional")? name:ID LPAREN (formalArgs=args)? RPAREN SEMI
72 {
73 templateName = name.getText();
74 groupI.defineTemplate(templateName, formalArgs, opt!=null);
75 }
76 ;
77
78 args returns [LinkedHashMap args=new LinkedHashMap()]
79 : a:ID {args.put(a.getText(), new FormalArgument(a.getText()));}
80 ( COMMA b:ID {args.put(b.getText(), new FormalArgument(b.getText()));} )*
81 ;
82
83
84 class InterfaceLexer extends Lexer;
85
86 options {
87 k=2;
88 charVocabulary = '\u0000'..'\uFFFE';
89 }
90
91 ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'-'|'_')*
92 ;
93
94 LPAREN: '(' ;
95 RPAREN: ')' ;
96 COMMA: ',' ;
97 SEMI: ';' ;
98 COLON: ':' ;
99
100 // Single-line comments
101 SL_COMMENT
102 : "//"
103 (~('\n'|'\r'))* (('\r')? '\n')?
104 {$setType(Token.SKIP); newline();}
105 ;
106
107 // multiple-line comments
108 ML_COMMENT
109 : "/*"
110 (
111 options {
112 greedy=false;
113 }
114 : ('\r')? '\n' {newline();}
115 | .
116 )*
117 "*/"
118 {$setType(Token.SKIP);}
119 ;
120
121 // Whitespace -- ignored
122 WS : ( ' '
123 | '\t'
124 | '\f'
125 | ('\r')? '\n' { newline(); }
126 )+
127 { $setType(Token.SKIP); }
128 ;
0 header {
1 /*
2 [The "BSD licence"]
3 Copyright (c) 2003-2004 Terence Parr
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 package org.antlr.stringtemplate.language;
29 import org.antlr.stringtemplate.*;
30 import java.io.*;
31 }
32
33 /** A parser used to break up a single template into chunks, text literals
34 * and attribute expressions.
35 */
36 class TemplateParser extends Parser;
37
38 {
39 protected StringTemplate self;
40
41 public void reportError(RecognitionException e) {
42 StringTemplateGroup group = self.getGroup();
43 if ( group==StringTemplate.defaultGroup ) {
44 self.error("template parse error; template context is "+self.getEnclosingInstanceStackString(), e);
45 }
46 else {
47 self.error("template parse error in group "+self.getGroup().getName()+" line "+self.getGroupFileLine()+"; template context is "+self.getEnclosingInstanceStackString(), e);
48 }
49 }
50 }
51
52 template[StringTemplate self]
53 {
54 this.self = self;
55 }
56 : ( s:LITERAL {self.addChunk(new StringRef(self,s.getText()));}
57 | nl:NEWLINE
58 {
59 if ( LA(1)!=ELSE && LA(1)!=ENDIF ) {
60 self.addChunk(new NewlineRef(self,nl.getText()));
61 }
62 }
63 | action[self]
64 )*
65 ;
66
67 action[StringTemplate self]
68 : a:ACTION
69 {
70 String indent = ((ChunkToken)a).getIndentation();
71 ASTExpr c = self.parseAction(a.getText());
72 c.setIndentation(indent);
73 self.addChunk(c);
74 }
75
76 | i:IF
77 {
78 ConditionalExpr c = (ConditionalExpr)self.parseAction(i.getText());
79 // create and precompile the subtemplate
80 StringTemplate subtemplate =
81 new StringTemplate(self.getGroup(), null);
82 subtemplate.setEnclosingInstance(self);
83 subtemplate.setName(i.getText()+"_subtemplate");
84 self.addChunk(c);
85 }
86
87 template[subtemplate] {if ( c!=null ) c.setSubtemplate(subtemplate);}
88
89 ( ei:ELSEIF
90 {
91 ASTExpr ec = self.parseAction(ei.getText());
92 // create and precompile the subtemplate
93 StringTemplate elseIfSubtemplate =
94 new StringTemplate(self.getGroup(), null);
95 elseIfSubtemplate.setEnclosingInstance(self);
96 elseIfSubtemplate.setName(ei.getText()+"_subtemplate");
97 }
98
99 template[elseIfSubtemplate]
100
101 {if ( c!=null ) c.addElseIfSubtemplate(ec, elseIfSubtemplate);}
102 )*
103
104 ( ELSE
105 {
106 // create and precompile the subtemplate
107 StringTemplate elseSubtemplate =
108 new StringTemplate(self.getGroup(), null);
109 elseSubtemplate.setEnclosingInstance(self);
110 elseSubtemplate.setName("else_subtemplate");
111 }
112
113 template[elseSubtemplate]
114 {if ( c!=null ) c.setElseSubtemplate(elseSubtemplate);}
115 )?
116
117 ENDIF
118
119 | rr:REGION_REF
120 {
121 // define implicit template and
122 // convert <@r()> to <region__enclosingTemplate__r()>
123 String regionName = rr.getText();
124 String mangledRef = null;
125 boolean err = false;
126 // watch out for <@super.r()>; that does NOT def implicit region
127 // convert to <super.region__enclosingTemplate__r()>
128 if ( regionName.startsWith("super.") ) {
129 //System.out.println("super region ref "+regionName);
130 String regionRef =
131 regionName.substring("super.".length(),regionName.length());
132 String templateScope =
133 self.getGroup().getUnMangledTemplateName(self.getName());
134 StringTemplate scopeST = self.getGroup().lookupTemplate(templateScope);
135 if ( scopeST==null ) {
136 self.getGroup().error("reference to region within undefined template: "+
137 templateScope);
138 err=true;
139 }
140 if ( !scopeST.containsRegionName(regionRef) ) {
141 self.getGroup().error("template "+templateScope+" has no region called "+
142 regionRef);
143 err=true;
144 }
145 else {
146 mangledRef =
147 self.getGroup().getMangledRegionName(templateScope,regionRef);
148 mangledRef = "super."+mangledRef;
149 }
150 }
151 else {
152 //System.out.println("region ref "+regionName);
153 StringTemplate regionST =
154 self.getGroup().defineImplicitRegionTemplate(self,regionName);
155 mangledRef = regionST.getName();
156 }
157
158 if ( !err ) {
159 // treat as regular action: mangled template include
160 String indent = ((ChunkToken)rr).getIndentation();
161 ASTExpr c = self.parseAction(mangledRef+"()");
162 c.setIndentation(indent);
163 self.addChunk(c);
164 }
165 }
166
167 | rd:REGION_DEF
168 {
169 String combinedNameTemplateStr = rd.getText();
170 int indexOfDefSymbol = combinedNameTemplateStr.indexOf("::=");
171 if ( indexOfDefSymbol>=1 ) {
172 String regionName = combinedNameTemplateStr.substring(0,indexOfDefSymbol);
173 String template =
174 combinedNameTemplateStr.substring(indexOfDefSymbol+3,
175 combinedNameTemplateStr.length());
176 StringTemplate regionST =
177 self.getGroup().defineRegionTemplate(self,
178 regionName,
179 template,
180 StringTemplate.REGION_EMBEDDED);
181 // treat as regular action: mangled template include
182 String indent = ((ChunkToken)rd).getIndentation();
183 ASTExpr c = self.parseAction(regionST.getName()+"()");
184 c.setIndentation(indent);
185 self.addChunk(c);
186 }
187 else {
188 self.error("embedded region definition screwed up");
189 }
190 }
191 ;
192
193 /** Break up an input text stream into chunks of either plain text
194 * or template actions in "$...$". Treat IF and ENDIF tokens
195 * specially.
196 */
197 class DefaultTemplateLexer extends Lexer;
198
199 options {
200 k=7; // see "$endif$"
201 charVocabulary = '\u0001'..'\uFFFE';
202 }
203
204 {
205 protected String currentIndent = null;
206 protected StringTemplate self;
207
208 public DefaultTemplateLexer(StringTemplate self, Reader r) {
209 this(r);
210 this.self = self;
211 }
212
213 public void reportError(RecognitionException e) {
214 self.error("$...$ chunk lexer error", e);
215 }
216
217 protected boolean upcomingELSE(int i) throws CharStreamException {
218 return LA(i)=='$'&&LA(i+1)=='e'&&LA(i+2)=='l'&&LA(i+3)=='s'&&LA(i+4)=='e'&&
219 LA(i+5)=='$';
220 }
221
222 protected boolean upcomingENDIF(int i) throws CharStreamException {
223 return LA(i)=='$'&&LA(i+1)=='e'&&LA(i+2)=='n'&&LA(i+3)=='d'&&LA(i+4)=='i'&&
224 LA(i+5)=='f'&&LA(i+6)=='$';
225 }
226
227 protected boolean upcomingAtEND(int i) throws CharStreamException {
228 return LA(i)=='$'&&LA(i+1)=='@'&&LA(i+2)=='e'&&LA(i+3)=='n'&&LA(i+4)=='d'&&LA(i+5)=='$';
229 }
230
231 protected boolean upcomingNewline(int i) throws CharStreamException {
232 return (LA(i)=='\r'&&LA(i+1)=='\n')||LA(i)=='\n';
233 }
234 }
235
236 LITERAL
237 : {LA(1)!='\r'&&LA(1)!='\n'}?
238 ( options { generateAmbigWarnings=false;}
239 {
240 int loopStartIndex=text.length();
241 int col=getColumn();
242 }
243 : '\\'! '$' // allow escaped delimiter
244 | '\\'! '\\' // always replace \\ with \
245 | '\\' ~'$' // otherwise ignore escape char
246 | ind:INDENT
247 {
248 if ( col==1 && LA(1)=='$' ) {
249 // store indent in ASTExpr not in a literal
250 currentIndent=ind.getText();
251 text.setLength(loopStartIndex); // reset length to wack text
252 }
253 else currentIndent=null;
254 }
255 | ~('$'|'\r'|'\n')
256 )+
257 {if (($getText).length()==0) {$setType(Token.SKIP);}} // pure indent?
258 ;
259
260 NEWLINE
261 : ('\r')? '\n' {newline(); currentIndent=null;}
262 ;
263
264 ACTION
265 options {
266 generateAmbigWarnings=false; // $EXPR$ is ambig with $!..!$
267 }
268 {
269 int startCol = getColumn();
270 }
271 : LINE_BREAK {$setType(Token.SKIP);}
272 | // Match escapes not in a string like <\n\ufea5>
273 {StringBuffer buf = new StringBuffer(); char uc = '\u0000';}
274 '$'! (uc=ESC_CHAR {buf.append(uc);} )+'$'!
275 {$setText(buf.toString()); $setType(LITERAL);}
276 | COMMENT {$setType(Token.SKIP);}
277 | (
278 options {
279 generateAmbigWarnings=false; // $EXPR$ is ambig with $endif$ etc...
280 }
281 : '$'! "if" (' '!)* "(" IF_EXPR ")" '$'! {$setType(TemplateParser.IF);}
282 ( ('\r'!)? '\n'! {newline();})? // ignore any newline right after an IF
283 | '$'! "elseif" (' '!)* "(" IF_EXPR ")" '$'! {$setType(TemplateParser.ELSEIF);}
284 ( ('\r'!)? '\n'! {newline();})? // ignore any newline right after an IF
285 | '$'! "else" '$'! {$setType(TemplateParser.ELSE);}
286 ( ('\r'!)? '\n'! {newline();})? // ignore any newline right after an ELSE
287 | '$'! "endif" '$'! {$setType(TemplateParser.ENDIF);}
288 ( {startCol==1}? ('\r'!)? '\n'! {newline();})? // ignore after ENDIF if on line by itself
289
290 | // match $@foo()$ => foo
291 // match $@foo$...$@end$ => foo::=...
292 '$'! '@'! (~('$'|'('))+
293 ( "()"! '$'! {$setType(TemplateParser.REGION_REF);}
294 | '$'!
295 {$setType(TemplateParser.REGION_DEF);
296 String t=$getText;
297 $setText(t+"::=");
298 }
299 ( options {greedy=true;} : ('\r'!)? '\n'! {newline();})?
300 {boolean atLeft = false;}
301 (
302 options {greedy=true;} // handle greedy=false with predicate
303 : {!(upcomingAtEND(1)||(upcomingNewline(1)&&upcomingAtEND(2)))}?
304 ( ('\r')? '\n' {newline(); atLeft = true;}
305 | . {atLeft = false;}
306 )
307 )+
308 ( ('\r'!)? '\n'! {newline(); atLeft = true;} )?
309 ( "$@end$"!
310 | . {self.error("missing region "+t+" $@end$ tag");}
311 )
312 ( {atLeft}? ('\r'!)? '\n'! {newline();})?
313 )
314
315 | '$'! EXPR '$'! // (Can't start with '!', which would mean comment)
316 )
317 {
318 ChunkToken t = new ChunkToken(_ttype, $getText, currentIndent);
319 $setToken(t);
320 }
321 ;
322
323 protected
324 EXPR: ( ESC
325 | ('\r')? '\n' {newline();}
326 | SUBTEMPLATE
327 | ('='|'+') TEMPLATE
328 | ('='|'+') SUBTEMPLATE
329 | ('='|'+') ~('"'|'<'|'{')
330 | ~'$'
331 )+
332 ;
333
334 protected
335 TEMPLATE
336 : '"' ( ESC | ~'"' )* '"'
337 | "<<"
338 (options {greedy=true;}:('\r'!)?'\n'! {newline();})? // consume 1st \n
339 ( options {greedy=false;} // stop when you see the >>
340 : {LA(3)=='>'&&LA(4)=='>'}? '\r'! '\n'! {newline();} // kill last \r\n
341 | {LA(2)=='>'&&LA(3)=='>'}? '\n'! {newline();} // kill last \n
342 | ('\r')? '\n' {newline();} // else keep
343 | .
344 )*
345 ">>"
346 ;
347
348 protected
349 IF_EXPR:( ESC
350 | ('\r')? '\n' {newline();}
351 | SUBTEMPLATE
352 | NESTED_PARENS
353 | ~')'
354 )+
355 ;
356
357 protected
358 ESC_CHAR returns [char uc='\u0000']
359 : "\\n"! {uc = '\n';}
360 | "\\r"! {uc = '\r';}
361 | "\\t"! {uc = '\t';}
362 | "\\ "! {uc = ' ';}
363 | "\\u"! a:HEX! b:HEX! c:HEX! d:HEX!
364 {uc = (char)Integer.parseInt(a.getText()+b.getText()+c.getText()+d.getText(), 16);}
365 ;
366
367 protected
368 ESC : '\\' . // ('$'|'n'|'t'|'"'|'\''|':'|'{'|'}')
369 ;
370
371 protected
372 HEX : '0'..'9'|'A'..'F'|'a'..'f'
373 ;
374
375 protected
376 SUBTEMPLATE
377 : '{' (SUBTEMPLATE|ESC|~'}')* '}'
378 ;
379
380 protected
381 NESTED_PARENS
382 : '(' (options {greedy=false;}:NESTED_PARENS|ESC|~')')+ ')'
383 ;
384
385 protected
386 INDENT
387 : ( options {greedy=true;}: ' ' | '\t')+
388 ;
389
390 protected
391 COMMENT
392 {
393 int startCol = getColumn();
394 }
395 : "$!"
396 ( options {greedy=false;}
397 : ('\r')? '\n' {newline();}
398 | .
399 )*
400 "!$" ( {startCol==1}? ('\r')? '\n' {newline();} )?
401 ;
402
403
404 protected
405 LINE_BREAK
406 : "$\\\\$" (INDENT)? ('\r')? '\n' {newline();} (INDENT)?
407 ;
0 /*
1 [Adapted from BSD licence]
2 Copyright (c) 2003-2005 Terence Parr
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package org.antlr.stringtemplate.misc;
28
29 import antlr.collections.AST;
30
31 import javax.swing.event.*;
32 import javax.swing.tree.*;
33
34 import org.antlr.stringtemplate.StringTemplate;
35 import org.antlr.stringtemplate.StringTemplateGroup;
36 import org.antlr.stringtemplate.language.*;
37
38 import java.util.*;
39 import java.lang.reflect.Constructor;
40
41 /** A model that pulls data from a string template hierarchy. This code
42 * is extremely ugly!
43 */
44 public class JTreeStringTemplateModel implements TreeModel {
45 static Map classNameToWrapperMap = new HashMap();
46
47 static {
48 classNameToWrapperMap.put("org.antlr.stringtemplate.StringTemplate",
49 StringTemplateWrapper.class);
50 classNameToWrapperMap.put("org.antlr.stringtemplate.language.ASTExpr",
51 ExprWrapper.class);
52 classNameToWrapperMap.put("java.util.Hashtable",
53 HashMapWrapper.class);
54 classNameToWrapperMap.put("java.util.ArrayList",
55 ListWrapper.class);
56 classNameToWrapperMap.put("java.util.Vector",
57 ListWrapper.class);
58 }
59 static abstract class Wrapper {
60 public abstract int getChildCount(Object parent);
61 public abstract int getIndexOfChild(Object parent, Object child);
62 public abstract Object getChild(Object parent, int index);
63 public abstract Object getWrappedObject();
64 public boolean isLeaf(Object node) {
65 return true;
66 }
67 }
68
69 static class StringTemplateWrapper extends Wrapper {
70 StringTemplate st = null;
71 public StringTemplateWrapper(Object o) {
72 this.st = (StringTemplate)o;
73 }
74 public Object getWrappedObject() {
75 return getStringTemplate();
76 }
77 public StringTemplate getStringTemplate() {
78 return st;
79 }
80 public Object getChild(Object parent, int index) {
81 StringTemplate st = ((StringTemplateWrapper)parent).getStringTemplate();
82 if ( index==0 ) {
83 // System.out.println("chunk type index "+index+" is attributes");
84 // return attributes
85 return new HashMapWrapper(st.getAttributes());
86 }
87 Expr chunk =
88 (Expr) st.getChunks().get(index-1);
89 // System.out.println("chunk type index "+index+" is "+chunk.getClass().getName());
90 if ( chunk instanceof StringRef ) {
91 return chunk;
92 }
93 return new ExprWrapper(chunk);
94 }
95 public int getChildCount(Object parent) {
96 return st.getChunks().size()+1; // extra one is attribute list
97 }
98 public int getIndexOfChild(Object parent, Object child) {
99 if ( child instanceof Wrapper ) {
100 child = ((Wrapper)child).getWrappedObject();
101 }
102 int index = st.getChunks().indexOf(child)+1;
103 // System.out.println("index of "+child+" is "+index);
104 return index;
105 }
106 public boolean isLeaf(Object node) {
107 return false;
108 }
109 public String toString() {
110 if ( st==null ) {
111 return "<invalid template>";
112 }
113 return st.getName();
114 }
115 }
116
117 static class ExprWrapper extends Wrapper {
118 Expr expr = null;
119 public ExprWrapper(Object o) {
120 this.expr = (Expr)o;
121 }
122 public Expr getExpr() {
123 return expr;
124 }
125 public Object getWrappedObject() {
126 return expr;
127 }
128 public Object getChild(Object parent, int index) {
129 Expr expr = ((ExprWrapper)parent).getExpr();
130 if ( expr instanceof ConditionalExpr ) {
131 // System.out.println("return wrapped subtemplate");
132 return new StringTemplateWrapper(
133 ((ConditionalExpr)expr).getSubtemplate()
134 );
135 }
136 if ( expr instanceof ASTExpr ) {
137 ASTExpr astExpr = (ASTExpr)expr;
138 AST root = astExpr.getAST();
139 if ( root.getType()==
140 ActionEvaluatorTokenTypes.INCLUDE )
141 {
142 switch (index) {
143 case 0 :
144 return root.getFirstChild().getNextSibling().toStringList();
145 case 1 :
146 String templateName = root.getFirstChild().getText();
147 StringTemplate enclosingST = expr.getEnclosingTemplate();
148 StringTemplateGroup group = enclosingST.getGroup();
149 StringTemplate embedded =
150 group.getEmbeddedInstanceOf(enclosingST,
151 templateName);
152 return new StringTemplateWrapper(embedded);
153 }
154 }
155 }
156 return "<invalid>";
157 }
158 public int getChildCount(Object parent) {
159 if ( expr instanceof ConditionalExpr ) {
160 return 1;
161 }
162 AST tree = ((ASTExpr)expr).getAST();
163 if ( tree.getType()==ActionEvaluatorTokenTypes.INCLUDE ) {
164 return 2; // one for args and one for template
165 }
166 return 0;
167 }
168 public int getIndexOfChild(Object parent, Object child) {
169 //System.out.println("Get index of child of "+parent.getClass().getName());
170 if ( expr instanceof ConditionalExpr ) {
171 return 0;
172 }
173 return -1;
174 }
175 public boolean isLeaf(Object node) {
176 if ( expr instanceof ConditionalExpr ) {
177 return false;
178 }
179 if ( expr instanceof ASTExpr ) {
180 AST tree = ((ASTExpr)expr).getAST();
181 if ( tree.getType()==ActionEvaluatorTokenTypes.INCLUDE ) {
182 return false;
183 }
184 }
185 return true;
186 }
187 /** Display different things depending on the ASTExpr type */
188 public String toString() {
189 if ( expr instanceof ASTExpr ) {
190 AST tree = ((ASTExpr)expr).getAST();
191 if ( tree.getType()==ActionEvaluatorTokenTypes.INCLUDE ) {
192 return "$include$";
193 }
194 return "$"+((ASTExpr)expr).getAST().toStringList()+"$";
195 }
196 if ( expr instanceof StringRef ) {
197 return expr.toString();
198 }
199 return "<invalid node type>";
200 }
201 }
202
203 static class ListWrapper extends Wrapper {
204 List v = null;
205 public ListWrapper(Object o) {
206 v = (List)o;
207 }
208 public int getChildCount(Object parent) {
209 return v.size();
210 }
211
212 public int getIndexOfChild(Object parent, Object child) {
213 if ( child instanceof Wrapper ) {
214 child = ((Wrapper)child).getWrappedObject();
215 }
216 return v.indexOf(child);
217 }
218
219 public Object getChild(Object parent, int index) {
220 return v.get(index);
221 }
222
223 public Object getWrappedObject() {
224 return v;
225 }
226
227 public boolean isLeaf(Object node) {
228 return false;
229 }
230 }
231
232 /** Wrap an entry in a map so that name appears as the root and the value
233 * appears as the child or children.
234 */
235 static class MapEntryWrapper extends Wrapper {
236 Object key, value;
237 public MapEntryWrapper(Object key, Object value) {
238 this.key = key;
239 this.value = value;
240 }
241 public Object getWrappedObject() {
242 return wrap(value);
243 }
244 public int getChildCount(Object parent) {
245 if ( value instanceof Wrapper ) {
246 return ((Wrapper)value).getChildCount(value);
247 }
248 return 1;
249 }
250
251 public int getIndexOfChild(Object parent, Object child) {
252 if ( value instanceof Wrapper ) {
253 return ((Wrapper)value).getIndexOfChild(value, child);
254 }
255 return 0;
256 }
257
258 public Object getChild(Object parent, int index) {
259 if ( value instanceof Wrapper ) {
260 return ((Wrapper)value).getChild(value, index);
261 }
262 return value;
263 }
264
265 public boolean isLeaf(Object node) {
266 return false;
267 }
268
269 public String toString() {
270 return key.toString();
271 }
272 }
273
274 static class HashMapWrapper extends Wrapper {
275 HashMap table;
276 public HashMapWrapper(Object o) {
277 this.table = (HashMap)o;
278 }
279 public Object getWrappedObject() {
280 return table;
281 }
282 public Object getChild(Object parent, int index) {
283 List attributes = getTableAsListOfKeys();
284 String key = (String)attributes.get(index);
285 Object attr = table.get(key);
286 Object wrappedAttr = wrap(attr);
287 return new MapEntryWrapper(key, wrappedAttr);
288 }
289 public int getChildCount(Object parent) {
290 List attributes = getTableAsListOfKeys();
291 return attributes.size();
292 }
293 public int getIndexOfChild(Object parent, Object child) {
294 List attributes = getTableAsListOfKeys();
295 return attributes.indexOf(child);
296 }
297 public boolean isLeaf(Object node) {
298 return false;
299 }
300 public String toString() {
301 return "attributes";
302 }
303 private List getTableAsListOfKeys() {
304 if ( table==null ) {
305 return new LinkedList();
306 }
307 Set keys = table.keySet();
308 List v = new LinkedList();
309 for (Iterator itr = keys.iterator(); itr.hasNext();) {
310 String attributeName = (String) itr.next();
311 v.add(attributeName);
312 }
313 return v;
314 }
315
316 }
317
318 Wrapper root = null;
319
320 /** Get a wrapper object by adding "Wrapper" to class name.
321 * If not present, return the object.
322 */
323 public static Object wrap(Object o) {
324 Object wrappedObject = o;
325 Class wrapperClass = null;
326 try {
327 wrapperClass = (Class)classNameToWrapperMap.get(o.getClass().getName());
328 Constructor ctor = wrapperClass.getConstructor(new Class[]{Object.class});
329 wrappedObject = ctor.newInstance(new Object[] {o});
330 }
331 catch (Exception e) {
332 // some problem...oh well, just use the object
333 ;
334 }
335 return wrappedObject;
336 }
337
338 public JTreeStringTemplateModel(StringTemplate st) {
339 if (st == null) {
340 throw new IllegalArgumentException("root is null");
341 }
342 root = new StringTemplateWrapper(st);
343 }
344
345 public void addTreeModelListener(TreeModelListener l) {
346 }
347
348 /** Get a child object. If Conditional then return subtemplate.
349 * If ASTExpr and INCLUDE then return ith chunk of sub StringTemplate
350 */
351 public Object getChild(Object parent, int index) {
352 //System.out.println("Get index "+index+" of "+parent.toString()+":"+parent.getClass().getName());
353 if (parent == null) {
354 return null;
355 }
356 return ((Wrapper)parent).getChild(parent, index);
357 }
358
359 public int getChildCount(Object parent) {
360 if (parent == null) {
361 throw new IllegalArgumentException("root is null");
362 }
363 return ((Wrapper)parent).getChildCount(parent);
364 }
365
366 public int getIndexOfChild(Object parent, Object child) {
367 if (parent == null || child == null) {
368 throw new IllegalArgumentException("root or child is null");
369 }
370 return ((Wrapper)parent).getIndexOfChild(parent,child);
371 }
372
373 public Object getRoot() {
374 return root;
375 }
376
377 public boolean isLeaf(Object node) {
378 if (node == null) {
379 throw new IllegalArgumentException("node is null");
380 }
381 if ( node instanceof Wrapper ) {
382 return ((Wrapper)node).isLeaf(node);
383 }
384 return true;
385 }
386
387 public void removeTreeModelListener(TreeModelListener l) {
388 }
389
390 public void valueForPathChanged(TreePath path, Object newValue) {
391 System.out.println("heh, who is calling this mystery method?");
392 }
393 }
0 /*
1 [Adapted from BSD licence]
2 Copyright (c) 2003-2005 Terence Parr
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 package org.antlr.stringtemplate.misc;
29
30 import java.awt.*;
31 import javax.swing.*;
32 import javax.swing.tree.*;
33 import javax.swing.event.*;
34
35 public class JTreeStringTemplatePanel extends JPanel {
36 JTree tree;
37
38 public JTreeStringTemplatePanel(TreeModel tm, TreeSelectionListener listener) {
39 // use a layout that will stretch tree to panel size
40 setLayout(new BorderLayout());
41
42 // Create tree
43 tree = new JTree(tm);
44
45 // Change line style
46 tree.putClientProperty("JTree.lineStyle", "Angled");
47
48 // Add TreeSelectionListener
49 if (listener != null)
50 tree.addTreeSelectionListener(listener);
51
52 // Put tree in a scrollable pane's viewport
53 JScrollPane sp = new JScrollPane();
54 sp.getViewport().add(tree);
55
56 add(sp, BorderLayout.CENTER);
57 }
58 }
0 /*
1 [Adapted from BSD licence]
2 Copyright (c) 2003-2005 Terence Parr
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 package org.antlr.stringtemplate.misc;
29
30 import org.antlr.stringtemplate.*;
31 import java.awt.*;
32 import java.awt.event.*;
33 import javax.swing.*;
34 import javax.swing.event.*;
35 import javax.swing.tree.*;
36
37 /** This class visually illustrates a StringTemplate instance including
38 * the chunks (text + expressions) and the attributes table. It correctly
39 * handles nested templates and so on. A prototype really, but may prove
40 * useful for debugging StringTemplate applications. Use it like this:
41 *
42 * <pre>
43 * StringTemplate st = ...;
44 * StringTemplateTreeView viz =
45 * new StringTemplateTreeView("sample",st);
46 * viz.setVisible(true);
47 * </Pre>
48 */
49 public class StringTemplateTreeView extends JFrame {
50 // The initial width and height of the frame
51 static final int WIDTH = 200;
52 static final int HEIGHT = 300;
53
54 public StringTemplateTreeView(String label, StringTemplate st) {
55 super(label);
56
57 JTreeStringTemplatePanel tp =
58 new JTreeStringTemplatePanel(new JTreeStringTemplateModel(st), null);
59 Container content = getContentPane();
60 content.add(tp, BorderLayout.CENTER);
61 addWindowListener(new WindowAdapter() {
62 public void windowClosing(WindowEvent e) {
63 Frame f = (Frame)e.getSource();
64 f.setVisible(false);
65 f.dispose();
66 // System.exit(0);
67 }
68 });
69 setSize(WIDTH, HEIGHT);
70 }
71
72 public static void main(String args[]) {
73 StringTemplateGroup group = new StringTemplateGroup("dummy");
74 StringTemplate bold = group.defineTemplate("bold", "<b>$attr$</b>");
75 StringTemplate banner = group.defineTemplate("banner", "the banner");
76 StringTemplate st = new StringTemplate(
77 group,
78 "<html>\n" + // doesn't like the first < and doesn't show :(
79 "$banner(a=b)$"+
80 "<p><b>$name$:$email$</b>"+
81 "$if(member)$<i>$fontTag$member</font></i>$endif$"
82 );
83 st.setAttribute("name", "Terence");
84 st.setAttribute("name", "Tom");
85 st.setAttribute("email", "parrt@cs.usfca.edu");
86 st.setAttribute("templateAttr", bold);
87 StringTemplateTreeView frame =
88 new StringTemplateTreeView("StringTemplate JTree Example", st);
89 frame.setVisible(true);
90 }
91 }
0 // $ANTLR 2.7.7 (20060906): eval.g -> ActionEvaluatorTokenTypes.txt$
1 ActionEvaluator // output token vocab name
2 APPLY=4
3 MULTI_APPLY=5
4 ARGS=6
5 INCLUDE=7
6 CONDITIONAL="if"=8
7 VALUE=9
8 TEMPLATE=10
9 FUNCTION=11
10 SINGLEVALUEARG=12
11 LIST=13
12 NOTHING=14
13 SEMI=15
14 LPAREN=16
15 RPAREN=17
16 LITERAL_elseif="elseif"=18
17 COMMA=19
18 ID=20
19 ASSIGN=21
20 COLON=22
21 NOT=23
22 PLUS=24
23 DOT=25
24 LITERAL_first="first"=26
25 LITERAL_rest="rest"=27
26 LITERAL_last="last"=28
27 LITERAL_length="length"=29
28 LITERAL_strip="strip"=30
29 LITERAL_trunc="trunc"=31
30 LITERAL_super="super"=32
31 ANONYMOUS_TEMPLATE=33
32 STRING=34
33 INT=35
34 LBRACK=36
35 RBRACK=37
36 DOTDOTDOT=38
37 TEMPLATE_ARGS=39
38 NESTED_ANONYMOUS_TEMPLATE=40
39 ESC_CHAR=41
40 WS=42
41 WS_CHAR=43
0 // $ANTLR 2.7.7 (20060906): action.g -> ActionParserTokenTypes.txt$
1 ActionParser // output token vocab name
2 APPLY=4
3 MULTI_APPLY=5
4 ARGS=6
5 INCLUDE=7
6 CONDITIONAL="if"=8
7 VALUE=9
8 TEMPLATE=10
9 FUNCTION=11
10 SINGLEVALUEARG=12
11 LIST=13
12 NOTHING=14
13 SEMI=15
14 LPAREN=16
15 RPAREN=17
16 LITERAL_elseif="elseif"=18
17 COMMA=19
18 ID=20
19 ASSIGN=21
20 COLON=22
21 NOT=23
22 PLUS=24
23 DOT=25
24 LITERAL_first="first"=26
25 LITERAL_rest="rest"=27
26 LITERAL_last="last"=28
27 LITERAL_length="length"=29
28 LITERAL_strip="strip"=30
29 LITERAL_trunc="trunc"=31
30 LITERAL_super="super"=32
31 ANONYMOUS_TEMPLATE=33
32 STRING=34
33 INT=35
34 LBRACK=36
35 RBRACK=37
36 DOTDOTDOT=38
37 TEMPLATE_ARGS=39
38 NESTED_ANONYMOUS_TEMPLATE=40
39 ESC_CHAR=41
40 WS=42
41 WS_CHAR=43
0 // $ANTLR 2.7.7 (20060906): angle.bracket.template.g -> AngleBracketTemplateLexerTokenTypes.txt$
1 AngleBracketTemplateLexer // output token vocab name
2 LITERAL=4
3 NEWLINE=5
4 ACTION=6
5 IF=7
6 ELSEIF=8
7 ELSE=9
8 ENDIF=10
9 REGION_REF=11
10 REGION_DEF=12
11 EXPR=13
12 TEMPLATE=14
13 IF_EXPR=15
14 ESC_CHAR=16
15 ESC=17
16 HEX=18
17 SUBTEMPLATE=19
18 NESTED_PARENS=20
19 INDENT=21
20 COMMENT=22
21 LINE_BREAK=23
0 // $ANTLR 2.7.7 (20060906): group.g -> GroupParserTokenTypes.txt$
1 GroupParser // output token vocab name
2 LITERAL_group="group"=4
3 ID=5
4 COLON=6
5 LITERAL_implements="implements"=7
6 COMMA=8
7 SEMI=9
8 AT=10
9 DOT=11
10 LPAREN=12
11 RPAREN=13
12 DEFINED_TO_BE=14
13 STRING=15
14 BIGSTRING=16
15 ASSIGN=17
16 ANONYMOUS_TEMPLATE=18
17 LBRACK=19
18 RBRACK=20
19 LITERAL_default="default"=21
20 STAR=22
21 PLUS=23
22 OPTIONAL=24
23 SL_COMMENT=25
24 ML_COMMENT=26
25 WS=27
0 // $ANTLR 2.7.7 (20060906): interface.g -> InterfaceParserTokenTypes.txt$
1 InterfaceParser // output token vocab name
2 LITERAL_interface="interface"=4
3 ID=5
4 SEMI=6
5 LITERAL_optional="optional"=7
6 LPAREN=8
7 RPAREN=9
8 COMMA=10
9 COLON=11
10 SL_COMMENT=12
11 ML_COMMENT=13
12 WS=14
0 // $ANTLR 2.7.7 (20060906): template.g -> TemplateParserTokenTypes.txt$
1 TemplateParser // output token vocab name
2 LITERAL=4
3 NEWLINE=5
4 ACTION=6
5 IF=7
6 ELSEIF=8
7 ELSE=9
8 ENDIF=10
9 REGION_REF=11
10 REGION_DEF=12
11 EXPR=13
12 TEMPLATE=14
13 IF_EXPR=15
14 ESC_CHAR=16
15 ESC=17
16 HEX=18
17 SUBTEMPLATE=19
18 NESTED_PARENS=20
19 INDENT=21
20 COMMENT=22
21 LINE_BREAK=23
0 // $ANTLR 2.7.7 (20060906): "eval.g" -> "ActionEvaluator.java"$
1
2 /*
3 [The "BSD licence"]
4 Copyright (c) 2003-2004 Terence Parr
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 package org.antlr.stringtemplate.language;
30 import org.antlr.stringtemplate.*;
31 import java.util.*;
32 import java.io.*;
33 import java.lang.reflect.*;
34
35 import antlr.TreeParser;
36 import antlr.Token;
37 import antlr.collections.AST;
38 import antlr.RecognitionException;
39 import antlr.ANTLRException;
40 import antlr.NoViableAltException;
41 import antlr.MismatchedTokenException;
42 import antlr.SemanticException;
43 import antlr.collections.impl.BitSet;
44 import antlr.ASTPair;
45 import antlr.collections.impl.ASTArray;
46
47
48 public class ActionEvaluator extends antlr.TreeParser implements ActionEvaluatorTokenTypes
49 {
50
51 public static class NameValuePair {
52 public String name;
53 public Object value;
54 };
55
56 protected StringTemplate self = null;
57 protected StringTemplateWriter out = null;
58 protected ASTExpr chunk = null;
59
60 /** Create an evaluator using attributes from self */
61 public ActionEvaluator(StringTemplate self, ASTExpr chunk, StringTemplateWriter out) {
62 this.self = self;
63 this.chunk = chunk;
64 this.out = out;
65 }
66
67 public void reportError(RecognitionException e) {
68 self.error("eval tree parse error", e);
69 }
70 public ActionEvaluator() {
71 tokenNames = _tokenNames;
72 }
73
74 public final int action(AST _t) throws RecognitionException {
75 int numCharsWritten=0;
76
77 org.antlr.stringtemplate.language.StringTemplateAST action_AST_in = (_t == ASTNULL) ? null : (org.antlr.stringtemplate.language.StringTemplateAST)_t;
78
79 Object e=null;
80
81
82 try { // for error handling
83 e=expr(_t);
84 _t = _retTree;
85 numCharsWritten = chunk.writeAttribute(self,e,out);
86 }
87 catch (RecognitionException ex) {
88 reportError(ex);
89 if (_t!=null) {_t = _t.getNextSibling();}
90 }
91 _retTree = _t;
92 return numCharsWritten;
93 }
94
95 public final Object expr(AST _t) throws RecognitionException {
96 Object value=null;
97
98 org.antlr.stringtemplate.language.StringTemplateAST expr_AST_in = (_t == ASTNULL) ? null : (org.antlr.stringtemplate.language.StringTemplateAST)_t;
99
100 Object a=null, b=null, e=null;
101 Map argumentContext=null;
102
103
104 try { // for error handling
105 if (_t==null) _t=ASTNULL;
106 switch ( _t.getType()) {
107 case PLUS:
108 {
109 AST __t3 = _t;
110 org.antlr.stringtemplate.language.StringTemplateAST tmp1_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
111 match(_t,PLUS);
112 _t = _t.getFirstChild();
113 a=expr(_t);
114 _t = _retTree;
115 b=expr(_t);
116 _t = _retTree;
117 value = chunk.add(a,b);
118 _t = __t3;
119 _t = _t.getNextSibling();
120 break;
121 }
122 case APPLY:
123 case MULTI_APPLY:
124 {
125 value=templateApplication(_t);
126 _t = _retTree;
127 break;
128 }
129 case ID:
130 case DOT:
131 case ANONYMOUS_TEMPLATE:
132 case STRING:
133 case INT:
134 {
135 value=attribute(_t);
136 _t = _retTree;
137 break;
138 }
139 case INCLUDE:
140 {
141 value=templateInclude(_t);
142 _t = _retTree;
143 break;
144 }
145 case FUNCTION:
146 {
147 value=function(_t);
148 _t = _retTree;
149 break;
150 }
151 case LIST:
152 {
153 value=list(_t);
154 _t = _retTree;
155 break;
156 }
157 case VALUE:
158 {
159 AST __t4 = _t;
160 org.antlr.stringtemplate.language.StringTemplateAST tmp2_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
161 match(_t,VALUE);
162 _t = _t.getFirstChild();
163 e=expr(_t);
164 _t = _retTree;
165 _t = __t4;
166 _t = _t.getNextSibling();
167
168 StringWriter buf = new StringWriter();
169 StringTemplateWriter sw =
170 self.getGroup().getStringTemplateWriter(buf);
171 int n = chunk.writeAttribute(self,e,sw);
172 if ( n > 0 ) {
173 value = buf.toString();
174 }
175
176 break;
177 }
178 default:
179 {
180 throw new NoViableAltException(_t);
181 }
182 }
183 }
184 catch (RecognitionException ex) {
185 reportError(ex);
186 if (_t!=null) {_t = _t.getNextSibling();}
187 }
188 _retTree = _t;
189 return value;
190 }
191
192 /** Apply template(s) to an attribute; can be applied to another apply
193 * result.
194 */
195 public final Object templateApplication(AST _t) throws RecognitionException {
196 Object value=null;
197
198 org.antlr.stringtemplate.language.StringTemplateAST templateApplication_AST_in = (_t == ASTNULL) ? null : (org.antlr.stringtemplate.language.StringTemplateAST)_t;
199 org.antlr.stringtemplate.language.StringTemplateAST anon = null;
200
201 Object a=null;
202 Vector templatesToApply=new Vector();
203 List attributes = new ArrayList();
204
205
206 try { // for error handling
207 if (_t==null) _t=ASTNULL;
208 switch ( _t.getType()) {
209 case APPLY:
210 {
211 AST __t14 = _t;
212 org.antlr.stringtemplate.language.StringTemplateAST tmp3_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
213 match(_t,APPLY);
214 _t = _t.getFirstChild();
215 a=expr(_t);
216 _t = _retTree;
217 {
218 int _cnt16=0;
219 _loop16:
220 do {
221 if (_t==null) _t=ASTNULL;
222 if ((_t.getType()==TEMPLATE)) {
223 template(_t,templatesToApply);
224 _t = _retTree;
225 }
226 else {
227 if ( _cnt16>=1 ) { break _loop16; } else {throw new NoViableAltException(_t);}
228 }
229
230 _cnt16++;
231 } while (true);
232 }
233 value = chunk.applyListOfAlternatingTemplates(self,a,templatesToApply);
234 _t = __t14;
235 _t = _t.getNextSibling();
236 break;
237 }
238 case MULTI_APPLY:
239 {
240 AST __t17 = _t;
241 org.antlr.stringtemplate.language.StringTemplateAST tmp4_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
242 match(_t,MULTI_APPLY);
243 _t = _t.getFirstChild();
244 {
245 int _cnt19=0;
246 _loop19:
247 do {
248 if (_t==null) _t=ASTNULL;
249 if ((_tokenSet_0.member(_t.getType()))) {
250 a=expr(_t);
251 _t = _retTree;
252 attributes.add(a);
253 }
254 else {
255 if ( _cnt19>=1 ) { break _loop19; } else {throw new NoViableAltException(_t);}
256 }
257
258 _cnt19++;
259 } while (true);
260 }
261 org.antlr.stringtemplate.language.StringTemplateAST tmp5_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
262 match(_t,COLON);
263 _t = _t.getNextSibling();
264 anon = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
265 match(_t,ANONYMOUS_TEMPLATE);
266 _t = _t.getNextSibling();
267
268 StringTemplate anonymous = anon.getStringTemplate();
269 templatesToApply.addElement(anonymous);
270 value = chunk.applyTemplateToListOfAttributes(self,
271 attributes,
272 anon.getStringTemplate());
273
274 _t = __t17;
275 _t = _t.getNextSibling();
276 break;
277 }
278 default:
279 {
280 throw new NoViableAltException(_t);
281 }
282 }
283 }
284 catch (RecognitionException ex) {
285 reportError(ex);
286 if (_t!=null) {_t = _t.getNextSibling();}
287 }
288 _retTree = _t;
289 return value;
290 }
291
292 public final Object attribute(AST _t) throws RecognitionException {
293 Object value=null;
294
295 org.antlr.stringtemplate.language.StringTemplateAST attribute_AST_in = (_t == ASTNULL) ? null : (org.antlr.stringtemplate.language.StringTemplateAST)_t;
296 org.antlr.stringtemplate.language.StringTemplateAST prop = null;
297 org.antlr.stringtemplate.language.StringTemplateAST i3 = null;
298 org.antlr.stringtemplate.language.StringTemplateAST i = null;
299 org.antlr.stringtemplate.language.StringTemplateAST s = null;
300 org.antlr.stringtemplate.language.StringTemplateAST at = null;
301
302 Object obj = null;
303 Object propName = null;
304 Object e = null;
305
306
307 try { // for error handling
308 if (_t==null) _t=ASTNULL;
309 switch ( _t.getType()) {
310 case DOT:
311 {
312 AST __t33 = _t;
313 org.antlr.stringtemplate.language.StringTemplateAST tmp6_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
314 match(_t,DOT);
315 _t = _t.getFirstChild();
316 obj=expr(_t);
317 _t = _retTree;
318 {
319 if (_t==null) _t=ASTNULL;
320 switch ( _t.getType()) {
321 case ID:
322 {
323 prop = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
324 match(_t,ID);
325 _t = _t.getNextSibling();
326 propName = prop.getText();
327 break;
328 }
329 case VALUE:
330 {
331 AST __t35 = _t;
332 org.antlr.stringtemplate.language.StringTemplateAST tmp7_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
333 match(_t,VALUE);
334 _t = _t.getFirstChild();
335 e=expr(_t);
336 _t = _retTree;
337 _t = __t35;
338 _t = _t.getNextSibling();
339 if (e!=null) {propName=e;}
340 break;
341 }
342 default:
343 {
344 throw new NoViableAltException(_t);
345 }
346 }
347 }
348 _t = __t33;
349 _t = _t.getNextSibling();
350 value = chunk.getObjectProperty(self,obj,propName);
351 break;
352 }
353 case ID:
354 {
355 i3 = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
356 match(_t,ID);
357 _t = _t.getNextSibling();
358
359 value=self.getAttribute(i3.getText());
360
361 break;
362 }
363 case INT:
364 {
365 i = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
366 match(_t,INT);
367 _t = _t.getNextSibling();
368 value=new Integer(i.getText());
369 break;
370 }
371 case STRING:
372 {
373 s = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
374 match(_t,STRING);
375 _t = _t.getNextSibling();
376
377 value=s.getText();
378
379 break;
380 }
381 case ANONYMOUS_TEMPLATE:
382 {
383 at = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
384 match(_t,ANONYMOUS_TEMPLATE);
385 _t = _t.getNextSibling();
386
387 value=at.getText();
388 if ( at.getText()!=null ) {
389 StringTemplate valueST =new StringTemplate(self.getGroup(), at.getText());
390 valueST.setEnclosingInstance(self);
391 valueST.setName("<anonymous template argument>");
392 value = valueST;
393 }
394
395 break;
396 }
397 default:
398 {
399 throw new NoViableAltException(_t);
400 }
401 }
402 }
403 catch (RecognitionException ex) {
404 reportError(ex);
405 if (_t!=null) {_t = _t.getNextSibling();}
406 }
407 _retTree = _t;
408 return value;
409 }
410
411 public final Object templateInclude(AST _t) throws RecognitionException {
412 Object value=null;
413
414 org.antlr.stringtemplate.language.StringTemplateAST templateInclude_AST_in = (_t == ASTNULL) ? null : (org.antlr.stringtemplate.language.StringTemplateAST)_t;
415 org.antlr.stringtemplate.language.StringTemplateAST id = null;
416 org.antlr.stringtemplate.language.StringTemplateAST a1 = null;
417 org.antlr.stringtemplate.language.StringTemplateAST a2 = null;
418
419 StringTemplateAST args = null;
420 String name = null;
421 Object n = null;
422
423
424 try { // for error handling
425 AST __t10 = _t;
426 org.antlr.stringtemplate.language.StringTemplateAST tmp8_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
427 match(_t,INCLUDE);
428 _t = _t.getFirstChild();
429 {
430 if (_t==null) _t=ASTNULL;
431 switch ( _t.getType()) {
432 case ID:
433 {
434 id = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
435 match(_t,ID);
436 _t = _t.getNextSibling();
437 a1 = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
438 if ( _t==null ) throw new MismatchedTokenException();
439 _t = _t.getNextSibling();
440 name=id.getText(); args=a1;
441 break;
442 }
443 case VALUE:
444 {
445 AST __t12 = _t;
446 org.antlr.stringtemplate.language.StringTemplateAST tmp9_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
447 match(_t,VALUE);
448 _t = _t.getFirstChild();
449 n=expr(_t);
450 _t = _retTree;
451 a2 = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
452 if ( _t==null ) throw new MismatchedTokenException();
453 _t = _t.getNextSibling();
454 _t = __t12;
455 _t = _t.getNextSibling();
456 if (n!=null) {name=n.toString();} args=a2;
457 break;
458 }
459 default:
460 {
461 throw new NoViableAltException(_t);
462 }
463 }
464 }
465 _t = __t10;
466 _t = _t.getNextSibling();
467
468 if ( name!=null ) {
469 value = chunk.getTemplateInclude(self, name, args);
470 }
471
472 }
473 catch (RecognitionException ex) {
474 reportError(ex);
475 if (_t!=null) {_t = _t.getNextSibling();}
476 }
477 _retTree = _t;
478 return value;
479 }
480
481 public final Object function(AST _t) throws RecognitionException {
482 Object value=null;
483
484 org.antlr.stringtemplate.language.StringTemplateAST function_AST_in = (_t == ASTNULL) ? null : (org.antlr.stringtemplate.language.StringTemplateAST)_t;
485
486 Object a;
487
488
489 try { // for error handling
490 AST __t21 = _t;
491 org.antlr.stringtemplate.language.StringTemplateAST tmp10_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
492 match(_t,FUNCTION);
493 _t = _t.getFirstChild();
494 {
495 if (_t==null) _t=ASTNULL;
496 switch ( _t.getType()) {
497 case LITERAL_first:
498 {
499 org.antlr.stringtemplate.language.StringTemplateAST tmp11_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
500 match(_t,LITERAL_first);
501 _t = _t.getNextSibling();
502 a=singleFunctionArg(_t);
503 _t = _retTree;
504 value=chunk.first(a);
505 break;
506 }
507 case LITERAL_rest:
508 {
509 org.antlr.stringtemplate.language.StringTemplateAST tmp12_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
510 match(_t,LITERAL_rest);
511 _t = _t.getNextSibling();
512 a=singleFunctionArg(_t);
513 _t = _retTree;
514 value=chunk.rest(a);
515 break;
516 }
517 case LITERAL_last:
518 {
519 org.antlr.stringtemplate.language.StringTemplateAST tmp13_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
520 match(_t,LITERAL_last);
521 _t = _t.getNextSibling();
522 a=singleFunctionArg(_t);
523 _t = _retTree;
524 value=chunk.last(a);
525 break;
526 }
527 case LITERAL_length:
528 {
529 org.antlr.stringtemplate.language.StringTemplateAST tmp14_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
530 match(_t,LITERAL_length);
531 _t = _t.getNextSibling();
532 a=singleFunctionArg(_t);
533 _t = _retTree;
534 value=chunk.length(a);
535 break;
536 }
537 case LITERAL_strip:
538 {
539 org.antlr.stringtemplate.language.StringTemplateAST tmp15_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
540 match(_t,LITERAL_strip);
541 _t = _t.getNextSibling();
542 a=singleFunctionArg(_t);
543 _t = _retTree;
544 value=chunk.strip(a);
545 break;
546 }
547 case LITERAL_trunc:
548 {
549 org.antlr.stringtemplate.language.StringTemplateAST tmp16_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
550 match(_t,LITERAL_trunc);
551 _t = _t.getNextSibling();
552 a=singleFunctionArg(_t);
553 _t = _retTree;
554 value=chunk.trunc(a);
555 break;
556 }
557 default:
558 {
559 throw new NoViableAltException(_t);
560 }
561 }
562 }
563 _t = __t21;
564 _t = _t.getNextSibling();
565 }
566 catch (RecognitionException ex) {
567 reportError(ex);
568 if (_t!=null) {_t = _t.getNextSibling();}
569 }
570 _retTree = _t;
571 return value;
572 }
573
574 /** create a new list of expressions as a new multi-value attribute */
575 public final Object list(AST _t) throws RecognitionException {
576 Object value=null;
577
578 org.antlr.stringtemplate.language.StringTemplateAST list_AST_in = (_t == ASTNULL) ? null : (org.antlr.stringtemplate.language.StringTemplateAST)_t;
579
580 Object e = null;
581 List elements = new ArrayList();
582
583
584 try { // for error handling
585 AST __t6 = _t;
586 org.antlr.stringtemplate.language.StringTemplateAST tmp17_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
587 match(_t,LIST);
588 _t = _t.getFirstChild();
589 {
590 int _cnt8=0;
591 _loop8:
592 do {
593 if (_t==null) _t=ASTNULL;
594 switch ( _t.getType()) {
595 case APPLY:
596 case MULTI_APPLY:
597 case INCLUDE:
598 case VALUE:
599 case FUNCTION:
600 case LIST:
601 case ID:
602 case PLUS:
603 case DOT:
604 case ANONYMOUS_TEMPLATE:
605 case STRING:
606 case INT:
607 {
608 e=expr(_t);
609 _t = _retTree;
610
611 if ( e!=null ) {
612 elements.add(e);
613 }
614
615 break;
616 }
617 case NOTHING:
618 {
619 org.antlr.stringtemplate.language.StringTemplateAST tmp18_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
620 match(_t,NOTHING);
621 _t = _t.getNextSibling();
622
623 List nullSingleton = new ArrayList() {{add(null);}};
624 elements.add(nullSingleton.iterator()); // add a blank
625
626 break;
627 }
628 default:
629 {
630 if ( _cnt8>=1 ) { break _loop8; } else {throw new NoViableAltException(_t);}
631 }
632 }
633 _cnt8++;
634 } while (true);
635 }
636 _t = __t6;
637 _t = _t.getNextSibling();
638 value = new Cat(elements);
639 }
640 catch (RecognitionException ex) {
641 reportError(ex);
642 if (_t!=null) {_t = _t.getNextSibling();}
643 }
644 _retTree = _t;
645 return value;
646 }
647
648 public final void template(AST _t,
649 Vector templatesToApply
650 ) throws RecognitionException {
651
652 org.antlr.stringtemplate.language.StringTemplateAST template_AST_in = (_t == ASTNULL) ? null : (org.antlr.stringtemplate.language.StringTemplateAST)_t;
653 org.antlr.stringtemplate.language.StringTemplateAST t = null;
654 org.antlr.stringtemplate.language.StringTemplateAST args = null;
655 org.antlr.stringtemplate.language.StringTemplateAST anon = null;
656 org.antlr.stringtemplate.language.StringTemplateAST args2 = null;
657
658 Map argumentContext = null;
659 Object n = null;
660
661
662 try { // for error handling
663 AST __t26 = _t;
664 org.antlr.stringtemplate.language.StringTemplateAST tmp19_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
665 match(_t,TEMPLATE);
666 _t = _t.getFirstChild();
667 {
668 if (_t==null) _t=ASTNULL;
669 switch ( _t.getType()) {
670 case ID:
671 {
672 t = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
673 match(_t,ID);
674 _t = _t.getNextSibling();
675 args = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
676 if ( _t==null ) throw new MismatchedTokenException();
677 _t = _t.getNextSibling();
678
679 String templateName = t.getText();
680 StringTemplateGroup group = self.getGroup();
681 StringTemplate embedded = group.getEmbeddedInstanceOf(self, templateName);
682 if ( embedded!=null ) {
683 embedded.setArgumentsAST(args);
684 templatesToApply.addElement(embedded);
685 }
686
687 break;
688 }
689 case ANONYMOUS_TEMPLATE:
690 {
691 anon = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
692 match(_t,ANONYMOUS_TEMPLATE);
693 _t = _t.getNextSibling();
694
695 StringTemplate anonymous = anon.getStringTemplate();
696 // to properly see overridden templates, always set
697 // anonymous' group to be self's group
698 anonymous.setGroup(self.getGroup());
699 templatesToApply.addElement(anonymous);
700
701 break;
702 }
703 case VALUE:
704 {
705 AST __t28 = _t;
706 org.antlr.stringtemplate.language.StringTemplateAST tmp20_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
707 match(_t,VALUE);
708 _t = _t.getFirstChild();
709 n=expr(_t);
710 _t = _retTree;
711 args2 = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
712 if ( _t==null ) throw new MismatchedTokenException();
713 _t = _t.getNextSibling();
714
715 StringTemplate embedded = null;
716 if ( n!=null ) {
717 String templateName = n.toString();
718 StringTemplateGroup group = self.getGroup();
719 embedded = group.getEmbeddedInstanceOf(self, templateName);
720 if ( embedded!=null ) {
721 embedded.setArgumentsAST(args2);
722 templatesToApply.addElement(embedded);
723 }
724 }
725
726 _t = __t28;
727 _t = _t.getNextSibling();
728 break;
729 }
730 default:
731 {
732 throw new NoViableAltException(_t);
733 }
734 }
735 }
736 _t = __t26;
737 _t = _t.getNextSibling();
738 }
739 catch (RecognitionException ex) {
740 reportError(ex);
741 if (_t!=null) {_t = _t.getNextSibling();}
742 }
743 _retTree = _t;
744 }
745
746 public final Object singleFunctionArg(AST _t) throws RecognitionException {
747 Object value=null;
748
749 org.antlr.stringtemplate.language.StringTemplateAST singleFunctionArg_AST_in = (_t == ASTNULL) ? null : (org.antlr.stringtemplate.language.StringTemplateAST)_t;
750
751 try { // for error handling
752 AST __t24 = _t;
753 org.antlr.stringtemplate.language.StringTemplateAST tmp21_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
754 match(_t,SINGLEVALUEARG);
755 _t = _t.getFirstChild();
756 value=expr(_t);
757 _t = _retTree;
758 _t = __t24;
759 _t = _t.getNextSibling();
760 }
761 catch (RecognitionException ex) {
762 reportError(ex);
763 if (_t!=null) {_t = _t.getNextSibling();}
764 }
765 _retTree = _t;
766 return value;
767 }
768
769 public final boolean ifCondition(AST _t) throws RecognitionException {
770 boolean value=false;
771
772 org.antlr.stringtemplate.language.StringTemplateAST ifCondition_AST_in = (_t == ASTNULL) ? null : (org.antlr.stringtemplate.language.StringTemplateAST)_t;
773
774 Object a=null, b=null;
775
776
777 try { // for error handling
778 if (_t==null) _t=ASTNULL;
779 switch ( _t.getType()) {
780 case APPLY:
781 case MULTI_APPLY:
782 case INCLUDE:
783 case VALUE:
784 case FUNCTION:
785 case LIST:
786 case ID:
787 case PLUS:
788 case DOT:
789 case ANONYMOUS_TEMPLATE:
790 case STRING:
791 case INT:
792 {
793 a=ifAtom(_t);
794 _t = _retTree;
795 value = chunk.testAttributeTrue(a);
796 break;
797 }
798 case NOT:
799 {
800 AST __t30 = _t;
801 org.antlr.stringtemplate.language.StringTemplateAST tmp22_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
802 match(_t,NOT);
803 _t = _t.getFirstChild();
804 a=ifAtom(_t);
805 _t = _retTree;
806 _t = __t30;
807 _t = _t.getNextSibling();
808 value = !chunk.testAttributeTrue(a);
809 break;
810 }
811 default:
812 {
813 throw new NoViableAltException(_t);
814 }
815 }
816 }
817 catch (RecognitionException ex) {
818 reportError(ex);
819 if (_t!=null) {_t = _t.getNextSibling();}
820 }
821 _retTree = _t;
822 return value;
823 }
824
825 public final Object ifAtom(AST _t) throws RecognitionException {
826 Object value=null;
827
828 org.antlr.stringtemplate.language.StringTemplateAST ifAtom_AST_in = (_t == ASTNULL) ? null : (org.antlr.stringtemplate.language.StringTemplateAST)_t;
829
830 try { // for error handling
831 value=expr(_t);
832 _t = _retTree;
833 }
834 catch (RecognitionException ex) {
835 reportError(ex);
836 if (_t!=null) {_t = _t.getNextSibling();}
837 }
838 _retTree = _t;
839 return value;
840 }
841
842 /** self is assumed to be the enclosing context as foo(x=y) must find y in
843 * the template that encloses the ref to foo(x=y). We must pass in
844 * the embedded template (the one invoked) so we can check formal args
845 * in rawSetArgumentAttribute.
846 */
847 public final Map argList(AST _t,
848 StringTemplate embedded, Map initialContext
849 ) throws RecognitionException {
850 Map argumentContext=null;
851
852 org.antlr.stringtemplate.language.StringTemplateAST argList_AST_in = (_t == ASTNULL) ? null : (org.antlr.stringtemplate.language.StringTemplateAST)_t;
853
854 argumentContext = initialContext;
855 if ( argumentContext==null ) {
856 argumentContext=new HashMap();
857 }
858
859
860 try { // for error handling
861 if (_t==null) _t=ASTNULL;
862 switch ( _t.getType()) {
863 case ARGS:
864 {
865 AST __t37 = _t;
866 org.antlr.stringtemplate.language.StringTemplateAST tmp23_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
867 match(_t,ARGS);
868 _t = _t.getFirstChild();
869 {
870 _loop39:
871 do {
872 if (_t==null) _t=ASTNULL;
873 if ((_t.getType()==ASSIGN||_t.getType()==DOTDOTDOT)) {
874 argumentAssignment(_t,embedded,argumentContext);
875 _t = _retTree;
876 }
877 else {
878 break _loop39;
879 }
880
881 } while (true);
882 }
883 _t = __t37;
884 _t = _t.getNextSibling();
885 break;
886 }
887 case SINGLEVALUEARG:
888 {
889 singleTemplateArg(_t,embedded,argumentContext);
890 _t = _retTree;
891 break;
892 }
893 default:
894 {
895 throw new NoViableAltException(_t);
896 }
897 }
898 }
899 catch (RecognitionException ex) {
900 reportError(ex);
901 if (_t!=null) {_t = _t.getNextSibling();}
902 }
903 _retTree = _t;
904 return argumentContext;
905 }
906
907 public final void argumentAssignment(AST _t,
908 StringTemplate embedded, Map argumentContext
909 ) throws RecognitionException {
910
911 org.antlr.stringtemplate.language.StringTemplateAST argumentAssignment_AST_in = (_t == ASTNULL) ? null : (org.antlr.stringtemplate.language.StringTemplateAST)_t;
912 org.antlr.stringtemplate.language.StringTemplateAST arg = null;
913
914 Object e = null;
915
916
917 try { // for error handling
918 if (_t==null) _t=ASTNULL;
919 switch ( _t.getType()) {
920 case ASSIGN:
921 {
922 AST __t43 = _t;
923 org.antlr.stringtemplate.language.StringTemplateAST tmp24_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
924 match(_t,ASSIGN);
925 _t = _t.getFirstChild();
926 arg = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
927 match(_t,ID);
928 _t = _t.getNextSibling();
929 e=expr(_t);
930 _t = _retTree;
931 _t = __t43;
932 _t = _t.getNextSibling();
933
934 if ( e!=null ) {
935 self.rawSetArgumentAttribute(embedded,argumentContext,arg.getText(),e);
936 }
937
938 break;
939 }
940 case DOTDOTDOT:
941 {
942 org.antlr.stringtemplate.language.StringTemplateAST tmp25_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
943 match(_t,DOTDOTDOT);
944 _t = _t.getNextSibling();
945 embedded.setPassThroughAttributes(true);
946 break;
947 }
948 default:
949 {
950 throw new NoViableAltException(_t);
951 }
952 }
953 }
954 catch (RecognitionException ex) {
955 reportError(ex);
956 if (_t!=null) {_t = _t.getNextSibling();}
957 }
958 _retTree = _t;
959 }
960
961 public final void singleTemplateArg(AST _t,
962 StringTemplate embedded, Map argumentContext
963 ) throws RecognitionException {
964
965 org.antlr.stringtemplate.language.StringTemplateAST singleTemplateArg_AST_in = (_t == ASTNULL) ? null : (org.antlr.stringtemplate.language.StringTemplateAST)_t;
966
967 Object e = null;
968
969
970 try { // for error handling
971 AST __t41 = _t;
972 org.antlr.stringtemplate.language.StringTemplateAST tmp26_AST_in = (org.antlr.stringtemplate.language.StringTemplateAST)_t;
973 match(_t,SINGLEVALUEARG);
974 _t = _t.getFirstChild();
975 e=expr(_t);
976 _t = _retTree;
977 _t = __t41;
978 _t = _t.getNextSibling();
979
980 if ( e!=null ) {
981 String soleArgName = null;
982 // find the sole defined formal argument for embedded
983 boolean error = false;
984 Map formalArgs = embedded.getFormalArguments();
985 if ( formalArgs!=null ) {
986 Set argNames = formalArgs.keySet();
987 if ( argNames.size()==1 ) {
988 soleArgName = (String)argNames.toArray()[0];
989 //System.out.println("sole formal arg of "+embedded.getName()+" is "+soleArgName);
990 }
991 else {
992 error=true;
993 }
994 }
995 else {
996 error=true;
997 }
998 if ( error ) {
999 self.error("template "+embedded.getName()+
1000 " must have exactly one formal arg in template context "+
1001 self.getEnclosingInstanceStackString());
1002 }
1003 else {
1004 self.rawSetArgumentAttribute(embedded,argumentContext,soleArgName,e);
1005 }
1006 }
1007
1008 }
1009 catch (RecognitionException ex) {
1010 reportError(ex);
1011 if (_t!=null) {_t = _t.getNextSibling();}
1012 }
1013 _retTree = _t;
1014 }
1015
1016
1017 public static final String[] _tokenNames = {
1018 "<0>",
1019 "EOF",
1020 "<2>",
1021 "NULL_TREE_LOOKAHEAD",
1022 "APPLY",
1023 "MULTI_APPLY",
1024 "ARGS",
1025 "INCLUDE",
1026 "\"if\"",
1027 "VALUE",
1028 "TEMPLATE",
1029 "FUNCTION",
1030 "SINGLEVALUEARG",
1031 "LIST",
1032 "NOTHING",
1033 "SEMI",
1034 "LPAREN",
1035 "RPAREN",
1036 "\"elseif\"",
1037 "COMMA",
1038 "ID",
1039 "ASSIGN",
1040 "COLON",
1041 "NOT",
1042 "PLUS",
1043 "DOT",
1044 "\"first\"",
1045 "\"rest\"",
1046 "\"last\"",
1047 "\"length\"",
1048 "\"strip\"",
1049 "\"trunc\"",
1050 "\"super\"",
1051 "ANONYMOUS_TEMPLATE",
1052 "STRING",
1053 "INT",
1054 "LBRACK",
1055 "RBRACK",
1056 "DOTDOTDOT",
1057 "TEMPLATE_ARGS",
1058 "NESTED_ANONYMOUS_TEMPLATE",
1059 "ESC_CHAR",
1060 "WS",
1061 "WS_CHAR"
1062 };
1063
1064 private static final long[] mk_tokenSet_0() {
1065 long[] data = { 60180933296L, 0L};
1066 return data;
1067 }
1068 public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0());
1069 }
1070
0 SMAP
1 ActionEvaluator.java
2 G
3 *S G
4 *F
5 + 0 eval.g
6 eval.g
7 *L
8 1:3
9 1:4
10 1:5
11 1:6
12 1:8
13 1:9
14 1:10
15 1:11
16 1:12
17 1:13
18 1:14
19 1:15
20 1:16
21 1:17
22 1:19
23 1:20
24 1:21
25 1:22
26 1:23
27 1:24
28 1:25
29 1:26
30 1:27
31 1:28
32 1:29
33 1:30
34 1:31
35 1:32
36 1:33
37 1:34
38 44:52
39 45:53
40 46:54
41 47:55
42 49:57
43 50:58
44 51:59
45 53:61
46 54:62
47 55:63
48 56:64
49 57:65
50 58:66
51 60:68
52 61:69
53 62:70
54 65:75
55 65:76
56 65:83
57 65:87
58 65:88
59 65:89
60 65:90
61 65:91
62 65:92
63 65:93
64 65:94
65 66:80
66 69:84
67 69:85
68 69:86
69 72:96
70 72:97
71 72:105
72 72:106
73 72:107
74 72:179
75 72:180
76 72:181
77 72:182
78 72:183
79 72:184
80 72:185
81 72:186
82 72:187
83 72:188
84 72:189
85 72:190
86 72:191
87 73:101
88 74:102
89 77:108
90 77:109
91 77:110
92 77:111
93 77:112
94 77:113
95 77:114
96 77:115
97 77:116
98 77:117
99 77:118
100 77:119
101 77:120
102 78:123
103 78:124
104 78:125
105 78:126
106 78:127
107 79:130
108 79:131
109 79:132
110 79:133
111 79:134
112 79:135
113 79:136
114 79:137
115 80:140
116 80:141
117 80:142
118 80:143
119 81:146
120 81:147
121 81:148
122 81:149
123 82:152
124 82:153
125 82:154
126 82:155
127 83:158
128 83:159
129 83:160
130 83:161
131 83:162
132 83:163
133 83:164
134 83:165
135 83:166
136 83:167
137 86:169
138 87:170
139 88:171
140 89:172
141 90:173
142 91:174
143 92:175
144 97:575
145 97:576
146 97:577
147 97:585
148 97:640
149 97:641
150 97:642
151 97:643
152 97:644
153 97:645
154 97:646
155 97:647
156 98:581
157 99:582
158 102:586
159 102:587
160 102:588
161 102:589
162 102:637
163 102:638
164 103:591
165 103:592
166 103:593
167 103:594
168 103:595
169 103:596
170 103:597
171 103:598
172 103:599
173 103:600
174 103:601
175 103:602
176 103:603
177 103:604
178 103:605
179 103:606
180 103:607
181 103:608
182 103:609
183 103:610
184 103:629
185 103:630
186 103:631
187 103:632
188 103:633
189 103:634
190 103:635
191 103:636
192 105:612
193 106:613
194 107:614
195 109:618
196 109:619
197 109:620
198 109:621
199 109:622
200 111:624
201 112:625
202 116:639
203 119:412
204 119:413
205 119:425
206 119:473
207 119:474
208 119:475
209 119:476
210 119:477
211 119:478
212 119:479
213 119:480
214 120:420
215 121:421
216 122:422
217 125:426
218 125:427
219 125:428
220 125:429
221 125:466
222 125:467
223 127:416
224 127:417
225 127:431
226 127:432
227 127:433
228 127:434
229 127:435
230 127:436
231 127:437
232 127:438
233 127:439
234 127:440
235 127:460
236 127:461
237 127:462
238 127:463
239 127:464
240 128:441
241 130:418
242 130:444
243 130:445
244 130:446
245 130:447
246 130:448
247 130:449
248 130:450
249 130:451
250 130:452
251 130:453
252 130:454
253 130:455
254 130:456
255 131:457
256 136:469
257 137:470
258 138:471
259 145:193
260 145:196
261 145:197
262 145:207
263 145:208
264 145:209
265 145:279
266 145:280
267 145:281
268 145:282
269 145:283
270 145:284
271 145:285
272 145:286
273 145:287
274 145:288
275 145:289
276 145:290
277 145:291
278 146:194
279 146:202
280 147:195
281 147:203
282 148:204
283 151:210
284 151:211
285 151:212
286 151:213
287 151:214
288 151:215
289 151:216
290 151:217
291 151:235
292 151:236
293 152:219
294 152:220
295 152:221
296 152:222
297 152:223
298 152:224
299 152:225
300 152:226
301 152:227
302 152:228
303 152:229
304 152:231
305 152:232
306 152:233
307 153:234
308 155:239
309 155:240
310 155:241
311 155:242
312 155:243
313 155:244
314 155:246
315 155:247
316 155:248
317 155:249
318 155:250
319 155:251
320 155:252
321 155:253
322 155:254
323 155:255
324 155:256
325 155:257
326 155:259
327 155:260
328 155:261
329 155:262
330 155:263
331 155:264
332 155:275
333 155:276
334 156:200
335 156:265
336 156:266
337 156:267
338 158:269
339 159:270
340 160:271
341 161:272
342 162:273
343 167:482
344 167:483
345 167:490
346 167:566
347 167:567
348 167:568
349 167:569
350 167:570
351 167:571
352 167:572
353 167:573
354 168:487
355 171:491
356 171:492
357 171:493
358 171:494
359 171:564
360 171:565
361 172:496
362 172:497
363 172:498
364 172:499
365 172:500
366 172:501
367 172:502
368 172:503
369 172:504
370 172:505
371 172:558
372 172:559
373 172:560
374 172:561
375 172:562
376 173:508
377 173:509
378 173:510
379 173:511
380 173:512
381 173:513
382 173:514
383 173:515
384 174:518
385 174:519
386 174:520
387 174:521
388 174:522
389 174:523
390 174:524
391 174:525
392 175:528
393 175:529
394 175:530
395 175:531
396 175:532
397 175:533
398 175:534
399 175:535
400 176:538
401 176:539
402 176:540
403 176:541
404 176:542
405 176:543
406 176:544
407 176:545
408 177:548
409 177:549
410 177:550
411 177:551
412 177:552
413 177:553
414 177:554
415 177:555
416 183:747
417 183:748
418 183:752
419 183:761
420 183:762
421 183:763
422 183:764
423 183:765
424 183:766
425 183:767
426 183:768
427 184:753
428 184:754
429 184:755
430 184:756
431 184:757
432 184:758
433 184:759
434 184:760
435 187:649
436 187:650
437 187:651
438 187:663
439 187:739
440 187:740
441 187:741
442 187:742
443 187:743
444 187:744
445 187:745
446 188:659
447 189:660
448 192:664
449 192:665
450 192:666
451 192:667
452 192:737
453 192:738
454 193:654
455 193:655
456 193:669
457 193:670
458 193:671
459 193:672
460 193:673
461 193:674
462 193:675
463 193:676
464 193:677
465 193:678
466 193:731
467 193:732
468 193:733
469 193:734
470 193:735
471 195:680
472 196:681
473 197:682
474 198:683
475 199:684
476 200:685
477 201:686
478 204:656
479 204:690
480 204:691
481 204:692
482 204:693
483 204:694
484 206:696
485 207:697
486 208:698
487 209:699
488 210:700
489 213:657
490 213:704
491 213:705
492 213:706
493 213:707
494 213:708
495 213:709
496 213:710
497 213:711
498 213:712
499 213:713
500 213:714
501 213:727
502 213:728
503 215:716
504 216:717
505 217:718
506 218:719
507 219:720
508 220:721
509 221:722
510 222:723
511 223:724
512 224:725
513 231:770
514 231:771
515 231:778
516 231:779
517 231:780
518 231:812
519 231:813
520 231:814
521 231:815
522 231:816
523 231:817
524 231:818
525 231:819
526 231:820
527 231:821
528 231:822
529 231:823
530 231:824
531 232:775
532 235:781
533 235:782
534 235:783
535 235:784
536 235:785
537 235:786
538 235:787
539 235:788
540 235:789
541 235:790
542 235:791
543 235:792
544 235:793
545 235:794
546 235:795
547 235:796
548 236:799
549 236:800
550 236:801
551 236:802
552 236:803
553 236:804
554 236:805
555 236:806
556 236:807
557 236:808
558 236:809
559 239:826
560 239:827
561 239:831
562 239:834
563 239:835
564 239:836
565 239:837
566 239:838
567 239:839
568 239:840
569 239:841
570 240:832
571 240:833
572 243:293
573 243:294
574 243:308
575 243:309
576 243:310
577 243:398
578 243:399
579 243:400
580 243:401
581 243:402
582 243:403
583 243:404
584 243:405
585 243:406
586 243:407
587 243:408
588 243:409
589 243:410
590 244:303
591 245:304
592 246:305
593 249:311
594 249:312
595 249:313
596 249:314
597 249:315
598 249:316
599 249:317
600 249:318
601 249:349
602 249:350
603 250:297
604 250:320
605 250:321
606 250:322
607 250:323
608 250:324
609 250:325
610 250:326
611 250:327
612 250:343
613 250:344
614 250:345
615 250:346
616 250:347
617 255:330
618 255:331
619 255:332
620 255:333
621 255:334
622 255:335
623 255:336
624 255:337
625 255:338
626 255:339
627 255:340
628 258:351
629 260:298
630 260:354
631 260:355
632 260:356
633 260:357
634 260:358
635 262:360
636 265:299
637 265:364
638 265:365
639 265:366
640 265:367
641 265:368
642 265:369
643 267:300
644 267:372
645 267:373
646 267:374
647 267:375
648 267:376
649 269:378
650 272:301
651 272:382
652 272:383
653 272:384
654 272:385
655 272:386
656 274:388
657 275:389
658 276:390
659 277:391
660 278:392
661 279:393
662 280:394
663 289:843
664 289:848
665 289:849
666 289:850
667 289:851
668 289:861
669 289:862
670 289:863
671 289:894
672 289:895
673 289:896
674 289:897
675 289:898
676 289:899
677 289:900
678 289:901
679 289:902
680 289:903
681 289:904
682 289:905
683 289:906
684 290:844
685 290:855
686 291:845
687 291:856
688 292:846
689 292:857
690 293:847
691 293:858
692 297:864
693 297:865
694 297:866
695 297:867
696 297:868
697 297:869
698 297:870
699 297:871
700 297:872
701 297:873
702 297:874
703 297:875
704 297:876
705 297:877
706 297:878
707 297:879
708 297:880
709 297:882
710 297:883
711 297:884
712 297:885
713 298:888
714 298:889
715 298:890
716 298:891
717 301:962
718 301:963
719 301:964
720 301:971
721 301:1009
722 301:1010
723 301:1011
724 301:1012
725 301:1013
726 301:1014
727 301:1015
728 302:968
729 305:972
730 305:973
731 305:974
732 305:975
733 305:976
734 305:977
735 305:978
736 305:979
737 307:981
738 308:982
739 309:983
740 310:984
741 311:985
742 312:986
743 313:987
744 314:988
745 315:989
746 316:990
747 317:991
748 318:992
749 319:993
750 320:994
751 321:995
752 322:996
753 323:997
754 324:998
755 325:999
756 326:1000
757 327:1001
758 328:1002
759 329:1003
760 330:1004
761 331:1005
762 332:1006
763 333:1007
764 337:908
765 337:909
766 337:910
767 337:918
768 337:919
769 337:920
770 337:949
771 337:950
772 337:951
773 337:952
774 337:953
775 337:954
776 337:955
777 337:956
778 337:957
779 337:958
780 337:959
781 337:960
782 338:915
783 341:913
784 341:921
785 341:922
786 341:923
787 341:924
788 341:925
789 341:926
790 341:927
791 341:928
792 341:929
793 341:930
794 341:931
795 341:932
796 341:933
797 343:935
798 344:936
799 345:937
800 347:941
801 347:942
802 347:943
803 347:944
804 347:945
805 347:946
806 *E
0 // $ANTLR 2.7.7 (20060906): "eval.g" -> "ActionEvaluator.java"$
1
2 /*
3 [The "BSD licence"]
4 Copyright (c) 2003-2004 Terence Parr
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 package org.antlr.stringtemplate.language;
30 import org.antlr.stringtemplate.*;
31 import java.util.*;
32 import java.io.*;
33 import java.lang.reflect.*;
34
35 public interface ActionEvaluatorTokenTypes {
36 int EOF = 1;
37 int NULL_TREE_LOOKAHEAD = 3;
38 int APPLY = 4;
39 int MULTI_APPLY = 5;
40 int ARGS = 6;
41 int INCLUDE = 7;
42 int CONDITIONAL = 8;
43 int VALUE = 9;
44 int TEMPLATE = 10;
45 int FUNCTION = 11;
46 int SINGLEVALUEARG = 12;
47 int LIST = 13;
48 int NOTHING = 14;
49 int SEMI = 15;
50 int LPAREN = 16;
51 int RPAREN = 17;
52 int LITERAL_elseif = 18;
53 int COMMA = 19;
54 int ID = 20;
55 int ASSIGN = 21;
56 int COLON = 22;
57 int NOT = 23;
58 int PLUS = 24;
59 int DOT = 25;
60 int LITERAL_first = 26;
61 int LITERAL_rest = 27;
62 int LITERAL_last = 28;
63 int LITERAL_length = 29;
64 int LITERAL_strip = 30;
65 int LITERAL_trunc = 31;
66 int LITERAL_super = 32;
67 int ANONYMOUS_TEMPLATE = 33;
68 int STRING = 34;
69 int INT = 35;
70 int LBRACK = 36;
71 int RBRACK = 37;
72 int DOTDOTDOT = 38;
73 int TEMPLATE_ARGS = 39;
74 int NESTED_ANONYMOUS_TEMPLATE = 40;
75 int ESC_CHAR = 41;
76 int WS = 42;
77 int WS_CHAR = 43;
78 }
0 // $ANTLR 2.7.7 (20060906): eval.g -> ActionEvaluatorTokenTypes.txt$
1 ActionEvaluator // output token vocab name
2 APPLY=4
3 MULTI_APPLY=5
4 ARGS=6
5 INCLUDE=7
6 CONDITIONAL="if"=8
7 VALUE=9
8 TEMPLATE=10
9 FUNCTION=11
10 SINGLEVALUEARG=12
11 LIST=13
12 NOTHING=14
13 SEMI=15
14 LPAREN=16
15 RPAREN=17
16 LITERAL_elseif="elseif"=18
17 COMMA=19
18 ID=20
19 ASSIGN=21
20 COLON=22
21 NOT=23
22 PLUS=24
23 DOT=25
24 LITERAL_first="first"=26
25 LITERAL_rest="rest"=27
26 LITERAL_last="last"=28
27 LITERAL_length="length"=29
28 LITERAL_strip="strip"=30
29 LITERAL_trunc="trunc"=31
30 LITERAL_super="super"=32
31 ANONYMOUS_TEMPLATE=33
32 STRING=34
33 INT=35
34 LBRACK=36
35 RBRACK=37
36 DOTDOTDOT=38
37 TEMPLATE_ARGS=39
38 NESTED_ANONYMOUS_TEMPLATE=40
39 ESC_CHAR=41
40 WS=42
41 WS_CHAR=43
0 // $ANTLR 2.7.7 (20060906): "action.g" -> "ActionLexer.java"$
1
2 /*
3 [The "BSD licence"]
4 Copyright (c) 2003-2004 Terence Parr
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 package org.antlr.stringtemplate.language;
30 import org.antlr.stringtemplate.*;
31 import java.util.*;
32
33 import java.io.InputStream;
34 import antlr.TokenStreamException;
35 import antlr.TokenStreamIOException;
36 import antlr.TokenStreamRecognitionException;
37 import antlr.CharStreamException;
38 import antlr.CharStreamIOException;
39 import antlr.ANTLRException;
40 import java.io.Reader;
41 import java.util.Hashtable;
42 import antlr.CharScanner;
43 import antlr.InputBuffer;
44 import antlr.ByteBuffer;
45 import antlr.CharBuffer;
46 import antlr.Token;
47 import antlr.CommonToken;
48 import antlr.RecognitionException;
49 import antlr.NoViableAltForCharException;
50 import antlr.MismatchedCharException;
51 import antlr.TokenStream;
52 import antlr.ANTLRHashString;
53 import antlr.LexerSharedInputState;
54 import antlr.collections.impl.BitSet;
55 import antlr.SemanticException;
56
57 public class ActionLexer extends antlr.CharScanner implements ActionParserTokenTypes, TokenStream
58 {
59 public ActionLexer(InputStream in) {
60 this(new ByteBuffer(in));
61 }
62 public ActionLexer(Reader in) {
63 this(new CharBuffer(in));
64 }
65 public ActionLexer(InputBuffer ib) {
66 this(new LexerSharedInputState(ib));
67 }
68 public ActionLexer(LexerSharedInputState state) {
69 super(state);
70 caseSensitiveLiterals = true;
71 setCaseSensitive(true);
72 literals = new Hashtable();
73 literals.put(new ANTLRHashString("super", this), new Integer(32));
74 literals.put(new ANTLRHashString("if", this), new Integer(8));
75 literals.put(new ANTLRHashString("first", this), new Integer(26));
76 literals.put(new ANTLRHashString("last", this), new Integer(28));
77 literals.put(new ANTLRHashString("rest", this), new Integer(27));
78 literals.put(new ANTLRHashString("trunc", this), new Integer(31));
79 literals.put(new ANTLRHashString("strip", this), new Integer(30));
80 literals.put(new ANTLRHashString("length", this), new Integer(29));
81 literals.put(new ANTLRHashString("elseif", this), new Integer(18));
82 }
83
84 public Token nextToken() throws TokenStreamException {
85 Token theRetToken=null;
86 tryAgain:
87 for (;;) {
88 Token _token = null;
89 int _ttype = Token.INVALID_TYPE;
90 resetText();
91 try { // for char stream error handling
92 try { // for lexical error handling
93 switch ( LA(1)) {
94 case 'A': case 'B': case 'C': case 'D':
95 case 'E': case 'F': case 'G': case 'H':
96 case 'I': case 'J': case 'K': case 'L':
97 case 'M': case 'N': case 'O': case 'P':
98 case 'Q': case 'R': case 'S': case 'T':
99 case 'U': case 'V': case 'W': case 'X':
100 case 'Y': case 'Z': case '_': case 'a':
101 case 'b': case 'c': case 'd': case 'e':
102 case 'f': case 'g': case 'h': case 'i':
103 case 'j': case 'k': case 'l': case 'm':
104 case 'n': case 'o': case 'p': case 'q':
105 case 'r': case 's': case 't': case 'u':
106 case 'v': case 'w': case 'x': case 'y':
107 case 'z':
108 {
109 mID(true);
110 theRetToken=_returnToken;
111 break;
112 }
113 case '0': case '1': case '2': case '3':
114 case '4': case '5': case '6': case '7':
115 case '8': case '9':
116 {
117 mINT(true);
118 theRetToken=_returnToken;
119 break;
120 }
121 case '"':
122 {
123 mSTRING(true);
124 theRetToken=_returnToken;
125 break;
126 }
127 case '{':
128 {
129 mANONYMOUS_TEMPLATE(true);
130 theRetToken=_returnToken;
131 break;
132 }
133 case '[':
134 {
135 mLBRACK(true);
136 theRetToken=_returnToken;
137 break;
138 }
139 case ']':
140 {
141 mRBRACK(true);
142 theRetToken=_returnToken;
143 break;
144 }
145 case '(':
146 {
147 mLPAREN(true);
148 theRetToken=_returnToken;
149 break;
150 }
151 case ')':
152 {
153 mRPAREN(true);
154 theRetToken=_returnToken;
155 break;
156 }
157 case ',':
158 {
159 mCOMMA(true);
160 theRetToken=_returnToken;
161 break;
162 }
163 case '=':
164 {
165 mASSIGN(true);
166 theRetToken=_returnToken;
167 break;
168 }
169 case ':':
170 {
171 mCOLON(true);
172 theRetToken=_returnToken;
173 break;
174 }
175 case '+':
176 {
177 mPLUS(true);
178 theRetToken=_returnToken;
179 break;
180 }
181 case ';':
182 {
183 mSEMI(true);
184 theRetToken=_returnToken;
185 break;
186 }
187 case '!':
188 {
189 mNOT(true);
190 theRetToken=_returnToken;
191 break;
192 }
193 case '\t': case '\n': case '\r': case ' ':
194 {
195 mWS(true);
196 theRetToken=_returnToken;
197 break;
198 }
199 default:
200 if ((LA(1)=='.') && (LA(2)=='.')) {
201 mDOTDOTDOT(true);
202 theRetToken=_returnToken;
203 }
204 else if ((LA(1)=='.') && (true)) {
205 mDOT(true);
206 theRetToken=_returnToken;
207 }
208 else {
209 if (LA(1)==EOF_CHAR) {uponEOF(); _returnToken = makeToken(Token.EOF_TYPE);}
210 else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
211 }
212 }
213 if ( _returnToken==null ) continue tryAgain; // found SKIP token
214 _ttype = _returnToken.getType();
215 _returnToken.setType(_ttype);
216 return _returnToken;
217 }
218 catch (RecognitionException e) {
219 throw new TokenStreamRecognitionException(e);
220 }
221 }
222 catch (CharStreamException cse) {
223 if ( cse instanceof CharStreamIOException ) {
224 throw new TokenStreamIOException(((CharStreamIOException)cse).io);
225 }
226 else {
227 throw new TokenStreamException(cse.getMessage());
228 }
229 }
230 }
231 }
232
233 public final void mID(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
234 int _ttype; Token _token=null; int _begin=text.length();
235 _ttype = ID;
236 int _saveIndex;
237
238 {
239 switch ( LA(1)) {
240 case 'a': case 'b': case 'c': case 'd':
241 case 'e': case 'f': case 'g': case 'h':
242 case 'i': case 'j': case 'k': case 'l':
243 case 'm': case 'n': case 'o': case 'p':
244 case 'q': case 'r': case 's': case 't':
245 case 'u': case 'v': case 'w': case 'x':
246 case 'y': case 'z':
247 {
248 matchRange('a','z');
249 break;
250 }
251 case 'A': case 'B': case 'C': case 'D':
252 case 'E': case 'F': case 'G': case 'H':
253 case 'I': case 'J': case 'K': case 'L':
254 case 'M': case 'N': case 'O': case 'P':
255 case 'Q': case 'R': case 'S': case 'T':
256 case 'U': case 'V': case 'W': case 'X':
257 case 'Y': case 'Z':
258 {
259 matchRange('A','Z');
260 break;
261 }
262 case '_':
263 {
264 match('_');
265 break;
266 }
267 default:
268 {
269 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
270 }
271 }
272 }
273 {
274 _loop60:
275 do {
276 switch ( LA(1)) {
277 case 'a': case 'b': case 'c': case 'd':
278 case 'e': case 'f': case 'g': case 'h':
279 case 'i': case 'j': case 'k': case 'l':
280 case 'm': case 'n': case 'o': case 'p':
281 case 'q': case 'r': case 's': case 't':
282 case 'u': case 'v': case 'w': case 'x':
283 case 'y': case 'z':
284 {
285 matchRange('a','z');
286 break;
287 }
288 case 'A': case 'B': case 'C': case 'D':
289 case 'E': case 'F': case 'G': case 'H':
290 case 'I': case 'J': case 'K': case 'L':
291 case 'M': case 'N': case 'O': case 'P':
292 case 'Q': case 'R': case 'S': case 'T':
293 case 'U': case 'V': case 'W': case 'X':
294 case 'Y': case 'Z':
295 {
296 matchRange('A','Z');
297 break;
298 }
299 case '0': case '1': case '2': case '3':
300 case '4': case '5': case '6': case '7':
301 case '8': case '9':
302 {
303 matchRange('0','9');
304 break;
305 }
306 case '_':
307 {
308 match('_');
309 break;
310 }
311 case '/':
312 {
313 match('/');
314 break;
315 }
316 default:
317 {
318 break _loop60;
319 }
320 }
321 } while (true);
322 }
323 _ttype = testLiteralsTable(_ttype);
324 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
325 _token = makeToken(_ttype);
326 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
327 }
328 _returnToken = _token;
329 }
330
331 public final void mINT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
332 int _ttype; Token _token=null; int _begin=text.length();
333 _ttype = INT;
334 int _saveIndex;
335
336 {
337 int _cnt63=0;
338 _loop63:
339 do {
340 if (((LA(1) >= '0' && LA(1) <= '9'))) {
341 matchRange('0','9');
342 }
343 else {
344 if ( _cnt63>=1 ) { break _loop63; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
345 }
346
347 _cnt63++;
348 } while (true);
349 }
350 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
351 _token = makeToken(_ttype);
352 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
353 }
354 _returnToken = _token;
355 }
356
357 public final void mSTRING(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
358 int _ttype; Token _token=null; int _begin=text.length();
359 _ttype = STRING;
360 int _saveIndex;
361
362 _saveIndex=text.length();
363 match('"');
364 text.setLength(_saveIndex);
365 {
366 _loop66:
367 do {
368 if ((LA(1)=='\\')) {
369 mESC_CHAR(false,true);
370 }
371 else if ((_tokenSet_0.member(LA(1)))) {
372 matchNot('"');
373 }
374 else {
375 break _loop66;
376 }
377
378 } while (true);
379 }
380 _saveIndex=text.length();
381 match('"');
382 text.setLength(_saveIndex);
383 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
384 _token = makeToken(_ttype);
385 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
386 }
387 _returnToken = _token;
388 }
389
390 /** Match escape sequences, optionally translating them for strings, but not
391 * for templates. Do \} only when in {...} templates.
392 */
393 protected final void mESC_CHAR(boolean _createToken,
394 boolean doEscape
395 ) throws RecognitionException, CharStreamException, TokenStreamException {
396 int _ttype; Token _token=null; int _begin=text.length();
397 _ttype = ESC_CHAR;
398 int _saveIndex;
399 char c = '\0';
400
401 match('\\');
402 {
403 if ((LA(1)=='n') && ((LA(2) >= '\u0003' && LA(2) <= '\ufffe'))) {
404 match('n');
405 if ( inputState.guessing==0 ) {
406 if (doEscape) { text.setLength(_begin); text.append("\n"); }
407 }
408 }
409 else if ((LA(1)=='r') && ((LA(2) >= '\u0003' && LA(2) <= '\ufffe'))) {
410 match('r');
411 if ( inputState.guessing==0 ) {
412 if (doEscape) { text.setLength(_begin); text.append("\r"); }
413 }
414 }
415 else if ((LA(1)=='t') && ((LA(2) >= '\u0003' && LA(2) <= '\ufffe'))) {
416 match('t');
417 if ( inputState.guessing==0 ) {
418 if (doEscape) { text.setLength(_begin); text.append("\t"); }
419 }
420 }
421 else if ((LA(1)=='b') && ((LA(2) >= '\u0003' && LA(2) <= '\ufffe'))) {
422 match('b');
423 if ( inputState.guessing==0 ) {
424 if (doEscape) { text.setLength(_begin); text.append("\b"); }
425 }
426 }
427 else if ((LA(1)=='f') && ((LA(2) >= '\u0003' && LA(2) <= '\ufffe'))) {
428 match('f');
429 if ( inputState.guessing==0 ) {
430 if (doEscape) { text.setLength(_begin); text.append("\f"); }
431 }
432 }
433 else if (((LA(1) >= '\u0003' && LA(1) <= '\ufffe')) && ((LA(2) >= '\u0003' && LA(2) <= '\ufffe'))) {
434 c = LA(1);
435 matchNot(EOF_CHAR);
436 if ( inputState.guessing==0 ) {
437 if (doEscape) {text.setLength(_begin); text.append(String.valueOf(c));}
438 }
439 }
440 else {
441 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
442 }
443
444 }
445 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
446 _token = makeToken(_ttype);
447 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
448 }
449 _returnToken = _token;
450 }
451
452 public final void mANONYMOUS_TEMPLATE(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
453 int _ttype; Token _token=null; int _begin=text.length();
454 _ttype = ANONYMOUS_TEMPLATE;
455 int _saveIndex;
456
457 List args=null;
458 StringTemplateToken t = null;
459
460
461 _saveIndex=text.length();
462 match('{');
463 text.setLength(_saveIndex);
464 {
465 boolean synPredMatched70 = false;
466 if (((_tokenSet_1.member(LA(1))) && (_tokenSet_2.member(LA(2))))) {
467 int _m70 = mark();
468 synPredMatched70 = true;
469 inputState.guessing++;
470 try {
471 {
472 mTEMPLATE_ARGS(false);
473 }
474 }
475 catch (RecognitionException pe) {
476 synPredMatched70 = false;
477 }
478 rewind(_m70);
479 inputState.guessing--;
480 }
481 if ( synPredMatched70 ) {
482 args=mTEMPLATE_ARGS(false);
483 {
484 if ((_tokenSet_3.member(LA(1))) && ((LA(2) >= '\u0003' && LA(2) <= '\ufffe'))) {
485 _saveIndex=text.length();
486 mWS_CHAR(false);
487 text.setLength(_saveIndex);
488 }
489 else if (((LA(1) >= '\u0003' && LA(1) <= '\ufffe')) && (true)) {
490 }
491 else {
492 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
493 }
494
495 }
496 if ( inputState.guessing==0 ) {
497
498 // create a special token to track args
499 t = new StringTemplateToken(ANONYMOUS_TEMPLATE,new String(text.getBuffer(),_begin,text.length()-_begin),args);
500 _token = t;
501
502 }
503 }
504 else if (((LA(1) >= '\u0003' && LA(1) <= '\ufffe')) && (true)) {
505 }
506 else {
507 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
508 }
509
510 }
511 {
512 _loop73:
513 do {
514 if ((LA(1)=='\\') && (LA(2)=='{')) {
515 _saveIndex=text.length();
516 match('\\');
517 text.setLength(_saveIndex);
518 match('{');
519 }
520 else if ((LA(1)=='\\') && (LA(2)=='}')) {
521 _saveIndex=text.length();
522 match('\\');
523 text.setLength(_saveIndex);
524 match('}');
525 }
526 else if ((LA(1)=='\\') && ((LA(2) >= '\u0003' && LA(2) <= '\ufffe'))) {
527 mESC_CHAR(false,false);
528 }
529 else if ((LA(1)=='{')) {
530 mNESTED_ANONYMOUS_TEMPLATE(false);
531 }
532 else if ((_tokenSet_4.member(LA(1)))) {
533 matchNot('}');
534 }
535 else {
536 break _loop73;
537 }
538
539 } while (true);
540 }
541 if ( inputState.guessing==0 ) {
542
543 if ( t!=null ) {
544 t.setText(new String(text.getBuffer(),_begin,text.length()-_begin));
545 }
546
547 }
548 _saveIndex=text.length();
549 match('}');
550 text.setLength(_saveIndex);
551 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
552 _token = makeToken(_ttype);
553 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
554 }
555 _returnToken = _token;
556 }
557
558 protected final List mTEMPLATE_ARGS(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
559 List args=new ArrayList();
560 int _ttype; Token _token=null; int _begin=text.length();
561 _ttype = TEMPLATE_ARGS;
562 int _saveIndex;
563 Token a=null;
564 Token a2=null;
565
566 {
567 switch ( LA(1)) {
568 case '\t': case '\n': case '\r': case ' ':
569 {
570 _saveIndex=text.length();
571 mWS_CHAR(false);
572 text.setLength(_saveIndex);
573 break;
574 }
575 case 'A': case 'B': case 'C': case 'D':
576 case 'E': case 'F': case 'G': case 'H':
577 case 'I': case 'J': case 'K': case 'L':
578 case 'M': case 'N': case 'O': case 'P':
579 case 'Q': case 'R': case 'S': case 'T':
580 case 'U': case 'V': case 'W': case 'X':
581 case 'Y': case 'Z': case '_': case 'a':
582 case 'b': case 'c': case 'd': case 'e':
583 case 'f': case 'g': case 'h': case 'i':
584 case 'j': case 'k': case 'l': case 'm':
585 case 'n': case 'o': case 'p': case 'q':
586 case 'r': case 's': case 't': case 'u':
587 case 'v': case 'w': case 'x': case 'y':
588 case 'z':
589 {
590 break;
591 }
592 default:
593 {
594 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
595 }
596 }
597 }
598 _saveIndex=text.length();
599 mID(true);
600 text.setLength(_saveIndex);
601 a=_returnToken;
602 if ( inputState.guessing==0 ) {
603 args.add(a.getText());
604 }
605 {
606 _loop79:
607 do {
608 if ((_tokenSet_5.member(LA(1))) && (_tokenSet_6.member(LA(2)))) {
609 {
610 switch ( LA(1)) {
611 case '\t': case '\n': case '\r': case ' ':
612 {
613 _saveIndex=text.length();
614 mWS_CHAR(false);
615 text.setLength(_saveIndex);
616 break;
617 }
618 case ',':
619 {
620 break;
621 }
622 default:
623 {
624 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
625 }
626 }
627 }
628 _saveIndex=text.length();
629 match(',');
630 text.setLength(_saveIndex);
631 {
632 switch ( LA(1)) {
633 case '\t': case '\n': case '\r': case ' ':
634 {
635 _saveIndex=text.length();
636 mWS_CHAR(false);
637 text.setLength(_saveIndex);
638 break;
639 }
640 case 'A': case 'B': case 'C': case 'D':
641 case 'E': case 'F': case 'G': case 'H':
642 case 'I': case 'J': case 'K': case 'L':
643 case 'M': case 'N': case 'O': case 'P':
644 case 'Q': case 'R': case 'S': case 'T':
645 case 'U': case 'V': case 'W': case 'X':
646 case 'Y': case 'Z': case '_': case 'a':
647 case 'b': case 'c': case 'd': case 'e':
648 case 'f': case 'g': case 'h': case 'i':
649 case 'j': case 'k': case 'l': case 'm':
650 case 'n': case 'o': case 'p': case 'q':
651 case 'r': case 's': case 't': case 'u':
652 case 'v': case 'w': case 'x': case 'y':
653 case 'z':
654 {
655 break;
656 }
657 default:
658 {
659 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
660 }
661 }
662 }
663 _saveIndex=text.length();
664 mID(true);
665 text.setLength(_saveIndex);
666 a2=_returnToken;
667 if ( inputState.guessing==0 ) {
668 args.add(a2.getText());
669 }
670 }
671 else {
672 break _loop79;
673 }
674
675 } while (true);
676 }
677 {
678 switch ( LA(1)) {
679 case '\t': case '\n': case '\r': case ' ':
680 {
681 _saveIndex=text.length();
682 mWS_CHAR(false);
683 text.setLength(_saveIndex);
684 break;
685 }
686 case '|':
687 {
688 break;
689 }
690 default:
691 {
692 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
693 }
694 }
695 }
696 _saveIndex=text.length();
697 match('|');
698 text.setLength(_saveIndex);
699 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
700 _token = makeToken(_ttype);
701 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
702 }
703 _returnToken = _token;
704 return args;
705 }
706
707 protected final void mWS_CHAR(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
708 int _ttype; Token _token=null; int _begin=text.length();
709 _ttype = WS_CHAR;
710 int _saveIndex;
711
712 switch ( LA(1)) {
713 case ' ':
714 {
715 match(' ');
716 break;
717 }
718 case '\t':
719 {
720 match('\t');
721 break;
722 }
723 case '\r':
724 {
725 match('\r');
726 break;
727 }
728 case '\n':
729 {
730 match('\n');
731 if ( inputState.guessing==0 ) {
732 newline();
733 }
734 break;
735 }
736 default:
737 {
738 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
739 }
740 }
741 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
742 _token = makeToken(_ttype);
743 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
744 }
745 _returnToken = _token;
746 }
747
748 protected final void mNESTED_ANONYMOUS_TEMPLATE(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
749 int _ttype; Token _token=null; int _begin=text.length();
750 _ttype = NESTED_ANONYMOUS_TEMPLATE;
751 int _saveIndex;
752
753 match('{');
754 {
755 _loop83:
756 do {
757 if ((LA(1)=='\\') && (LA(2)=='{')) {
758 _saveIndex=text.length();
759 match('\\');
760 text.setLength(_saveIndex);
761 match('{');
762 }
763 else if ((LA(1)=='\\') && (LA(2)=='}')) {
764 _saveIndex=text.length();
765 match('\\');
766 text.setLength(_saveIndex);
767 match('}');
768 }
769 else if ((LA(1)=='\\') && ((LA(2) >= '\u0003' && LA(2) <= '\ufffe'))) {
770 mESC_CHAR(false,false);
771 }
772 else if ((LA(1)=='{')) {
773 mNESTED_ANONYMOUS_TEMPLATE(false);
774 }
775 else if ((_tokenSet_4.member(LA(1)))) {
776 matchNot('}');
777 }
778 else {
779 break _loop83;
780 }
781
782 } while (true);
783 }
784 match('}');
785 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
786 _token = makeToken(_ttype);
787 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
788 }
789 _returnToken = _token;
790 }
791
792 public final void mLBRACK(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
793 int _ttype; Token _token=null; int _begin=text.length();
794 _ttype = LBRACK;
795 int _saveIndex;
796
797 match('[');
798 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
799 _token = makeToken(_ttype);
800 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
801 }
802 _returnToken = _token;
803 }
804
805 public final void mRBRACK(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
806 int _ttype; Token _token=null; int _begin=text.length();
807 _ttype = RBRACK;
808 int _saveIndex;
809
810 match(']');
811 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
812 _token = makeToken(_ttype);
813 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
814 }
815 _returnToken = _token;
816 }
817
818 public final void mLPAREN(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
819 int _ttype; Token _token=null; int _begin=text.length();
820 _ttype = LPAREN;
821 int _saveIndex;
822
823 match('(');
824 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
825 _token = makeToken(_ttype);
826 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
827 }
828 _returnToken = _token;
829 }
830
831 public final void mRPAREN(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
832 int _ttype; Token _token=null; int _begin=text.length();
833 _ttype = RPAREN;
834 int _saveIndex;
835
836 match(')');
837 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
838 _token = makeToken(_ttype);
839 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
840 }
841 _returnToken = _token;
842 }
843
844 public final void mCOMMA(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
845 int _ttype; Token _token=null; int _begin=text.length();
846 _ttype = COMMA;
847 int _saveIndex;
848
849 match(',');
850 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
851 _token = makeToken(_ttype);
852 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
853 }
854 _returnToken = _token;
855 }
856
857 public final void mDOT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
858 int _ttype; Token _token=null; int _begin=text.length();
859 _ttype = DOT;
860 int _saveIndex;
861
862 match('.');
863 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
864 _token = makeToken(_ttype);
865 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
866 }
867 _returnToken = _token;
868 }
869
870 public final void mASSIGN(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
871 int _ttype; Token _token=null; int _begin=text.length();
872 _ttype = ASSIGN;
873 int _saveIndex;
874
875 match('=');
876 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
877 _token = makeToken(_ttype);
878 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
879 }
880 _returnToken = _token;
881 }
882
883 public final void mCOLON(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
884 int _ttype; Token _token=null; int _begin=text.length();
885 _ttype = COLON;
886 int _saveIndex;
887
888 match(':');
889 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
890 _token = makeToken(_ttype);
891 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
892 }
893 _returnToken = _token;
894 }
895
896 public final void mPLUS(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
897 int _ttype; Token _token=null; int _begin=text.length();
898 _ttype = PLUS;
899 int _saveIndex;
900
901 match('+');
902 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
903 _token = makeToken(_ttype);
904 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
905 }
906 _returnToken = _token;
907 }
908
909 public final void mSEMI(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
910 int _ttype; Token _token=null; int _begin=text.length();
911 _ttype = SEMI;
912 int _saveIndex;
913
914 match(';');
915 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
916 _token = makeToken(_ttype);
917 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
918 }
919 _returnToken = _token;
920 }
921
922 public final void mNOT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
923 int _ttype; Token _token=null; int _begin=text.length();
924 _ttype = NOT;
925 int _saveIndex;
926
927 match('!');
928 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
929 _token = makeToken(_ttype);
930 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
931 }
932 _returnToken = _token;
933 }
934
935 public final void mDOTDOTDOT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
936 int _ttype; Token _token=null; int _begin=text.length();
937 _ttype = DOTDOTDOT;
938 int _saveIndex;
939
940 match("...");
941 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
942 _token = makeToken(_ttype);
943 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
944 }
945 _returnToken = _token;
946 }
947
948 public final void mWS(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
949 int _ttype; Token _token=null; int _begin=text.length();
950 _ttype = WS;
951 int _saveIndex;
952
953 {
954 int _cnt100=0;
955 _loop100:
956 do {
957 switch ( LA(1)) {
958 case ' ':
959 {
960 match(' ');
961 break;
962 }
963 case '\t':
964 {
965 match('\t');
966 break;
967 }
968 case '\r':
969 {
970 match('\r');
971 break;
972 }
973 case '\n':
974 {
975 match('\n');
976 if ( inputState.guessing==0 ) {
977 newline();
978 }
979 break;
980 }
981 default:
982 {
983 if ( _cnt100>=1 ) { break _loop100; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
984 }
985 }
986 _cnt100++;
987 } while (true);
988 }
989 if ( inputState.guessing==0 ) {
990 _ttype = Token.SKIP;
991 }
992 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
993 _token = makeToken(_ttype);
994 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
995 }
996 _returnToken = _token;
997 }
998
999
1000 private static final long[] mk_tokenSet_0() {
1001 long[] data = new long[2048];
1002 data[0]=-17179869192L;
1003 data[1]=-268435457L;
1004 for (int i = 2; i<=1022; i++) { data[i]=-1L; }
1005 data[1023]=9223372036854775807L;
1006 return data;
1007 }
1008 public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0());
1009 private static final long[] mk_tokenSet_1() {
1010 long[] data = new long[1025];
1011 data[0]=4294977024L;
1012 data[1]=576460745995190270L;
1013 return data;
1014 }
1015 public static final BitSet _tokenSet_1 = new BitSet(mk_tokenSet_1());
1016 private static final long[] mk_tokenSet_2() {
1017 long[] data = new long[1025];
1018 data[0]=288107235144377856L;
1019 data[1]=1729382250602037246L;
1020 return data;
1021 }
1022 public static final BitSet _tokenSet_2 = new BitSet(mk_tokenSet_2());
1023 private static final long[] mk_tokenSet_3() {
1024 long[] data = new long[1025];
1025 data[0]=4294977024L;
1026 return data;
1027 }
1028 public static final BitSet _tokenSet_3 = new BitSet(mk_tokenSet_3());
1029 private static final long[] mk_tokenSet_4() {
1030 long[] data = new long[2048];
1031 data[0]=-8L;
1032 data[1]=-2882303761785552897L;
1033 for (int i = 2; i<=1022; i++) { data[i]=-1L; }
1034 data[1023]=9223372036854775807L;
1035 return data;
1036 }
1037 public static final BitSet _tokenSet_4 = new BitSet(mk_tokenSet_4());
1038 private static final long[] mk_tokenSet_5() {
1039 long[] data = new long[1025];
1040 data[0]=17596481021440L;
1041 return data;
1042 }
1043 public static final BitSet _tokenSet_5 = new BitSet(mk_tokenSet_5());
1044 private static final long[] mk_tokenSet_6() {
1045 long[] data = new long[1025];
1046 data[0]=17596481021440L;
1047 data[1]=576460745995190270L;
1048 return data;
1049 }
1050 public static final BitSet _tokenSet_6 = new BitSet(mk_tokenSet_6());
1051
1052 }
0 SMAP
1 ActionLexer.java
2 G
3 *S G
4 *F
5 + 0 action.g
6 action.g
7 *L
8 0:110
9 0:118
10 0:124
11 0:130
12 0:136
13 0:142
14 0:148
15 0:154
16 0:160
17 0:166
18 0:172
19 0:178
20 0:184
21 0:190
22 0:196
23 0:202
24 0:206
25 1:3
26 1:4
27 1:5
28 1:6
29 1:8
30 1:9
31 1:10
32 1:11
33 1:12
34 1:13
35 1:14
36 1:15
37 1:16
38 1:17
39 1:19
40 1:20
41 1:21
42 1:22
43 1:23
44 1:24
45 1:25
46 1:26
47 1:27
48 1:28
49 1:29
50 1:30
51 1:31
52 1:32
53 241:234
54 241:235
55 241:236
56 241:237
57 241:324
58 241:325
59 241:326
60 241:327
61 241:328
62 241:329
63 241:330
64 245:240
65 245:241
66 245:242
67 245:243
68 245:244
69 245:245
70 245:246
71 245:247
72 245:248
73 245:249
74 245:252
75 245:253
76 245:254
77 245:255
78 245:256
79 245:257
80 245:258
81 245:259
82 245:260
83 245:263
84 245:264
85 245:265
86 245:268
87 245:269
88 245:270
89 245:271
90 245:272
91 245:274
92 245:275
93 245:276
94 245:277
95 245:278
96 245:279
97 245:280
98 245:281
99 245:282
100 245:283
101 245:284
102 245:285
103 245:286
104 245:289
105 245:290
106 245:291
107 245:292
108 245:293
109 245:294
110 245:295
111 245:296
112 245:297
113 245:300
114 245:301
115 245:302
116 245:303
117 245:304
118 245:307
119 245:308
120 245:309
121 245:312
122 245:313
123 245:314
124 245:317
125 245:318
126 245:319
127 245:320
128 245:321
129 245:322
130 245:323
131 248:332
132 248:333
133 248:334
134 248:335
135 248:338
136 248:339
137 248:340
138 248:341
139 248:342
140 248:343
141 248:344
142 248:345
143 248:346
144 248:348
145 248:349
146 248:350
147 248:351
148 248:352
149 248:353
150 248:354
151 248:355
152 248:356
153 250:358
154 250:359
155 250:360
156 250:361
157 250:384
158 250:385
159 250:386
160 250:387
161 250:388
162 250:389
163 251:363
164 251:364
165 251:365
166 251:366
167 251:367
168 251:368
169 251:369
170 251:370
171 251:371
172 251:372
173 251:373
174 251:374
175 251:375
176 251:376
177 251:377
178 251:379
179 251:380
180 251:381
181 251:382
182 251:383
183 254:453
184 254:454
185 254:455
186 254:456
187 254:552
188 254:553
189 254:554
190 254:555
191 254:556
192 254:557
193 255:458
194 256:459
195 259:462
196 259:463
197 259:464
198 260:466
199 260:467
200 260:468
201 260:469
202 260:470
203 260:471
204 260:473
205 260:475
206 260:476
207 260:477
208 260:478
209 260:479
210 260:480
211 260:481
212 260:482
213 260:483
214 260:485
215 260:486
216 260:487
217 260:488
218 260:489
219 260:491
220 260:492
221 260:493
222 260:494
223 260:504
224 260:506
225 260:507
226 260:508
227 260:509
228 261:497
229 262:499
230 263:500
231 264:501
232 268:512
233 268:513
234 268:514
235 268:515
236 268:516
237 268:517
238 268:518
239 268:519
240 268:520
241 268:521
242 268:522
243 268:523
244 268:524
245 268:525
246 268:526
247 268:527
248 268:528
249 268:529
250 268:530
251 268:531
252 268:532
253 268:533
254 268:534
255 268:535
256 268:536
257 268:537
258 268:538
259 268:540
260 268:541
261 269:542
262 270:544
263 271:545
264 272:546
265 274:549
266 274:550
267 274:551
268 278:559
269 278:560
270 278:561
271 278:562
272 278:563
273 278:700
274 278:701
275 278:702
276 278:703
277 278:704
278 278:705
279 278:706
280 279:564
281 279:568
282 279:569
283 279:570
284 279:571
285 279:572
286 279:573
287 279:593
288 279:594
289 279:595
290 279:596
291 279:597
292 279:599
293 279:600
294 279:601
295 279:602
296 279:603
297 279:604
298 280:565
299 280:606
300 280:607
301 280:608
302 280:609
303 280:611
304 280:612
305 280:613
306 280:614
307 280:615
308 280:616
309 280:623
310 280:624
311 280:625
312 280:626
313 280:627
314 280:629
315 280:630
316 280:631
317 280:633
318 280:634
319 280:635
320 280:636
321 280:637
322 280:638
323 280:658
324 280:659
325 280:660
326 280:661
327 280:662
328 280:664
329 280:665
330 280:666
331 280:667
332 280:668
333 280:669
334 280:671
335 280:672
336 280:673
337 280:674
338 280:676
339 280:677
340 281:679
341 281:680
342 281:681
343 281:682
344 281:683
345 281:684
346 281:691
347 281:692
348 281:693
349 281:694
350 281:695
351 281:697
352 281:698
353 281:699
354 285:749
355 285:750
356 285:751
357 285:752
358 285:786
359 285:787
360 285:788
361 285:789
362 285:790
363 285:791
364 286:754
365 286:755
366 286:756
367 286:757
368 286:758
369 286:759
370 286:760
371 286:761
372 286:762
373 286:763
374 286:764
375 286:765
376 286:766
377 286:767
378 286:768
379 286:769
380 286:770
381 286:771
382 286:772
383 286:773
384 286:774
385 286:775
386 286:776
387 286:777
388 286:778
389 286:779
390 286:780
391 286:781
392 286:783
393 286:784
394 286:785
395 293:391
396 293:394
397 293:395
398 293:396
399 293:397
400 293:398
401 293:399
402 293:446
403 293:447
404 293:448
405 293:449
406 293:450
407 293:451
408 294:392
409 294:402
410 295:393
411 295:409
412 295:415
413 295:421
414 295:427
415 295:433
416 295:440
417 295:441
418 295:442
419 295:443
420 296:404
421 296:405
422 296:406
423 296:407
424 297:410
425 297:411
426 297:412
427 297:413
428 298:416
429 298:417
430 298:418
431 298:419
432 299:422
433 299:423
434 299:424
435 299:425
436 300:428
437 300:429
438 300:430
439 300:431
440 301:400
441 301:434
442 301:435
443 301:436
444 301:437
445 301:438
446 305:793
447 305:794
448 305:795
449 305:796
450 305:798
451 305:799
452 305:800
453 305:801
454 305:802
455 305:803
456 305:804
457 306:806
458 306:807
459 306:808
460 306:809
461 306:811
462 306:812
463 306:813
464 306:814
465 306:815
466 306:816
467 306:817
468 307:819
469 307:820
470 307:821
471 307:822
472 307:824
473 307:825
474 307:826
475 307:827
476 307:828
477 307:829
478 307:830
479 308:832
480 308:833
481 308:834
482 308:835
483 308:837
484 308:838
485 308:839
486 308:840
487 308:841
488 308:842
489 308:843
490 309:845
491 309:846
492 309:847
493 309:848
494 309:850
495 309:851
496 309:852
497 309:853
498 309:854
499 309:855
500 309:856
501 310:858
502 310:859
503 310:860
504 310:861
505 310:863
506 310:864
507 310:865
508 310:866
509 310:867
510 310:868
511 310:869
512 311:871
513 311:872
514 311:873
515 311:874
516 311:876
517 311:877
518 311:878
519 311:879
520 311:880
521 311:881
522 311:882
523 312:884
524 312:885
525 312:886
526 312:887
527 312:889
528 312:890
529 312:891
530 312:892
531 312:893
532 312:894
533 312:895
534 313:897
535 313:898
536 313:899
537 313:900
538 313:902
539 313:903
540 313:904
541 313:905
542 313:906
543 313:907
544 313:908
545 314:910
546 314:911
547 314:912
548 314:913
549 314:915
550 314:916
551 314:917
552 314:918
553 314:919
554 314:920
555 314:921
556 315:923
557 315:924
558 315:925
559 315:926
560 315:928
561 315:929
562 315:930
563 315:931
564 315:932
565 315:933
566 315:934
567 316:936
568 316:937
569 316:938
570 316:939
571 316:941
572 316:942
573 316:943
574 316:944
575 316:945
576 316:946
577 316:947
578 318:949
579 318:950
580 318:951
581 318:952
582 318:955
583 318:956
584 318:957
585 318:958
586 318:959
587 318:960
588 318:961
589 318:964
590 318:965
591 318:966
592 318:969
593 318:970
594 318:971
595 318:974
596 318:975
597 318:976
598 318:977
599 318:978
600 318:982
601 318:983
602 318:984
603 318:985
604 318:986
605 318:987
606 318:988
607 318:989
608 318:990
609 318:991
610 318:993
611 318:994
612 318:995
613 318:996
614 318:997
615 318:998
616 322:708
617 322:709
618 322:710
619 322:711
620 322:713
621 322:737
622 322:738
623 322:739
624 322:740
625 322:741
626 322:742
627 322:743
628 322:744
629 322:745
630 322:746
631 322:747
632 323:714
633 323:715
634 323:716
635 323:719
636 323:720
637 323:721
638 323:724
639 323:725
640 323:726
641 323:729
642 323:730
643 323:731
644 323:732
645 323:733
646 *E
0 // $ANTLR 2.7.7 (20060906): "action.g" -> "ActionParser.java"$
1
2 /*
3 [The "BSD licence"]
4 Copyright (c) 2003-2004 Terence Parr
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 package org.antlr.stringtemplate.language;
30 import org.antlr.stringtemplate.*;
31 import java.util.*;
32
33 import antlr.TokenBuffer;
34 import antlr.TokenStreamException;
35 import antlr.TokenStreamIOException;
36 import antlr.ANTLRException;
37 import antlr.LLkParser;
38 import antlr.Token;
39 import antlr.TokenStream;
40 import antlr.RecognitionException;
41 import antlr.NoViableAltException;
42 import antlr.MismatchedTokenException;
43 import antlr.SemanticException;
44 import antlr.ParserSharedInputState;
45 import antlr.collections.impl.BitSet;
46 import antlr.collections.AST;
47 import java.util.Hashtable;
48 import antlr.ASTFactory;
49 import antlr.ASTPair;
50 import antlr.collections.impl.ASTArray;
51
52 /** Parse the individual attribute expressions */
53 public class ActionParser extends antlr.LLkParser implements ActionParserTokenTypes
54 {
55
56 protected StringTemplate self = null;
57
58 public ActionParser(TokenStream lexer, StringTemplate self) {
59 this(lexer, 2);
60 this.self = self;
61 }
62
63 public void reportError(RecognitionException e) {
64 StringTemplateGroup group = self.getGroup();
65 if ( group==StringTemplate.defaultGroup ) {
66 self.error("action parse error; template context is "+self.getEnclosingInstanceStackString(), e);
67 }
68 else {
69 self.error("action parse error in group "+self.getGroup().getName()+" line "+self.getGroupFileLine()+"; template context is "+self.getEnclosingInstanceStackString(), e);
70 }
71 }
72
73 protected ActionParser(TokenBuffer tokenBuf, int k) {
74 super(tokenBuf,k);
75 tokenNames = _tokenNames;
76 buildTokenTypeASTClassMap();
77 astFactory = new ASTFactory(getTokenTypeToASTClassMap());
78 }
79
80 public ActionParser(TokenBuffer tokenBuf) {
81 this(tokenBuf,2);
82 }
83
84 protected ActionParser(TokenStream lexer, int k) {
85 super(lexer,k);
86 tokenNames = _tokenNames;
87 buildTokenTypeASTClassMap();
88 astFactory = new ASTFactory(getTokenTypeToASTClassMap());
89 }
90
91 public ActionParser(TokenStream lexer) {
92 this(lexer,2);
93 }
94
95 public ActionParser(ParserSharedInputState state) {
96 super(state,2);
97 tokenNames = _tokenNames;
98 buildTokenTypeASTClassMap();
99 astFactory = new ASTFactory(getTokenTypeToASTClassMap());
100 }
101
102 public final Map action() throws RecognitionException, TokenStreamException {
103 Map opts=null;
104
105 returnAST = null;
106 ASTPair currentAST = new ASTPair();
107 org.antlr.stringtemplate.language.StringTemplateAST action_AST = null;
108
109 try { // for error handling
110 switch ( LA(1)) {
111 case LPAREN:
112 case ID:
113 case LITERAL_first:
114 case LITERAL_rest:
115 case LITERAL_last:
116 case LITERAL_length:
117 case LITERAL_strip:
118 case LITERAL_trunc:
119 case LITERAL_super:
120 case ANONYMOUS_TEMPLATE:
121 case STRING:
122 case INT:
123 case LBRACK:
124 {
125 templatesExpr();
126 astFactory.addASTChild(currentAST, returnAST);
127 {
128 switch ( LA(1)) {
129 case SEMI:
130 {
131 match(SEMI);
132 opts=optionList();
133 astFactory.addASTChild(currentAST, returnAST);
134 break;
135 }
136 case EOF:
137 {
138 break;
139 }
140 default:
141 {
142 throw new NoViableAltException(LT(1), getFilename());
143 }
144 }
145 }
146 action_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
147 break;
148 }
149 case CONDITIONAL:
150 {
151 org.antlr.stringtemplate.language.StringTemplateAST tmp2_AST = null;
152 tmp2_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
153 astFactory.makeASTRoot(currentAST, tmp2_AST);
154 match(CONDITIONAL);
155 match(LPAREN);
156 ifCondition();
157 astFactory.addASTChild(currentAST, returnAST);
158 match(RPAREN);
159 action_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
160 break;
161 }
162 case LITERAL_elseif:
163 {
164 match(LITERAL_elseif);
165 match(LPAREN);
166 ifCondition();
167 astFactory.addASTChild(currentAST, returnAST);
168 match(RPAREN);
169 action_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
170 break;
171 }
172 default:
173 {
174 throw new NoViableAltException(LT(1), getFilename());
175 }
176 }
177 }
178 catch (RecognitionException ex) {
179 if (inputState.guessing==0) {
180 reportError(ex);
181 recover(ex,_tokenSet_0);
182 } else {
183 throw ex;
184 }
185 }
186 returnAST = action_AST;
187 return opts;
188 }
189
190 public final void templatesExpr() throws RecognitionException, TokenStreamException {
191
192 returnAST = null;
193 ASTPair currentAST = new ASTPair();
194 org.antlr.stringtemplate.language.StringTemplateAST templatesExpr_AST = null;
195 Token c = null;
196 org.antlr.stringtemplate.language.StringTemplateAST c_AST = null;
197
198 try { // for error handling
199 boolean synPredMatched10 = false;
200 if (((_tokenSet_1.member(LA(1))) && (_tokenSet_2.member(LA(2))))) {
201 int _m10 = mark();
202 synPredMatched10 = true;
203 inputState.guessing++;
204 try {
205 {
206 parallelArrayTemplateApplication();
207 }
208 }
209 catch (RecognitionException pe) {
210 synPredMatched10 = false;
211 }
212 rewind(_m10);
213 inputState.guessing--;
214 }
215 if ( synPredMatched10 ) {
216 parallelArrayTemplateApplication();
217 astFactory.addASTChild(currentAST, returnAST);
218 templatesExpr_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
219 }
220 else if ((_tokenSet_1.member(LA(1))) && (_tokenSet_3.member(LA(2)))) {
221 expr();
222 astFactory.addASTChild(currentAST, returnAST);
223 {
224 _loop14:
225 do {
226 if ((LA(1)==COLON)) {
227 c = LT(1);
228 c_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(c);
229 astFactory.makeASTRoot(currentAST, c_AST);
230 match(COLON);
231 if ( inputState.guessing==0 ) {
232 c_AST.setType(APPLY);
233 }
234 template();
235 astFactory.addASTChild(currentAST, returnAST);
236 {
237 _loop13:
238 do {
239 if ((LA(1)==COMMA)) {
240 match(COMMA);
241 template();
242 astFactory.addASTChild(currentAST, returnAST);
243 }
244 else {
245 break _loop13;
246 }
247
248 } while (true);
249 }
250 }
251 else {
252 break _loop14;
253 }
254
255 } while (true);
256 }
257 templatesExpr_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
258 }
259 else {
260 throw new NoViableAltException(LT(1), getFilename());
261 }
262
263 }
264 catch (RecognitionException ex) {
265 if (inputState.guessing==0) {
266 reportError(ex);
267 recover(ex,_tokenSet_4);
268 } else {
269 throw ex;
270 }
271 }
272 returnAST = templatesExpr_AST;
273 }
274
275 public final Map optionList() throws RecognitionException, TokenStreamException {
276 Map opts=new HashMap();
277
278 returnAST = null;
279 ASTPair currentAST = new ASTPair();
280 org.antlr.stringtemplate.language.StringTemplateAST optionList_AST = null;
281
282 try { // for error handling
283 option(opts);
284 {
285 _loop5:
286 do {
287 if ((LA(1)==COMMA)) {
288 org.antlr.stringtemplate.language.StringTemplateAST tmp9_AST = null;
289 tmp9_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
290 match(COMMA);
291 option(opts);
292 }
293 else {
294 break _loop5;
295 }
296
297 } while (true);
298 }
299 }
300 catch (RecognitionException ex) {
301 if (inputState.guessing==0) {
302 reportError(ex);
303 recover(ex,_tokenSet_0);
304 } else {
305 throw ex;
306 }
307 }
308 returnAST = optionList_AST;
309 return opts;
310 }
311
312 public final void ifCondition() throws RecognitionException, TokenStreamException {
313
314 returnAST = null;
315 ASTPair currentAST = new ASTPair();
316 org.antlr.stringtemplate.language.StringTemplateAST ifCondition_AST = null;
317
318 try { // for error handling
319 switch ( LA(1)) {
320 case LPAREN:
321 case ID:
322 case LITERAL_first:
323 case LITERAL_rest:
324 case LITERAL_last:
325 case LITERAL_length:
326 case LITERAL_strip:
327 case LITERAL_trunc:
328 case LITERAL_super:
329 case ANONYMOUS_TEMPLATE:
330 case STRING:
331 case INT:
332 case LBRACK:
333 {
334 ifAtom();
335 astFactory.addASTChild(currentAST, returnAST);
336 ifCondition_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
337 break;
338 }
339 case NOT:
340 {
341 org.antlr.stringtemplate.language.StringTemplateAST tmp10_AST = null;
342 tmp10_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
343 astFactory.makeASTRoot(currentAST, tmp10_AST);
344 match(NOT);
345 ifAtom();
346 astFactory.addASTChild(currentAST, returnAST);
347 ifCondition_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
348 break;
349 }
350 default:
351 {
352 throw new NoViableAltException(LT(1), getFilename());
353 }
354 }
355 }
356 catch (RecognitionException ex) {
357 if (inputState.guessing==0) {
358 reportError(ex);
359 recover(ex,_tokenSet_5);
360 } else {
361 throw ex;
362 }
363 }
364 returnAST = ifCondition_AST;
365 }
366
367 public final void option(
368 Map opts
369 ) throws RecognitionException, TokenStreamException {
370
371 returnAST = null;
372 ASTPair currentAST = new ASTPair();
373 org.antlr.stringtemplate.language.StringTemplateAST option_AST = null;
374 Token i = null;
375 org.antlr.stringtemplate.language.StringTemplateAST i_AST = null;
376 org.antlr.stringtemplate.language.StringTemplateAST e_AST = null;
377
378 Object v=null;
379
380
381 try { // for error handling
382 i = LT(1);
383 i_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(i);
384 astFactory.addASTChild(currentAST, i_AST);
385 match(ID);
386 {
387 switch ( LA(1)) {
388 case ASSIGN:
389 {
390 org.antlr.stringtemplate.language.StringTemplateAST tmp11_AST = null;
391 tmp11_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
392 astFactory.addASTChild(currentAST, tmp11_AST);
393 match(ASSIGN);
394 nonAlternatingTemplateExpr();
395 e_AST = (org.antlr.stringtemplate.language.StringTemplateAST)returnAST;
396 astFactory.addASTChild(currentAST, returnAST);
397 if ( inputState.guessing==0 ) {
398 v=e_AST;
399 }
400 break;
401 }
402 case EOF:
403 case COMMA:
404 {
405 if ( inputState.guessing==0 ) {
406 v=ASTExpr.EMPTY_OPTION;
407 }
408 break;
409 }
410 default:
411 {
412 throw new NoViableAltException(LT(1), getFilename());
413 }
414 }
415 }
416 if ( inputState.guessing==0 ) {
417 opts.put(i_AST.getText(),v);
418 }
419 option_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
420 }
421 catch (RecognitionException ex) {
422 if (inputState.guessing==0) {
423 reportError(ex);
424 recover(ex,_tokenSet_6);
425 } else {
426 throw ex;
427 }
428 }
429 returnAST = option_AST;
430 }
431
432 public final void nonAlternatingTemplateExpr() throws RecognitionException, TokenStreamException {
433
434 returnAST = null;
435 ASTPair currentAST = new ASTPair();
436 org.antlr.stringtemplate.language.StringTemplateAST nonAlternatingTemplateExpr_AST = null;
437 Token c = null;
438 org.antlr.stringtemplate.language.StringTemplateAST c_AST = null;
439
440 try { // for error handling
441 expr();
442 astFactory.addASTChild(currentAST, returnAST);
443 {
444 _loop35:
445 do {
446 if ((LA(1)==COLON)) {
447 c = LT(1);
448 c_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(c);
449 astFactory.makeASTRoot(currentAST, c_AST);
450 match(COLON);
451 if ( inputState.guessing==0 ) {
452 c_AST.setType(APPLY);
453 }
454 template();
455 astFactory.addASTChild(currentAST, returnAST);
456 }
457 else {
458 break _loop35;
459 }
460
461 } while (true);
462 }
463 nonAlternatingTemplateExpr_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
464 }
465 catch (RecognitionException ex) {
466 if (inputState.guessing==0) {
467 reportError(ex);
468 recover(ex,_tokenSet_7);
469 } else {
470 throw ex;
471 }
472 }
473 returnAST = nonAlternatingTemplateExpr_AST;
474 }
475
476 public final void parallelArrayTemplateApplication() throws RecognitionException, TokenStreamException {
477
478 returnAST = null;
479 ASTPair currentAST = new ASTPair();
480 org.antlr.stringtemplate.language.StringTemplateAST parallelArrayTemplateApplication_AST = null;
481 Token c = null;
482 org.antlr.stringtemplate.language.StringTemplateAST c_AST = null;
483
484 try { // for error handling
485 expr();
486 astFactory.addASTChild(currentAST, returnAST);
487 {
488 int _cnt17=0;
489 _loop17:
490 do {
491 if ((LA(1)==COMMA)) {
492 match(COMMA);
493 expr();
494 astFactory.addASTChild(currentAST, returnAST);
495 }
496 else {
497 if ( _cnt17>=1 ) { break _loop17; } else {throw new NoViableAltException(LT(1), getFilename());}
498 }
499
500 _cnt17++;
501 } while (true);
502 }
503 c = LT(1);
504 c_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(c);
505 astFactory.addASTChild(currentAST, c_AST);
506 match(COLON);
507 anonymousTemplate();
508 astFactory.addASTChild(currentAST, returnAST);
509 if ( inputState.guessing==0 ) {
510 parallelArrayTemplateApplication_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
511 parallelArrayTemplateApplication_AST =
512 (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.make( (new ASTArray(2)).add((org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(MULTI_APPLY,"MULTI_APPLY")).add(parallelArrayTemplateApplication_AST));
513 currentAST.root = parallelArrayTemplateApplication_AST;
514 currentAST.child = parallelArrayTemplateApplication_AST!=null &&parallelArrayTemplateApplication_AST.getFirstChild()!=null ?
515 parallelArrayTemplateApplication_AST.getFirstChild() : parallelArrayTemplateApplication_AST;
516 currentAST.advanceChildToEnd();
517 }
518 parallelArrayTemplateApplication_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
519 }
520 catch (RecognitionException ex) {
521 if (inputState.guessing==0) {
522 reportError(ex);
523 recover(ex,_tokenSet_4);
524 } else {
525 throw ex;
526 }
527 }
528 returnAST = parallelArrayTemplateApplication_AST;
529 }
530
531 public final void expr() throws RecognitionException, TokenStreamException {
532
533 returnAST = null;
534 ASTPair currentAST = new ASTPair();
535 org.antlr.stringtemplate.language.StringTemplateAST expr_AST = null;
536
537 try { // for error handling
538 primaryExpr();
539 astFactory.addASTChild(currentAST, returnAST);
540 {
541 _loop22:
542 do {
543 if ((LA(1)==PLUS)) {
544 org.antlr.stringtemplate.language.StringTemplateAST tmp13_AST = null;
545 tmp13_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
546 astFactory.makeASTRoot(currentAST, tmp13_AST);
547 match(PLUS);
548 primaryExpr();
549 astFactory.addASTChild(currentAST, returnAST);
550 }
551 else {
552 break _loop22;
553 }
554
555 } while (true);
556 }
557 expr_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
558 }
559 catch (RecognitionException ex) {
560 if (inputState.guessing==0) {
561 reportError(ex);
562 recover(ex,_tokenSet_8);
563 } else {
564 throw ex;
565 }
566 }
567 returnAST = expr_AST;
568 }
569
570 public final void template() throws RecognitionException, TokenStreamException {
571
572 returnAST = null;
573 ASTPair currentAST = new ASTPair();
574 org.antlr.stringtemplate.language.StringTemplateAST template_AST = null;
575
576 try { // for error handling
577 {
578 switch ( LA(1)) {
579 case LPAREN:
580 case ID:
581 case LITERAL_super:
582 {
583 namedTemplate();
584 astFactory.addASTChild(currentAST, returnAST);
585 break;
586 }
587 case ANONYMOUS_TEMPLATE:
588 {
589 anonymousTemplate();
590 astFactory.addASTChild(currentAST, returnAST);
591 break;
592 }
593 default:
594 {
595 throw new NoViableAltException(LT(1), getFilename());
596 }
597 }
598 }
599 if ( inputState.guessing==0 ) {
600 template_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
601 template_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.make( (new ASTArray(2)).add((org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(TEMPLATE)).add(template_AST));
602 currentAST.root = template_AST;
603 currentAST.child = template_AST!=null &&template_AST.getFirstChild()!=null ?
604 template_AST.getFirstChild() : template_AST;
605 currentAST.advanceChildToEnd();
606 }
607 template_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
608 }
609 catch (RecognitionException ex) {
610 if (inputState.guessing==0) {
611 reportError(ex);
612 recover(ex,_tokenSet_8);
613 } else {
614 throw ex;
615 }
616 }
617 returnAST = template_AST;
618 }
619
620 public final void anonymousTemplate() throws RecognitionException, TokenStreamException {
621
622 returnAST = null;
623 ASTPair currentAST = new ASTPair();
624 org.antlr.stringtemplate.language.StringTemplateAST anonymousTemplate_AST = null;
625 Token t = null;
626 org.antlr.stringtemplate.language.StringTemplateAST t_AST = null;
627
628 try { // for error handling
629 t = LT(1);
630 t_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(t);
631 astFactory.addASTChild(currentAST, t_AST);
632 match(ANONYMOUS_TEMPLATE);
633 if ( inputState.guessing==0 ) {
634
635 StringTemplate anonymous = new StringTemplate();
636 anonymous.setGroup(self.getGroup());
637 anonymous.setEnclosingInstance(self);
638 anonymous.setTemplate(t.getText());
639 anonymous.defineFormalArguments(((StringTemplateToken)t).args);
640 t_AST.setStringTemplate(anonymous);
641
642 }
643 anonymousTemplate_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
644 }
645 catch (RecognitionException ex) {
646 if (inputState.guessing==0) {
647 reportError(ex);
648 recover(ex,_tokenSet_8);
649 } else {
650 throw ex;
651 }
652 }
653 returnAST = anonymousTemplate_AST;
654 }
655
656 public final void ifAtom() throws RecognitionException, TokenStreamException {
657
658 returnAST = null;
659 ASTPair currentAST = new ASTPair();
660 org.antlr.stringtemplate.language.StringTemplateAST ifAtom_AST = null;
661
662 try { // for error handling
663 templatesExpr();
664 astFactory.addASTChild(currentAST, returnAST);
665 ifAtom_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
666 }
667 catch (RecognitionException ex) {
668 if (inputState.guessing==0) {
669 reportError(ex);
670 recover(ex,_tokenSet_5);
671 } else {
672 throw ex;
673 }
674 }
675 returnAST = ifAtom_AST;
676 }
677
678 public final void primaryExpr() throws RecognitionException, TokenStreamException {
679
680 returnAST = null;
681 ASTPair currentAST = new ASTPair();
682 org.antlr.stringtemplate.language.StringTemplateAST primaryExpr_AST = null;
683
684 try { // for error handling
685 switch ( LA(1)) {
686 case LITERAL_first:
687 case LITERAL_rest:
688 case LITERAL_last:
689 case LITERAL_length:
690 case LITERAL_strip:
691 case LITERAL_trunc:
692 {
693 function();
694 astFactory.addASTChild(currentAST, returnAST);
695 {
696 _loop31:
697 do {
698 if ((LA(1)==DOT)) {
699 org.antlr.stringtemplate.language.StringTemplateAST tmp14_AST = null;
700 tmp14_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
701 astFactory.makeASTRoot(currentAST, tmp14_AST);
702 match(DOT);
703 {
704 switch ( LA(1)) {
705 case ID:
706 {
707 org.antlr.stringtemplate.language.StringTemplateAST tmp15_AST = null;
708 tmp15_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
709 astFactory.addASTChild(currentAST, tmp15_AST);
710 match(ID);
711 break;
712 }
713 case LPAREN:
714 {
715 valueExpr();
716 astFactory.addASTChild(currentAST, returnAST);
717 break;
718 }
719 default:
720 {
721 throw new NoViableAltException(LT(1), getFilename());
722 }
723 }
724 }
725 }
726 else {
727 break _loop31;
728 }
729
730 } while (true);
731 }
732 primaryExpr_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
733 break;
734 }
735 case LBRACK:
736 {
737 list();
738 astFactory.addASTChild(currentAST, returnAST);
739 primaryExpr_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
740 break;
741 }
742 default:
743 boolean synPredMatched25 = false;
744 if (((LA(1)==LPAREN||LA(1)==ID||LA(1)==LITERAL_super) && (_tokenSet_9.member(LA(2))))) {
745 int _m25 = mark();
746 synPredMatched25 = true;
747 inputState.guessing++;
748 try {
749 {
750 templateInclude();
751 }
752 }
753 catch (RecognitionException pe) {
754 synPredMatched25 = false;
755 }
756 rewind(_m25);
757 inputState.guessing--;
758 }
759 if ( synPredMatched25 ) {
760 templateInclude();
761 astFactory.addASTChild(currentAST, returnAST);
762 primaryExpr_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
763 }
764 else if ((_tokenSet_10.member(LA(1))) && (_tokenSet_11.member(LA(2)))) {
765 atom();
766 astFactory.addASTChild(currentAST, returnAST);
767 {
768 _loop28:
769 do {
770 if ((LA(1)==DOT)) {
771 org.antlr.stringtemplate.language.StringTemplateAST tmp16_AST = null;
772 tmp16_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
773 astFactory.makeASTRoot(currentAST, tmp16_AST);
774 match(DOT);
775 {
776 switch ( LA(1)) {
777 case ID:
778 {
779 org.antlr.stringtemplate.language.StringTemplateAST tmp17_AST = null;
780 tmp17_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
781 astFactory.addASTChild(currentAST, tmp17_AST);
782 match(ID);
783 break;
784 }
785 case LPAREN:
786 {
787 valueExpr();
788 astFactory.addASTChild(currentAST, returnAST);
789 break;
790 }
791 default:
792 {
793 throw new NoViableAltException(LT(1), getFilename());
794 }
795 }
796 }
797 }
798 else {
799 break _loop28;
800 }
801
802 } while (true);
803 }
804 primaryExpr_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
805 }
806 else if ((LA(1)==LPAREN) && (_tokenSet_1.member(LA(2)))) {
807 valueExpr();
808 astFactory.addASTChild(currentAST, returnAST);
809 primaryExpr_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
810 }
811 else {
812 throw new NoViableAltException(LT(1), getFilename());
813 }
814 }
815 }
816 catch (RecognitionException ex) {
817 if (inputState.guessing==0) {
818 reportError(ex);
819 recover(ex,_tokenSet_12);
820 } else {
821 throw ex;
822 }
823 }
824 returnAST = primaryExpr_AST;
825 }
826
827 public final void templateInclude() throws RecognitionException, TokenStreamException {
828
829 returnAST = null;
830 ASTPair currentAST = new ASTPair();
831 org.antlr.stringtemplate.language.StringTemplateAST templateInclude_AST = null;
832 Token id = null;
833 org.antlr.stringtemplate.language.StringTemplateAST id_AST = null;
834 Token qid = null;
835 org.antlr.stringtemplate.language.StringTemplateAST qid_AST = null;
836
837 try { // for error handling
838 {
839 switch ( LA(1)) {
840 case ID:
841 {
842 id = LT(1);
843 id_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(id);
844 astFactory.addASTChild(currentAST, id_AST);
845 match(ID);
846 argList();
847 astFactory.addASTChild(currentAST, returnAST);
848 break;
849 }
850 case LITERAL_super:
851 {
852 match(LITERAL_super);
853 match(DOT);
854 qid = LT(1);
855 qid_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(qid);
856 astFactory.addASTChild(currentAST, qid_AST);
857 match(ID);
858 if ( inputState.guessing==0 ) {
859 qid_AST.setText("super."+qid_AST.getText());
860 }
861 argList();
862 astFactory.addASTChild(currentAST, returnAST);
863 break;
864 }
865 case LPAREN:
866 {
867 indirectTemplate();
868 astFactory.addASTChild(currentAST, returnAST);
869 break;
870 }
871 default:
872 {
873 throw new NoViableAltException(LT(1), getFilename());
874 }
875 }
876 }
877 if ( inputState.guessing==0 ) {
878 templateInclude_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
879 templateInclude_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.make( (new ASTArray(2)).add((org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(INCLUDE,"include")).add(templateInclude_AST));
880 currentAST.root = templateInclude_AST;
881 currentAST.child = templateInclude_AST!=null &&templateInclude_AST.getFirstChild()!=null ?
882 templateInclude_AST.getFirstChild() : templateInclude_AST;
883 currentAST.advanceChildToEnd();
884 }
885 templateInclude_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
886 }
887 catch (RecognitionException ex) {
888 if (inputState.guessing==0) {
889 reportError(ex);
890 recover(ex,_tokenSet_12);
891 } else {
892 throw ex;
893 }
894 }
895 returnAST = templateInclude_AST;
896 }
897
898 public final void atom() throws RecognitionException, TokenStreamException {
899
900 returnAST = null;
901 ASTPair currentAST = new ASTPair();
902 org.antlr.stringtemplate.language.StringTemplateAST atom_AST = null;
903
904 try { // for error handling
905 switch ( LA(1)) {
906 case ID:
907 {
908 org.antlr.stringtemplate.language.StringTemplateAST tmp20_AST = null;
909 tmp20_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
910 astFactory.addASTChild(currentAST, tmp20_AST);
911 match(ID);
912 atom_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
913 break;
914 }
915 case STRING:
916 {
917 org.antlr.stringtemplate.language.StringTemplateAST tmp21_AST = null;
918 tmp21_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
919 astFactory.addASTChild(currentAST, tmp21_AST);
920 match(STRING);
921 atom_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
922 break;
923 }
924 case INT:
925 {
926 org.antlr.stringtemplate.language.StringTemplateAST tmp22_AST = null;
927 tmp22_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
928 astFactory.addASTChild(currentAST, tmp22_AST);
929 match(INT);
930 atom_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
931 break;
932 }
933 case ANONYMOUS_TEMPLATE:
934 {
935 org.antlr.stringtemplate.language.StringTemplateAST tmp23_AST = null;
936 tmp23_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
937 astFactory.addASTChild(currentAST, tmp23_AST);
938 match(ANONYMOUS_TEMPLATE);
939 atom_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
940 break;
941 }
942 default:
943 {
944 throw new NoViableAltException(LT(1), getFilename());
945 }
946 }
947 }
948 catch (RecognitionException ex) {
949 if (inputState.guessing==0) {
950 reportError(ex);
951 recover(ex,_tokenSet_11);
952 } else {
953 throw ex;
954 }
955 }
956 returnAST = atom_AST;
957 }
958
959 public final void valueExpr() throws RecognitionException, TokenStreamException {
960
961 returnAST = null;
962 ASTPair currentAST = new ASTPair();
963 org.antlr.stringtemplate.language.StringTemplateAST valueExpr_AST = null;
964 Token eval = null;
965 org.antlr.stringtemplate.language.StringTemplateAST eval_AST = null;
966
967 try { // for error handling
968 eval = LT(1);
969 eval_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(eval);
970 astFactory.makeASTRoot(currentAST, eval_AST);
971 match(LPAREN);
972 templatesExpr();
973 astFactory.addASTChild(currentAST, returnAST);
974 match(RPAREN);
975 if ( inputState.guessing==0 ) {
976 eval_AST.setType(VALUE); eval_AST.setText("value");
977 }
978 valueExpr_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
979 }
980 catch (RecognitionException ex) {
981 if (inputState.guessing==0) {
982 reportError(ex);
983 recover(ex,_tokenSet_11);
984 } else {
985 throw ex;
986 }
987 }
988 returnAST = valueExpr_AST;
989 }
990
991 public final void function() throws RecognitionException, TokenStreamException {
992
993 returnAST = null;
994 ASTPair currentAST = new ASTPair();
995 org.antlr.stringtemplate.language.StringTemplateAST function_AST = null;
996
997 try { // for error handling
998 {
999 switch ( LA(1)) {
1000 case LITERAL_first:
1001 {
1002 org.antlr.stringtemplate.language.StringTemplateAST tmp25_AST = null;
1003 tmp25_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
1004 astFactory.addASTChild(currentAST, tmp25_AST);
1005 match(LITERAL_first);
1006 break;
1007 }
1008 case LITERAL_rest:
1009 {
1010 org.antlr.stringtemplate.language.StringTemplateAST tmp26_AST = null;
1011 tmp26_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
1012 astFactory.addASTChild(currentAST, tmp26_AST);
1013 match(LITERAL_rest);
1014 break;
1015 }
1016 case LITERAL_last:
1017 {
1018 org.antlr.stringtemplate.language.StringTemplateAST tmp27_AST = null;
1019 tmp27_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
1020 astFactory.addASTChild(currentAST, tmp27_AST);
1021 match(LITERAL_last);
1022 break;
1023 }
1024 case LITERAL_length:
1025 {
1026 org.antlr.stringtemplate.language.StringTemplateAST tmp28_AST = null;
1027 tmp28_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
1028 astFactory.addASTChild(currentAST, tmp28_AST);
1029 match(LITERAL_length);
1030 break;
1031 }
1032 case LITERAL_strip:
1033 {
1034 org.antlr.stringtemplate.language.StringTemplateAST tmp29_AST = null;
1035 tmp29_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
1036 astFactory.addASTChild(currentAST, tmp29_AST);
1037 match(LITERAL_strip);
1038 break;
1039 }
1040 case LITERAL_trunc:
1041 {
1042 org.antlr.stringtemplate.language.StringTemplateAST tmp30_AST = null;
1043 tmp30_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
1044 astFactory.addASTChild(currentAST, tmp30_AST);
1045 match(LITERAL_trunc);
1046 break;
1047 }
1048 default:
1049 {
1050 throw new NoViableAltException(LT(1), getFilename());
1051 }
1052 }
1053 }
1054 singleArg();
1055 astFactory.addASTChild(currentAST, returnAST);
1056 if ( inputState.guessing==0 ) {
1057 function_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
1058 function_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.make( (new ASTArray(2)).add((org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(FUNCTION)).add(function_AST));
1059 currentAST.root = function_AST;
1060 currentAST.child = function_AST!=null &&function_AST.getFirstChild()!=null ?
1061 function_AST.getFirstChild() : function_AST;
1062 currentAST.advanceChildToEnd();
1063 }
1064 function_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
1065 }
1066 catch (RecognitionException ex) {
1067 if (inputState.guessing==0) {
1068 reportError(ex);
1069 recover(ex,_tokenSet_11);
1070 } else {
1071 throw ex;
1072 }
1073 }
1074 returnAST = function_AST;
1075 }
1076
1077 public final void list() throws RecognitionException, TokenStreamException {
1078
1079 returnAST = null;
1080 ASTPair currentAST = new ASTPair();
1081 org.antlr.stringtemplate.language.StringTemplateAST list_AST = null;
1082 Token lb = null;
1083 org.antlr.stringtemplate.language.StringTemplateAST lb_AST = null;
1084
1085 try { // for error handling
1086 lb = LT(1);
1087 lb_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(lb);
1088 astFactory.makeASTRoot(currentAST, lb_AST);
1089 match(LBRACK);
1090 if ( inputState.guessing==0 ) {
1091 lb_AST.setType(LIST); lb_AST.setText("value");
1092 }
1093 listElement();
1094 astFactory.addASTChild(currentAST, returnAST);
1095 {
1096 _loop45:
1097 do {
1098 if ((LA(1)==COMMA)) {
1099 match(COMMA);
1100 listElement();
1101 astFactory.addASTChild(currentAST, returnAST);
1102 }
1103 else {
1104 break _loop45;
1105 }
1106
1107 } while (true);
1108 }
1109 match(RBRACK);
1110 list_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
1111 }
1112 catch (RecognitionException ex) {
1113 if (inputState.guessing==0) {
1114 reportError(ex);
1115 recover(ex,_tokenSet_12);
1116 } else {
1117 throw ex;
1118 }
1119 }
1120 returnAST = list_AST;
1121 }
1122
1123 public final void singleArg() throws RecognitionException, TokenStreamException {
1124
1125 returnAST = null;
1126 ASTPair currentAST = new ASTPair();
1127 org.antlr.stringtemplate.language.StringTemplateAST singleArg_AST = null;
1128
1129 try { // for error handling
1130 match(LPAREN);
1131 nonAlternatingTemplateExpr();
1132 astFactory.addASTChild(currentAST, returnAST);
1133 match(RPAREN);
1134 if ( inputState.guessing==0 ) {
1135 singleArg_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
1136 singleArg_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.make( (new ASTArray(2)).add((org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(SINGLEVALUEARG,"SINGLEVALUEARG")).add(singleArg_AST));
1137 currentAST.root = singleArg_AST;
1138 currentAST.child = singleArg_AST!=null &&singleArg_AST.getFirstChild()!=null ?
1139 singleArg_AST.getFirstChild() : singleArg_AST;
1140 currentAST.advanceChildToEnd();
1141 }
1142 singleArg_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
1143 }
1144 catch (RecognitionException ex) {
1145 if (inputState.guessing==0) {
1146 reportError(ex);
1147 recover(ex,_tokenSet_11);
1148 } else {
1149 throw ex;
1150 }
1151 }
1152 returnAST = singleArg_AST;
1153 }
1154
1155 public final void namedTemplate() throws RecognitionException, TokenStreamException {
1156
1157 returnAST = null;
1158 ASTPair currentAST = new ASTPair();
1159 org.antlr.stringtemplate.language.StringTemplateAST namedTemplate_AST = null;
1160 Token qid = null;
1161 org.antlr.stringtemplate.language.StringTemplateAST qid_AST = null;
1162
1163 try { // for error handling
1164 switch ( LA(1)) {
1165 case ID:
1166 {
1167 org.antlr.stringtemplate.language.StringTemplateAST tmp35_AST = null;
1168 tmp35_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
1169 astFactory.addASTChild(currentAST, tmp35_AST);
1170 match(ID);
1171 argList();
1172 astFactory.addASTChild(currentAST, returnAST);
1173 namedTemplate_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
1174 break;
1175 }
1176 case LITERAL_super:
1177 {
1178 match(LITERAL_super);
1179 match(DOT);
1180 qid = LT(1);
1181 qid_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(qid);
1182 astFactory.addASTChild(currentAST, qid_AST);
1183 match(ID);
1184 if ( inputState.guessing==0 ) {
1185 qid_AST.setText("super."+qid_AST.getText());
1186 }
1187 argList();
1188 astFactory.addASTChild(currentAST, returnAST);
1189 namedTemplate_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
1190 break;
1191 }
1192 case LPAREN:
1193 {
1194 indirectTemplate();
1195 astFactory.addASTChild(currentAST, returnAST);
1196 namedTemplate_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
1197 break;
1198 }
1199 default:
1200 {
1201 throw new NoViableAltException(LT(1), getFilename());
1202 }
1203 }
1204 }
1205 catch (RecognitionException ex) {
1206 if (inputState.guessing==0) {
1207 reportError(ex);
1208 recover(ex,_tokenSet_8);
1209 } else {
1210 throw ex;
1211 }
1212 }
1213 returnAST = namedTemplate_AST;
1214 }
1215
1216 public final void argList() throws RecognitionException, TokenStreamException {
1217
1218 returnAST = null;
1219 ASTPair currentAST = new ASTPair();
1220 org.antlr.stringtemplate.language.StringTemplateAST argList_AST = null;
1221
1222 try { // for error handling
1223 if ((LA(1)==LPAREN) && (LA(2)==RPAREN)) {
1224 match(LPAREN);
1225 match(RPAREN);
1226 if ( inputState.guessing==0 ) {
1227 argList_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
1228 argList_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(ARGS,"ARGS");
1229 currentAST.root = argList_AST;
1230 currentAST.child = argList_AST!=null &&argList_AST.getFirstChild()!=null ?
1231 argList_AST.getFirstChild() : argList_AST;
1232 currentAST.advanceChildToEnd();
1233 }
1234 }
1235 else {
1236 boolean synPredMatched52 = false;
1237 if (((LA(1)==LPAREN) && (_tokenSet_1.member(LA(2))))) {
1238 int _m52 = mark();
1239 synPredMatched52 = true;
1240 inputState.guessing++;
1241 try {
1242 {
1243 singleArg();
1244 }
1245 }
1246 catch (RecognitionException pe) {
1247 synPredMatched52 = false;
1248 }
1249 rewind(_m52);
1250 inputState.guessing--;
1251 }
1252 if ( synPredMatched52 ) {
1253 singleArg();
1254 astFactory.addASTChild(currentAST, returnAST);
1255 argList_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
1256 }
1257 else if ((LA(1)==LPAREN) && (LA(2)==ID||LA(2)==DOTDOTDOT)) {
1258 match(LPAREN);
1259 argumentAssignment();
1260 astFactory.addASTChild(currentAST, returnAST);
1261 {
1262 _loop54:
1263 do {
1264 if ((LA(1)==COMMA)) {
1265 match(COMMA);
1266 argumentAssignment();
1267 astFactory.addASTChild(currentAST, returnAST);
1268 }
1269 else {
1270 break _loop54;
1271 }
1272
1273 } while (true);
1274 }
1275 match(RPAREN);
1276 if ( inputState.guessing==0 ) {
1277 argList_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
1278 argList_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.make( (new ASTArray(2)).add((org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(ARGS,"ARGS")).add(argList_AST));
1279 currentAST.root = argList_AST;
1280 currentAST.child = argList_AST!=null &&argList_AST.getFirstChild()!=null ?
1281 argList_AST.getFirstChild() : argList_AST;
1282 currentAST.advanceChildToEnd();
1283 }
1284 argList_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
1285 }
1286 else {
1287 throw new NoViableAltException(LT(1), getFilename());
1288 }
1289 }
1290 }
1291 catch (RecognitionException ex) {
1292 if (inputState.guessing==0) {
1293 reportError(ex);
1294 recover(ex,_tokenSet_12);
1295 } else {
1296 throw ex;
1297 }
1298 }
1299 returnAST = argList_AST;
1300 }
1301
1302 /** Match (foo)() and (foo+".terse")() */
1303 public final void indirectTemplate() throws RecognitionException, TokenStreamException {
1304
1305 returnAST = null;
1306 ASTPair currentAST = new ASTPair();
1307 org.antlr.stringtemplate.language.StringTemplateAST indirectTemplate_AST = null;
1308 org.antlr.stringtemplate.language.StringTemplateAST e_AST = null;
1309 org.antlr.stringtemplate.language.StringTemplateAST args_AST = null;
1310
1311 try { // for error handling
1312 org.antlr.stringtemplate.language.StringTemplateAST tmp43_AST = null;
1313 tmp43_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
1314 match(LPAREN);
1315 templatesExpr();
1316 e_AST = (org.antlr.stringtemplate.language.StringTemplateAST)returnAST;
1317 org.antlr.stringtemplate.language.StringTemplateAST tmp44_AST = null;
1318 tmp44_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
1319 match(RPAREN);
1320 argList();
1321 args_AST = (org.antlr.stringtemplate.language.StringTemplateAST)returnAST;
1322 if ( inputState.guessing==0 ) {
1323 indirectTemplate_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
1324 indirectTemplate_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.make( (new ASTArray(3)).add((org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(VALUE,"value")).add(e_AST).add(args_AST));
1325 currentAST.root = indirectTemplate_AST;
1326 currentAST.child = indirectTemplate_AST!=null &&indirectTemplate_AST.getFirstChild()!=null ?
1327 indirectTemplate_AST.getFirstChild() : indirectTemplate_AST;
1328 currentAST.advanceChildToEnd();
1329 }
1330 }
1331 catch (RecognitionException ex) {
1332 if (inputState.guessing==0) {
1333 reportError(ex);
1334 recover(ex,_tokenSet_12);
1335 } else {
1336 throw ex;
1337 }
1338 }
1339 returnAST = indirectTemplate_AST;
1340 }
1341
1342 public final void listElement() throws RecognitionException, TokenStreamException {
1343
1344 returnAST = null;
1345 ASTPair currentAST = new ASTPair();
1346 org.antlr.stringtemplate.language.StringTemplateAST listElement_AST = null;
1347
1348 try { // for error handling
1349 switch ( LA(1)) {
1350 case LPAREN:
1351 case ID:
1352 case LITERAL_first:
1353 case LITERAL_rest:
1354 case LITERAL_last:
1355 case LITERAL_length:
1356 case LITERAL_strip:
1357 case LITERAL_trunc:
1358 case LITERAL_super:
1359 case ANONYMOUS_TEMPLATE:
1360 case STRING:
1361 case INT:
1362 case LBRACK:
1363 {
1364 nonAlternatingTemplateExpr();
1365 astFactory.addASTChild(currentAST, returnAST);
1366 listElement_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
1367 break;
1368 }
1369 case COMMA:
1370 case RBRACK:
1371 {
1372 if ( inputState.guessing==0 ) {
1373 listElement_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
1374 listElement_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(NOTHING,"NOTHING");
1375 currentAST.root = listElement_AST;
1376 currentAST.child = listElement_AST!=null &&listElement_AST.getFirstChild()!=null ?
1377 listElement_AST.getFirstChild() : listElement_AST;
1378 currentAST.advanceChildToEnd();
1379 }
1380 listElement_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
1381 break;
1382 }
1383 default:
1384 {
1385 throw new NoViableAltException(LT(1), getFilename());
1386 }
1387 }
1388 }
1389 catch (RecognitionException ex) {
1390 if (inputState.guessing==0) {
1391 reportError(ex);
1392 recover(ex,_tokenSet_13);
1393 } else {
1394 throw ex;
1395 }
1396 }
1397 returnAST = listElement_AST;
1398 }
1399
1400 public final void argumentAssignment() throws RecognitionException, TokenStreamException {
1401
1402 returnAST = null;
1403 ASTPair currentAST = new ASTPair();
1404 org.antlr.stringtemplate.language.StringTemplateAST argumentAssignment_AST = null;
1405
1406 try { // for error handling
1407 switch ( LA(1)) {
1408 case ID:
1409 {
1410 org.antlr.stringtemplate.language.StringTemplateAST tmp45_AST = null;
1411 tmp45_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
1412 astFactory.addASTChild(currentAST, tmp45_AST);
1413 match(ID);
1414 org.antlr.stringtemplate.language.StringTemplateAST tmp46_AST = null;
1415 tmp46_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
1416 astFactory.makeASTRoot(currentAST, tmp46_AST);
1417 match(ASSIGN);
1418 nonAlternatingTemplateExpr();
1419 astFactory.addASTChild(currentAST, returnAST);
1420 argumentAssignment_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
1421 break;
1422 }
1423 case DOTDOTDOT:
1424 {
1425 org.antlr.stringtemplate.language.StringTemplateAST tmp47_AST = null;
1426 tmp47_AST = (org.antlr.stringtemplate.language.StringTemplateAST)astFactory.create(LT(1));
1427 astFactory.addASTChild(currentAST, tmp47_AST);
1428 match(DOTDOTDOT);
1429 argumentAssignment_AST = (org.antlr.stringtemplate.language.StringTemplateAST)currentAST.root;
1430 break;
1431 }
1432 default:
1433 {
1434 throw new NoViableAltException(LT(1), getFilename());
1435 }
1436 }
1437 }
1438 catch (RecognitionException ex) {
1439 if (inputState.guessing==0) {
1440 reportError(ex);
1441 recover(ex,_tokenSet_14);
1442 } else {
1443 throw ex;
1444 }
1445 }
1446 returnAST = argumentAssignment_AST;
1447 }
1448
1449
1450 public static final String[] _tokenNames = {
1451 "<0>",
1452 "EOF",
1453 "<2>",
1454 "NULL_TREE_LOOKAHEAD",
1455 "APPLY",
1456 "MULTI_APPLY",
1457 "ARGS",
1458 "INCLUDE",
1459 "\"if\"",
1460 "VALUE",
1461 "TEMPLATE",
1462 "FUNCTION",
1463 "SINGLEVALUEARG",
1464 "LIST",
1465 "NOTHING",
1466 "SEMI",
1467 "LPAREN",
1468 "RPAREN",
1469 "\"elseif\"",
1470 "COMMA",
1471 "ID",
1472 "ASSIGN",
1473 "COLON",
1474 "NOT",
1475 "PLUS",
1476 "DOT",
1477 "\"first\"",
1478 "\"rest\"",
1479 "\"last\"",
1480 "\"length\"",
1481 "\"strip\"",
1482 "\"trunc\"",
1483 "\"super\"",
1484 "ANONYMOUS_TEMPLATE",
1485 "STRING",
1486 "INT",
1487 "LBRACK",
1488 "RBRACK",
1489 "DOTDOTDOT",
1490 "TEMPLATE_ARGS",
1491 "NESTED_ANONYMOUS_TEMPLATE",
1492 "ESC_CHAR",
1493 "WS",
1494 "WS_CHAR"
1495 };
1496
1497 protected void buildTokenTypeASTClassMap() {
1498 tokenTypeToASTClassMap=null;
1499 };
1500
1501 private static final long[] mk_tokenSet_0() {
1502 long[] data = { 2L, 0L};
1503 return data;
1504 }
1505 public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0());
1506 private static final long[] mk_tokenSet_1() {
1507 long[] data = { 137372958720L, 0L};
1508 return data;
1509 }
1510 public static final BitSet _tokenSet_1 = new BitSet(mk_tokenSet_1());
1511 private static final long[] mk_tokenSet_2() {
1512 long[] data = { 274862768128L, 0L};
1513 return data;
1514 }
1515 public static final BitSet _tokenSet_2 = new BitSet(mk_tokenSet_2());
1516 private static final long[] mk_tokenSet_3() {
1517 long[] data = { 274867126274L, 0L};
1518 return data;
1519 }
1520 public static final BitSet _tokenSet_3 = new BitSet(mk_tokenSet_3());
1521 private static final long[] mk_tokenSet_4() {
1522 long[] data = { 163842L, 0L};
1523 return data;
1524 }
1525 public static final BitSet _tokenSet_4 = new BitSet(mk_tokenSet_4());
1526 private static final long[] mk_tokenSet_5() {
1527 long[] data = { 131072L, 0L};
1528 return data;
1529 }
1530 public static final BitSet _tokenSet_5 = new BitSet(mk_tokenSet_5());
1531 private static final long[] mk_tokenSet_6() {
1532 long[] data = { 524290L, 0L};
1533 return data;
1534 }
1535 public static final BitSet _tokenSet_6 = new BitSet(mk_tokenSet_6());
1536 private static final long[] mk_tokenSet_7() {
1537 long[] data = { 137439608834L, 0L};
1538 return data;
1539 }
1540 public static final BitSet _tokenSet_7 = new BitSet(mk_tokenSet_7());
1541 private static final long[] mk_tokenSet_8() {
1542 long[] data = { 137443835906L, 0L};
1543 return data;
1544 }
1545 public static final BitSet _tokenSet_8 = new BitSet(mk_tokenSet_8());
1546 private static final long[] mk_tokenSet_9() {
1547 long[] data = { 137406513152L, 0L};
1548 return data;
1549 }
1550 public static final BitSet _tokenSet_9 = new BitSet(mk_tokenSet_9());
1551 private static final long[] mk_tokenSet_10() {
1552 long[] data = { 60130590720L, 0L};
1553 return data;
1554 }
1555 public static final BitSet _tokenSet_10 = new BitSet(mk_tokenSet_10());
1556 private static final long[] mk_tokenSet_11() {
1557 long[] data = { 137494167554L, 0L};
1558 return data;
1559 }
1560 public static final BitSet _tokenSet_11 = new BitSet(mk_tokenSet_11());
1561 private static final long[] mk_tokenSet_12() {
1562 long[] data = { 137460613122L, 0L};
1563 return data;
1564 }
1565 public static final BitSet _tokenSet_12 = new BitSet(mk_tokenSet_12());
1566 private static final long[] mk_tokenSet_13() {
1567 long[] data = { 137439477760L, 0L};
1568 return data;
1569 }
1570 public static final BitSet _tokenSet_13 = new BitSet(mk_tokenSet_13());
1571 private static final long[] mk_tokenSet_14() {
1572 long[] data = { 655360L, 0L};
1573 return data;
1574 }
1575 public static final BitSet _tokenSet_14 = new BitSet(mk_tokenSet_14());
1576
1577 }
0 SMAP
1 ActionParser.java
2 G
3 *S G
4 *F
5 + 0 action.g
6 action.g
7 *L
8 1:3
9 1:4
10 1:5
11 1:6
12 1:8
13 1:9
14 1:10
15 1:11
16 1:12
17 1:13
18 1:14
19 1:15
20 1:16
21 1:17
22 1:19
23 1:20
24 1:21
25 1:22
26 1:23
27 1:24
28 1:25
29 1:26
30 1:27
31 1:28
32 1:29
33 1:30
34 1:31
35 1:32
36 57:57
37 59:59
38 60:60
39 61:61
40 62:62
41 64:64
42 65:65
43 66:66
44 67:67
45 68:68
46 69:69
47 70:70
48 71:71
49 72:72
50 75:103
51 75:104
52 75:106
53 75:107
54 75:108
55 75:110
56 75:111
57 75:173
58 75:174
59 75:175
60 75:176
61 75:177
62 75:178
63 75:179
64 75:180
65 75:181
66 75:182
67 75:183
68 75:184
69 75:185
70 75:186
71 75:187
72 75:188
73 75:189
74 76:112
75 76:113
76 76:114
77 76:115
78 76:116
79 76:117
80 76:118
81 76:119
82 76:120
83 76:121
84 76:122
85 76:123
86 76:124
87 76:125
88 76:126
89 76:127
90 76:129
91 76:130
92 76:131
93 76:132
94 76:133
95 76:134
96 76:141
97 76:142
98 76:143
99 76:144
100 76:145
101 77:147
102 77:150
103 77:151
104 77:152
105 77:153
106 77:154
107 77:155
108 77:156
109 77:157
110 77:158
111 77:159
112 78:163
113 78:164
114 78:165
115 78:166
116 78:167
117 78:168
118 78:169
119 79:160
120 80:170
121 81:276
122 81:277
123 81:279
124 81:280
125 81:281
126 81:283
127 81:300
128 81:301
129 81:302
130 81:303
131 81:304
132 81:305
133 81:306
134 81:307
135 81:308
136 81:309
137 81:310
138 81:311
139 82:284
140 82:285
141 82:286
142 82:287
143 82:288
144 82:289
145 82:290
146 82:291
147 82:292
148 82:293
149 82:294
150 82:295
151 82:296
152 82:298
153 82:299
154 85:368
155 85:369
156 85:370
157 85:372
158 85:373
159 85:374
160 85:382
161 85:421
162 85:422
163 85:423
164 85:424
165 85:425
166 85:426
167 85:427
168 85:428
169 85:429
170 85:430
171 85:431
172 86:379
173 89:375
174 89:376
175 89:383
176 89:384
177 89:385
178 89:386
179 90:377
180 90:388
181 90:389
182 90:390
183 90:391
184 90:392
185 90:393
186 90:394
187 90:395
188 90:396
189 90:397
190 90:398
191 90:399
192 90:411
193 90:412
194 90:413
195 90:414
196 90:415
197 91:403
198 91:404
199 91:405
200 91:406
201 91:407
202 93:417
203 93:418
204 96:191
205 96:193
206 96:194
207 96:195
208 96:199
209 96:220
210 96:259
211 96:260
212 96:261
213 96:262
214 96:264
215 96:265
216 96:266
217 96:267
218 96:268
219 96:269
220 96:270
221 96:271
222 96:272
223 96:273
224 96:274
225 96:420
226 97:200
227 97:201
228 97:202
229 97:203
230 97:204
231 97:205
232 97:207
233 97:209
234 97:210
235 97:211
236 97:212
237 97:213
238 97:214
239 97:215
240 97:216
241 97:217
242 97:218
243 97:219
244 98:221
245 98:222
246 98:223
247 99:196
248 99:197
249 99:224
250 99:225
251 99:226
252 99:227
253 99:228
254 99:229
255 99:230
256 99:231
257 99:232
258 99:233
259 99:235
260 99:236
261 99:237
262 99:238
263 99:239
264 99:240
265 99:241
266 99:242
267 99:243
268 99:244
269 99:245
270 99:246
271 99:247
272 99:249
273 99:250
274 99:251
275 99:252
276 99:253
277 99:254
278 99:256
279 99:257
280 99:258
281 103:477
282 103:479
283 103:480
284 103:481
285 103:485
286 103:520
287 103:521
288 103:522
289 103:523
290 103:524
291 103:525
292 103:526
293 103:527
294 103:528
295 103:529
296 103:530
297 104:482
298 104:483
299 104:486
300 104:487
301 104:489
302 104:490
303 104:491
304 104:492
305 104:493
306 104:494
307 104:495
308 104:496
309 104:497
310 104:498
311 104:499
312 104:501
313 104:502
314 104:503
315 104:504
316 104:505
317 104:506
318 104:507
319 104:508
320 104:509
321 105:510
322 105:511
323 105:512
324 105:514
325 105:516
326 105:517
327 106:513
328 106:519
329 109:313
330 109:315
331 109:316
332 109:317
333 109:319
334 109:320
335 109:351
336 109:352
337 109:353
338 109:354
339 109:355
340 109:356
341 109:357
342 109:358
343 109:359
344 109:360
345 109:361
346 109:362
347 109:363
348 109:364
349 109:365
350 109:366
351 110:321
352 110:322
353 110:323
354 110:324
355 110:325
356 110:326
357 110:327
358 110:328
359 110:329
360 110:330
361 110:331
362 110:332
363 110:333
364 110:334
365 110:335
366 110:336
367 110:337
368 111:340
369 111:341
370 111:342
371 111:343
372 111:344
373 111:345
374 111:346
375 111:347
376 111:348
377 114:657
378 114:659
379 114:660
380 114:661
381 114:663
382 114:667
383 114:668
384 114:669
385 114:670
386 114:671
387 114:672
388 114:673
389 114:674
390 114:675
391 114:676
392 114:677
393 115:664
394 115:665
395 115:666
396 118:532
397 118:534
398 118:535
399 118:536
400 118:538
401 118:539
402 118:540
403 118:541
404 118:542
405 118:543
406 118:544
407 118:545
408 118:546
409 118:547
410 118:548
411 118:549
412 118:550
413 118:551
414 118:552
415 118:553
416 118:554
417 118:556
418 118:557
419 118:558
420 118:559
421 118:560
422 118:561
423 118:562
424 118:563
425 118:564
426 118:565
427 118:566
428 118:567
429 118:568
430 118:569
431 121:679
432 121:681
433 121:682
434 121:683
435 121:685
436 121:686
437 121:743
438 121:764
439 121:806
440 121:811
441 121:812
442 121:813
443 121:814
444 121:815
445 121:816
446 121:817
447 121:818
448 121:819
449 121:820
450 121:821
451 121:822
452 121:823
453 121:824
454 121:825
455 121:826
456 122:744
457 122:745
458 122:746
459 122:747
460 122:748
461 122:749
462 122:751
463 122:753
464 122:754
465 122:755
466 122:756
467 122:757
468 122:758
469 122:759
470 122:760
471 122:761
472 122:762
473 122:763
474 123:765
475 123:766
476 123:767
477 124:768
478 124:769
479 124:770
480 124:771
481 124:772
482 124:773
483 124:774
484 124:775
485 124:798
486 124:799
487 124:800
488 124:801
489 124:803
490 124:804
491 124:805
492 125:777
493 125:778
494 125:779
495 125:780
496 125:781
497 125:782
498 125:783
499 125:792
500 125:793
501 125:794
502 125:795
503 125:796
504 126:786
505 126:787
506 126:788
507 126:789
508 129:687
509 129:688
510 129:689
511 129:690
512 129:691
513 129:692
514 129:693
515 129:694
516 129:695
517 130:696
518 130:697
519 130:698
520 130:699
521 130:700
522 130:701
523 130:702
524 130:703
525 130:726
526 130:727
527 130:728
528 130:729
529 130:731
530 130:732
531 130:733
532 131:705
533 131:706
534 131:707
535 131:708
536 131:709
537 131:710
538 131:711
539 131:720
540 131:721
541 131:722
542 131:723
543 131:724
544 132:714
545 132:715
546 132:716
547 132:717
548 135:807
549 135:808
550 135:809
551 135:810
552 136:736
553 136:737
554 136:738
555 136:739
556 136:740
557 139:960
558 139:962
559 139:963
560 139:964
561 139:968
562 139:980
563 139:981
564 139:982
565 139:983
566 139:984
567 139:985
568 139:986
569 139:987
570 139:988
571 139:989
572 139:990
573 140:965
574 140:966
575 140:969
576 140:970
577 140:971
578 140:972
579 140:973
580 140:974
581 140:975
582 141:976
583 141:977
584 144:433
585 144:435
586 144:436
587 144:437
588 144:441
589 144:465
590 144:466
591 144:467
592 144:468
593 144:469
594 144:470
595 144:471
596 144:472
597 144:473
598 144:474
599 144:475
600 144:979
601 145:438
602 145:439
603 145:442
604 145:443
605 145:444
606 145:445
607 145:446
608 145:447
609 145:448
610 145:449
611 145:450
612 145:451
613 145:452
614 145:453
615 145:455
616 145:456
617 145:457
618 145:458
619 145:459
620 145:460
621 145:462
622 145:463
623 145:464
624 148:992
625 148:994
626 148:995
627 148:996
628 148:998
629 148:1066
630 148:1067
631 148:1068
632 148:1069
633 148:1070
634 148:1071
635 148:1072
636 148:1073
637 148:1074
638 148:1075
639 148:1076
640 149:1000
641 149:1001
642 149:1002
643 149:1003
644 149:1004
645 149:1005
646 149:1006
647 149:1049
648 149:1050
649 149:1051
650 149:1052
651 149:1053
652 150:1009
653 150:1010
654 150:1011
655 150:1012
656 150:1013
657 150:1014
658 151:1017
659 151:1018
660 151:1019
661 151:1020
662 151:1021
663 151:1022
664 152:1025
665 152:1026
666 152:1027
667 152:1028
668 152:1029
669 152:1030
670 153:1033
671 153:1034
672 153:1035
673 153:1036
674 153:1037
675 153:1038
676 154:1041
677 154:1042
678 154:1043
679 154:1044
680 154:1045
681 154:1046
682 156:1055
683 156:1056
684 157:1057
685 157:1058
686 157:1059
687 157:1060
688 157:1062
689 157:1063
690 158:1065
691 160:571
692 160:573
693 160:574
694 160:575
695 160:577
696 160:609
697 160:610
698 160:611
699 160:612
700 160:613
701 160:614
702 160:615
703 160:616
704 160:617
705 160:618
706 160:619
707 161:579
708 161:580
709 161:581
710 161:582
711 161:583
712 161:584
713 161:585
714 161:594
715 161:595
716 161:596
717 161:597
718 161:598
719 162:588
720 162:589
721 162:590
722 162:591
723 164:600
724 164:601
725 164:602
726 164:603
727 164:605
728 164:606
729 165:608
730 167:1156
731 167:1158
732 167:1159
733 167:1160
734 167:1164
735 167:1165
736 167:1200
737 167:1201
738 167:1202
739 167:1203
740 167:1204
741 167:1205
742 167:1206
743 167:1207
744 167:1208
745 167:1209
746 167:1210
747 167:1211
748 167:1212
749 167:1213
750 167:1214
751 167:1215
752 168:1166
753 168:1167
754 168:1168
755 168:1169
756 168:1170
757 168:1171
758 168:1172
759 168:1173
760 168:1174
761 169:1161
762 169:1162
763 169:1177
764 169:1178
765 169:1179
766 169:1180
767 169:1181
768 169:1182
769 169:1183
770 169:1184
771 169:1185
772 169:1186
773 169:1188
774 169:1189
775 169:1190
776 170:1193
777 170:1194
778 170:1195
779 170:1196
780 170:1197
781 173:621
782 173:623
783 173:624
784 173:625
785 173:629
786 173:645
787 173:646
788 173:647
789 173:648
790 173:649
791 173:650
792 173:651
793 173:652
794 173:653
795 173:654
796 173:655
797 174:626
798 174:627
799 174:630
800 174:631
801 174:632
802 174:633
803 175:634
804 176:636
805 177:637
806 178:638
807 179:639
808 180:640
809 181:641
810 185:644
811 185:899
812 185:901
813 185:902
814 185:903
815 185:905
816 185:906
817 185:907
818 185:908
819 185:909
820 185:910
821 185:911
822 185:912
823 185:943
824 185:944
825 185:945
826 185:946
827 185:947
828 185:948
829 185:949
830 185:950
831 185:951
832 185:952
833 185:953
834 185:954
835 185:955
836 185:956
837 185:957
838 185:958
839 186:916
840 186:917
841 186:918
842 186:919
843 186:920
844 186:921
845 187:913
846 187:925
847 187:926
848 187:927
849 187:928
850 187:929
851 187:930
852 188:922
853 188:934
854 188:935
855 188:936
856 188:937
857 188:938
858 188:939
859 189:931
860 190:940
861 191:1078
862 191:1080
863 191:1081
864 191:1082
865 191:1083
866 191:1084
867 191:1086
868 191:1087
869 191:1088
870 191:1089
871 191:1090
872 191:1091
873 191:1092
874 191:1112
875 191:1113
876 191:1114
877 191:1115
878 191:1116
879 191:1117
880 191:1118
881 191:1119
882 191:1120
883 191:1121
884 191:1122
885 192:1094
886 192:1095
887 192:1096
888 192:1097
889 192:1098
890 192:1099
891 192:1100
892 192:1101
893 192:1102
894 192:1103
895 192:1104
896 192:1105
897 192:1106
898 192:1108
899 192:1109
900 193:1110
901 195:1111
902 196:1343
903 196:1345
904 196:1346
905 196:1347
906 196:1349
907 196:1350
908 196:1384
909 196:1385
910 196:1386
911 196:1387
912 196:1388
913 196:1389
914 196:1390
915 196:1391
916 196:1392
917 196:1393
918 196:1394
919 196:1395
920 196:1396
921 196:1397
922 196:1398
923 196:1399
924 197:1351
925 197:1352
926 197:1353
927 197:1354
928 197:1355
929 197:1356
930 197:1357
931 197:1358
932 197:1359
933 197:1360
934 197:1361
935 197:1362
936 197:1363
937 197:1364
938 197:1365
939 197:1366
940 197:1367
941 198:1370
942 198:1371
943 198:1372
944 198:1373
945 198:1374
946 198:1375
947 198:1376
948 198:1378
949 198:1379
950 199:1381
951 201:828
952 201:830
953 201:831
954 201:832
955 201:838
956 201:887
957 201:888
958 201:889
959 201:890
960 201:891
961 201:892
962 201:893
963 201:894
964 201:895
965 201:896
966 201:897
967 202:833
968 202:834
969 202:840
970 202:841
971 202:842
972 202:843
973 202:844
974 202:845
975 202:846
976 202:847
977 202:848
978 202:872
979 202:873
980 202:874
981 202:875
982 202:876
983 203:835
984 203:836
985 203:851
986 203:852
987 203:853
988 203:854
989 203:855
990 203:856
991 203:857
992 203:858
993 203:859
994 203:860
995 203:862
996 203:863
997 204:866
998 204:867
999 204:868
1000 204:869
1001 206:878
1002 206:879
1003 206:880
1004 206:881
1005 206:883
1006 206:884
1007 207:886
1008 210:1303
1009 210:1304
1010 210:1306
1011 210:1307
1012 210:1308
1013 210:1312
1014 210:1331
1015 210:1332
1016 210:1333
1017 210:1334
1018 210:1335
1019 210:1336
1020 210:1337
1021 210:1338
1022 210:1339
1023 210:1340
1024 210:1341
1025 211:1309
1026 211:1310
1027 211:1313
1028 211:1314
1029 211:1315
1030 211:1316
1031 211:1317
1032 211:1318
1033 211:1319
1034 211:1320
1035 211:1321
1036 211:1322
1037 212:1323
1038 212:1324
1039 212:1325
1040 212:1326
1041 212:1328
1042 212:1329
1043 215:1217
1044 215:1219
1045 215:1220
1046 215:1221
1047 215:1223
1048 215:1235
1049 215:1257
1050 215:1286
1051 215:1287
1052 215:1288
1053 215:1289
1054 215:1290
1055 215:1291
1056 215:1292
1057 215:1293
1058 215:1294
1059 215:1295
1060 215:1296
1061 215:1297
1062 215:1298
1063 215:1299
1064 215:1300
1065 215:1301
1066 216:1224
1067 216:1225
1068 216:1226
1069 216:1227
1070 216:1228
1071 216:1229
1072 216:1230
1073 216:1232
1074 216:1233
1075 217:1236
1076 217:1237
1077 217:1238
1078 217:1239
1079 217:1240
1080 217:1241
1081 217:1242
1082 217:1244
1083 217:1246
1084 217:1247
1085 217:1248
1086 217:1249
1087 217:1250
1088 217:1251
1089 217:1252
1090 217:1253
1091 217:1254
1092 217:1255
1093 217:1256
1094 218:1258
1095 218:1259
1096 218:1260
1097 218:1261
1098 218:1262
1099 218:1263
1100 218:1264
1101 218:1265
1102 218:1266
1103 218:1267
1104 218:1268
1105 218:1269
1106 218:1270
1107 218:1271
1108 218:1272
1109 218:1274
1110 218:1275
1111 218:1276
1112 219:1277
1113 219:1278
1114 219:1279
1115 219:1280
1116 219:1282
1117 219:1283
1118 220:1285
1119 222:1124
1120 222:1126
1121 222:1127
1122 222:1128
1123 222:1130
1124 222:1144
1125 222:1145
1126 222:1146
1127 222:1147
1128 222:1148
1129 222:1149
1130 222:1150
1131 222:1151
1132 222:1152
1133 222:1153
1134 222:1154
1135 223:1131
1136 223:1132
1137 223:1133
1138 223:1134
1139 224:1135
1140 224:1136
1141 224:1137
1142 224:1138
1143 224:1140
1144 224:1141
1145 225:1143
1146 227:1401
1147 227:1403
1148 227:1404
1149 227:1405
1150 227:1407
1151 227:1408
1152 227:1433
1153 227:1434
1154 227:1435
1155 227:1436
1156 227:1437
1157 227:1438
1158 227:1439
1159 227:1440
1160 227:1441
1161 227:1442
1162 227:1443
1163 227:1444
1164 227:1445
1165 227:1446
1166 227:1447
1167 227:1448
1168 228:1409
1169 228:1410
1170 228:1411
1171 228:1412
1172 228:1413
1173 228:1414
1174 228:1415
1175 228:1416
1176 228:1417
1177 228:1418
1178 228:1419
1179 228:1420
1180 228:1421
1181 229:1424
1182 229:1425
1183 229:1426
1184 229:1427
1185 229:1428
1186 229:1429
1187 231:1430
1188 *E
0 // $ANTLR 2.7.7 (20060906): "action.g" -> "ActionParser.java"$
1
2 /*
3 [The "BSD licence"]
4 Copyright (c) 2003-2004 Terence Parr
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 package org.antlr.stringtemplate.language;
30 import org.antlr.stringtemplate.*;
31 import java.util.*;
32
33 public interface ActionParserTokenTypes {
34 int EOF = 1;
35 int NULL_TREE_LOOKAHEAD = 3;
36 int APPLY = 4;
37 int MULTI_APPLY = 5;
38 int ARGS = 6;
39 int INCLUDE = 7;
40 int CONDITIONAL = 8;
41 int VALUE = 9;
42 int TEMPLATE = 10;
43 int FUNCTION = 11;
44 int SINGLEVALUEARG = 12;
45 int LIST = 13;
46 int NOTHING = 14;
47 int SEMI = 15;
48 int LPAREN = 16;
49 int RPAREN = 17;
50 int LITERAL_elseif = 18;
51 int COMMA = 19;
52 int ID = 20;
53 int ASSIGN = 21;
54 int COLON = 22;
55 int NOT = 23;
56 int PLUS = 24;
57 int DOT = 25;
58 int LITERAL_first = 26;
59 int LITERAL_rest = 27;
60 int LITERAL_last = 28;
61 int LITERAL_length = 29;
62 int LITERAL_strip = 30;
63 int LITERAL_trunc = 31;
64 int LITERAL_super = 32;
65 int ANONYMOUS_TEMPLATE = 33;
66 int STRING = 34;
67 int INT = 35;
68 int LBRACK = 36;
69 int RBRACK = 37;
70 int DOTDOTDOT = 38;
71 int TEMPLATE_ARGS = 39;
72 int NESTED_ANONYMOUS_TEMPLATE = 40;
73 int ESC_CHAR = 41;
74 int WS = 42;
75 int WS_CHAR = 43;
76 }
0 // $ANTLR 2.7.7 (20060906): action.g -> ActionParserTokenTypes.txt$
1 ActionParser // output token vocab name
2 APPLY=4
3 MULTI_APPLY=5
4 ARGS=6
5 INCLUDE=7
6 CONDITIONAL="if"=8
7 VALUE=9
8 TEMPLATE=10
9 FUNCTION=11
10 SINGLEVALUEARG=12
11 LIST=13
12 NOTHING=14
13 SEMI=15
14 LPAREN=16
15 RPAREN=17
16 LITERAL_elseif="elseif"=18
17 COMMA=19
18 ID=20
19 ASSIGN=21
20 COLON=22
21 NOT=23
22 PLUS=24
23 DOT=25
24 LITERAL_first="first"=26
25 LITERAL_rest="rest"=27
26 LITERAL_last="last"=28
27 LITERAL_length="length"=29
28 LITERAL_strip="strip"=30
29 LITERAL_trunc="trunc"=31
30 LITERAL_super="super"=32
31 ANONYMOUS_TEMPLATE=33
32 STRING=34
33 INT=35
34 LBRACK=36
35 RBRACK=37
36 DOTDOTDOT=38
37 TEMPLATE_ARGS=39
38 NESTED_ANONYMOUS_TEMPLATE=40
39 ESC_CHAR=41
40 WS=42
41 WS_CHAR=43
0 // $ANTLR 2.7.7 (20060906): "angle.bracket.template.g" -> "AngleBracketTemplateLexer.java"$
1
2 /*
3 [The "BSD licence"]
4 Copyright (c) 2003-2004 Terence Parr
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 package org.antlr.stringtemplate.language;
30 import org.antlr.stringtemplate.*;
31 import java.io.*;
32
33 import java.io.InputStream;
34 import antlr.TokenStreamException;
35 import antlr.TokenStreamIOException;
36 import antlr.TokenStreamRecognitionException;
37 import antlr.CharStreamException;
38 import antlr.CharStreamIOException;
39 import antlr.ANTLRException;
40 import java.io.Reader;
41 import java.util.Hashtable;
42 import antlr.CharScanner;
43 import antlr.InputBuffer;
44 import antlr.ByteBuffer;
45 import antlr.CharBuffer;
46 import antlr.Token;
47 import antlr.CommonToken;
48 import antlr.RecognitionException;
49 import antlr.NoViableAltForCharException;
50 import antlr.MismatchedCharException;
51 import antlr.TokenStream;
52 import antlr.ANTLRHashString;
53 import antlr.LexerSharedInputState;
54 import antlr.collections.impl.BitSet;
55 import antlr.SemanticException;
56
57 /** Break up an input text stream into chunks of either plain text
58 * or template actions in "<...>". Treat IF and ENDIF tokens
59 * specially.
60 */
61 public class AngleBracketTemplateLexer extends antlr.CharScanner implements AngleBracketTemplateLexerTokenTypes, TokenStream
62 {
63
64 protected String currentIndent = null;
65 protected StringTemplate self;
66
67 public AngleBracketTemplateLexer(StringTemplate self, Reader r) {
68 this(r);
69 this.self = self;
70 }
71
72 public void reportError(RecognitionException e) {
73 self.error("<...> chunk lexer error", e);
74 }
75
76 protected boolean upcomingELSE(int i) throws CharStreamException {
77 return LA(i)=='<'&&LA(i+1)=='e'&&LA(i+2)=='l'&&LA(i+3)=='s'&&LA(i+4)=='e'&&
78 LA(i+5)=='>';
79 }
80
81 protected boolean upcomingENDIF(int i) throws CharStreamException {
82 return LA(i)=='<'&&LA(i+1)=='e'&&LA(i+2)=='n'&&LA(i+3)=='d'&&LA(i+4)=='i'&&
83 LA(i+5)=='f'&&LA(i+6)=='>';
84 }
85
86 protected boolean upcomingAtEND(int i) throws CharStreamException {
87 return LA(i)=='<'&&LA(i+1)=='@'&&LA(i+2)=='e'&&LA(i+3)=='n'&&LA(i+4)=='d'&&LA(i+5)=='>';
88 }
89
90 protected boolean upcomingNewline(int i) throws CharStreamException {
91 return (LA(i)=='\r'&&LA(i+1)=='\n')||LA(i)=='\n';
92 }
93 public AngleBracketTemplateLexer(InputStream in) {
94 this(new ByteBuffer(in));
95 }
96 public AngleBracketTemplateLexer(Reader in) {
97 this(new CharBuffer(in));
98 }
99 public AngleBracketTemplateLexer(InputBuffer ib) {
100 this(new LexerSharedInputState(ib));
101 }
102 public AngleBracketTemplateLexer(LexerSharedInputState state) {
103 super(state);
104 caseSensitiveLiterals = true;
105 setCaseSensitive(true);
106 literals = new Hashtable();
107 }
108
109 public Token nextToken() throws TokenStreamException {
110 Token theRetToken=null;
111 tryAgain:
112 for (;;) {
113 Token _token = null;
114 int _ttype = Token.INVALID_TYPE;
115 resetText();
116 try { // for char stream error handling
117 try { // for lexical error handling
118 switch ( LA(1)) {
119 case '\n': case '\r':
120 {
121 mNEWLINE(true);
122 theRetToken=_returnToken;
123 break;
124 }
125 case '<':
126 {
127 mACTION(true);
128 theRetToken=_returnToken;
129 break;
130 }
131 default:
132 if (((_tokenSet_0.member(LA(1))))&&(LA(1)!='\r'&&LA(1)!='\n')) {
133 mLITERAL(true);
134 theRetToken=_returnToken;
135 }
136 else {
137 if (LA(1)==EOF_CHAR) {uponEOF(); _returnToken = makeToken(Token.EOF_TYPE);}
138 else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
139 }
140 }
141 if ( _returnToken==null ) continue tryAgain; // found SKIP token
142 _ttype = _returnToken.getType();
143 _ttype = testLiteralsTable(_ttype);
144 _returnToken.setType(_ttype);
145 return _returnToken;
146 }
147 catch (RecognitionException e) {
148 throw new TokenStreamRecognitionException(e);
149 }
150 }
151 catch (CharStreamException cse) {
152 if ( cse instanceof CharStreamIOException ) {
153 throw new TokenStreamIOException(((CharStreamIOException)cse).io);
154 }
155 else {
156 throw new TokenStreamException(cse.getMessage());
157 }
158 }
159 }
160 }
161
162 public final void mLITERAL(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
163 int _ttype; Token _token=null; int _begin=text.length();
164 _ttype = LITERAL;
165 int _saveIndex;
166 Token ind=null;
167
168 if (!(LA(1)!='\r'&&LA(1)!='\n'))
169 throw new SemanticException("LA(1)!='\\r'&&LA(1)!='\\n'");
170 {
171 int _cnt5=0;
172 _loop5:
173 do {
174
175 int loopStartIndex=text.length();
176 int col=getColumn();
177
178 if ((LA(1)=='\\') && (LA(2)=='<')) {
179 _saveIndex=text.length();
180 match('\\');
181 text.setLength(_saveIndex);
182 match('<');
183 }
184 else if ((LA(1)=='\\') && (LA(2)=='>') && (true) && (true) && (true) && (true) && (true)) {
185 _saveIndex=text.length();
186 match('\\');
187 text.setLength(_saveIndex);
188 match('>');
189 }
190 else if ((LA(1)=='\\') && (LA(2)=='\\') && (true) && (true) && (true) && (true) && (true)) {
191 _saveIndex=text.length();
192 match('\\');
193 text.setLength(_saveIndex);
194 match('\\');
195 }
196 else if ((LA(1)=='\\') && (_tokenSet_1.member(LA(2))) && (true) && (true) && (true) && (true) && (true)) {
197 match('\\');
198 {
199 match(_tokenSet_1);
200 }
201 }
202 else if ((LA(1)=='\t'||LA(1)==' ') && (true) && (true) && (true) && (true) && (true) && (true)) {
203 mINDENT(true);
204 ind=_returnToken;
205
206 if ( col==1 && LA(1)=='<' ) {
207 // store indent in ASTExpr not in a literal
208 currentIndent=ind.getText();
209 text.setLength(loopStartIndex); // reset length to wack text
210 }
211 else currentIndent=null;
212
213 }
214 else if ((_tokenSet_0.member(LA(1))) && (true) && (true) && (true) && (true) && (true) && (true)) {
215 {
216 match(_tokenSet_0);
217 }
218 }
219 else {
220 if ( _cnt5>=1 ) { break _loop5; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
221 }
222
223 _cnt5++;
224 } while (true);
225 }
226 if ((new String(text.getBuffer(),_begin,text.length()-_begin)).length()==0) {_ttype = Token.SKIP;}
227 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
228 _token = makeToken(_ttype);
229 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
230 }
231 _returnToken = _token;
232 }
233
234 protected final void mINDENT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
235 int _ttype; Token _token=null; int _begin=text.length();
236 _ttype = INDENT;
237 int _saveIndex;
238
239 {
240 int _cnt8=0;
241 _loop8:
242 do {
243 if ((LA(1)==' ') && (true) && (true) && (true) && (true) && (true) && (true)) {
244 match(' ');
245 }
246 else if ((LA(1)=='\t') && (true) && (true) && (true) && (true) && (true) && (true)) {
247 match('\t');
248 }
249 else {
250 if ( _cnt8>=1 ) { break _loop8; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
251 }
252
253 _cnt8++;
254 } while (true);
255 }
256 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
257 _token = makeToken(_ttype);
258 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
259 }
260 _returnToken = _token;
261 }
262
263 public final void mNEWLINE(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
264 int _ttype; Token _token=null; int _begin=text.length();
265 _ttype = NEWLINE;
266 int _saveIndex;
267
268 {
269 switch ( LA(1)) {
270 case '\r':
271 {
272 match('\r');
273 break;
274 }
275 case '\n':
276 {
277 break;
278 }
279 default:
280 {
281 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
282 }
283 }
284 }
285 match('\n');
286 newline(); currentIndent=null;
287 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
288 _token = makeToken(_ttype);
289 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
290 }
291 _returnToken = _token;
292 }
293
294 public final void mACTION(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
295 int _ttype; Token _token=null; int _begin=text.length();
296 _ttype = ACTION;
297 int _saveIndex;
298
299 int startCol = getColumn();
300
301
302 if ((LA(1)=='<') && (LA(2)=='\\') && (LA(3)=='\\') && (LA(4)=='>') && (_tokenSet_2.member(LA(5))) && (true) && (true)) {
303 mLINE_BREAK(false);
304 _ttype = Token.SKIP;
305 }
306 else if ((LA(1)=='<') && (LA(2)=='\\') && (_tokenSet_3.member(LA(3))) && (_tokenSet_4.member(LA(4))) && (true) && (true) && (true)) {
307 StringBuffer buf = new StringBuffer(); char uc = '\u0000';
308 _saveIndex=text.length();
309 match('<');
310 text.setLength(_saveIndex);
311 {
312 int _cnt13=0;
313 _loop13:
314 do {
315 if ((LA(1)=='\\')) {
316 uc=mESC_CHAR(false);
317 buf.append(uc);
318 }
319 else {
320 if ( _cnt13>=1 ) { break _loop13; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
321 }
322
323 _cnt13++;
324 } while (true);
325 }
326 _saveIndex=text.length();
327 match('>');
328 text.setLength(_saveIndex);
329 text.setLength(_begin); text.append(buf.toString()); _ttype = LITERAL;
330 }
331 else if ((LA(1)=='<') && (LA(2)=='!') && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && ((LA(4) >= '\u0001' && LA(4) <= '\ufffe')) && (true) && (true) && (true)) {
332 mCOMMENT(false);
333 _ttype = Token.SKIP;
334 }
335 else if ((LA(1)=='<') && (_tokenSet_5.member(LA(2))) && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && (true) && (true) && (true) && (true)) {
336 {
337 if ((LA(1)=='<') && (LA(2)=='i') && (LA(3)=='f') && (LA(4)==' '||LA(4)=='(') && (_tokenSet_6.member(LA(5))) && ((LA(6) >= '\u0001' && LA(6) <= '\ufffe')) && ((LA(7) >= '\u0001' && LA(7) <= '\ufffe'))) {
338 _saveIndex=text.length();
339 match('<');
340 text.setLength(_saveIndex);
341 match("if");
342 {
343 _loop16:
344 do {
345 if ((LA(1)==' ')) {
346 _saveIndex=text.length();
347 match(' ');
348 text.setLength(_saveIndex);
349 }
350 else {
351 break _loop16;
352 }
353
354 } while (true);
355 }
356 match("(");
357 mIF_EXPR(false);
358 match(")");
359 _saveIndex=text.length();
360 match('>');
361 text.setLength(_saveIndex);
362 _ttype = TemplateParser.IF;
363 {
364 if ((LA(1)=='\n'||LA(1)=='\r')) {
365 {
366 switch ( LA(1)) {
367 case '\r':
368 {
369 _saveIndex=text.length();
370 match('\r');
371 text.setLength(_saveIndex);
372 break;
373 }
374 case '\n':
375 {
376 break;
377 }
378 default:
379 {
380 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
381 }
382 }
383 }
384 _saveIndex=text.length();
385 match('\n');
386 text.setLength(_saveIndex);
387 newline();
388 }
389 else {
390 }
391
392 }
393 }
394 else if ((LA(1)=='<') && (LA(2)=='e') && (LA(3)=='l') && (LA(4)=='s') && (LA(5)=='e') && (LA(6)=='i') && (LA(7)=='f')) {
395 _saveIndex=text.length();
396 match('<');
397 text.setLength(_saveIndex);
398 match("elseif");
399 {
400 _loop20:
401 do {
402 if ((LA(1)==' ')) {
403 _saveIndex=text.length();
404 match(' ');
405 text.setLength(_saveIndex);
406 }
407 else {
408 break _loop20;
409 }
410
411 } while (true);
412 }
413 match("(");
414 mIF_EXPR(false);
415 match(")");
416 _saveIndex=text.length();
417 match('>');
418 text.setLength(_saveIndex);
419 _ttype = TemplateParser.ELSEIF;
420 {
421 if ((LA(1)=='\n'||LA(1)=='\r')) {
422 {
423 switch ( LA(1)) {
424 case '\r':
425 {
426 _saveIndex=text.length();
427 match('\r');
428 text.setLength(_saveIndex);
429 break;
430 }
431 case '\n':
432 {
433 break;
434 }
435 default:
436 {
437 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
438 }
439 }
440 }
441 _saveIndex=text.length();
442 match('\n');
443 text.setLength(_saveIndex);
444 newline();
445 }
446 else {
447 }
448
449 }
450 }
451 else if ((LA(1)=='<') && (LA(2)=='e') && (LA(3)=='n') && (LA(4)=='d') && (LA(5)=='i') && (LA(6)=='f') && (LA(7)=='>')) {
452 _saveIndex=text.length();
453 match('<');
454 text.setLength(_saveIndex);
455 match("endif");
456 _saveIndex=text.length();
457 match('>');
458 text.setLength(_saveIndex);
459 _ttype = TemplateParser.ENDIF;
460 {
461 if (((LA(1)=='\n'||LA(1)=='\r'))&&(startCol==1)) {
462 {
463 switch ( LA(1)) {
464 case '\r':
465 {
466 _saveIndex=text.length();
467 match('\r');
468 text.setLength(_saveIndex);
469 break;
470 }
471 case '\n':
472 {
473 break;
474 }
475 default:
476 {
477 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
478 }
479 }
480 }
481 _saveIndex=text.length();
482 match('\n');
483 text.setLength(_saveIndex);
484 newline();
485 }
486 else {
487 }
488
489 }
490 }
491 else if ((LA(1)=='<') && (LA(2)=='e') && (LA(3)=='l') && (LA(4)=='s') && (LA(5)=='e') && (LA(6)=='>') && (true)) {
492 _saveIndex=text.length();
493 match('<');
494 text.setLength(_saveIndex);
495 match("else");
496 _saveIndex=text.length();
497 match('>');
498 text.setLength(_saveIndex);
499 _ttype = TemplateParser.ELSE;
500 {
501 if ((LA(1)=='\n'||LA(1)=='\r')) {
502 {
503 switch ( LA(1)) {
504 case '\r':
505 {
506 _saveIndex=text.length();
507 match('\r');
508 text.setLength(_saveIndex);
509 break;
510 }
511 case '\n':
512 {
513 break;
514 }
515 default:
516 {
517 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
518 }
519 }
520 }
521 _saveIndex=text.length();
522 match('\n');
523 text.setLength(_saveIndex);
524 newline();
525 }
526 else {
527 }
528
529 }
530 }
531 else if ((LA(1)=='<') && (LA(2)=='@') && (_tokenSet_7.member(LA(3))) && ((LA(4) >= '\u0001' && LA(4) <= '\ufffe')) && ((LA(5) >= '\u0001' && LA(5) <= '\ufffe')) && ((LA(6) >= '\u0001' && LA(6) <= '\ufffe')) && (true)) {
532 _saveIndex=text.length();
533 match('<');
534 text.setLength(_saveIndex);
535 _saveIndex=text.length();
536 match('@');
537 text.setLength(_saveIndex);
538 {
539 int _cnt29=0;
540 _loop29:
541 do {
542 if ((_tokenSet_7.member(LA(1)))) {
543 {
544 match(_tokenSet_7);
545 }
546 }
547 else {
548 if ( _cnt29>=1 ) { break _loop29; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
549 }
550
551 _cnt29++;
552 } while (true);
553 }
554 {
555 switch ( LA(1)) {
556 case '(':
557 {
558 _saveIndex=text.length();
559 match("()");
560 text.setLength(_saveIndex);
561 _saveIndex=text.length();
562 match('>');
563 text.setLength(_saveIndex);
564 _ttype = TemplateParser.REGION_REF;
565 break;
566 }
567 case '>':
568 {
569 _saveIndex=text.length();
570 match('>');
571 text.setLength(_saveIndex);
572
573 _ttype = TemplateParser.REGION_DEF;
574 String t=new String(text.getBuffer(),_begin,text.length()-_begin);
575 text.setLength(_begin); text.append(t+"::=");
576
577 {
578 if ((LA(1)=='\n'||LA(1)=='\r') && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && (true) && (true) && (true) && (true)) {
579 {
580 switch ( LA(1)) {
581 case '\r':
582 {
583 _saveIndex=text.length();
584 match('\r');
585 text.setLength(_saveIndex);
586 break;
587 }
588 case '\n':
589 {
590 break;
591 }
592 default:
593 {
594 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
595 }
596 }
597 }
598 _saveIndex=text.length();
599 match('\n');
600 text.setLength(_saveIndex);
601 newline();
602 }
603 else if (((LA(1) >= '\u0001' && LA(1) <= '\ufffe')) && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && (true) && (true) && (true) && (true) && (true)) {
604 }
605 else {
606 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
607 }
608
609 }
610 boolean atLeft = false;
611 {
612 int _cnt36=0;
613 _loop36:
614 do {
615 if ((((LA(1) >= '\u0001' && LA(1) <= '\ufffe')) && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && (true) && (true) && (true) && (true) && (true))&&(!(upcomingAtEND(1)||(upcomingNewline(1)&&upcomingAtEND(2))))) {
616 {
617 if ((LA(1)=='\n'||LA(1)=='\r') && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && (true) && (true) && (true) && (true) && (true)) {
618 {
619 switch ( LA(1)) {
620 case '\r':
621 {
622 match('\r');
623 break;
624 }
625 case '\n':
626 {
627 break;
628 }
629 default:
630 {
631 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
632 }
633 }
634 }
635 match('\n');
636 newline(); atLeft = true;
637 }
638 else if (((LA(1) >= '\u0001' && LA(1) <= '\ufffe')) && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && (true) && (true) && (true) && (true) && (true)) {
639 matchNot(EOF_CHAR);
640 atLeft = false;
641 }
642 else {
643 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
644 }
645
646 }
647 }
648 else {
649 if ( _cnt36>=1 ) { break _loop36; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
650 }
651
652 _cnt36++;
653 } while (true);
654 }
655 {
656 if ((LA(1)=='\n'||LA(1)=='\r') && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && (true) && (true) && (true) && (true) && (true)) {
657 {
658 switch ( LA(1)) {
659 case '\r':
660 {
661 _saveIndex=text.length();
662 match('\r');
663 text.setLength(_saveIndex);
664 break;
665 }
666 case '\n':
667 {
668 break;
669 }
670 default:
671 {
672 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
673 }
674 }
675 }
676 _saveIndex=text.length();
677 match('\n');
678 text.setLength(_saveIndex);
679 newline(); atLeft = true;
680 }
681 else if (((LA(1) >= '\u0001' && LA(1) <= '\ufffe')) && (true) && (true) && (true) && (true) && (true) && (true)) {
682 }
683 else {
684 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
685 }
686
687 }
688 {
689 if ((LA(1)=='<') && (LA(2)=='@')) {
690 _saveIndex=text.length();
691 match("<@end>");
692 text.setLength(_saveIndex);
693 }
694 else if (((LA(1) >= '\u0001' && LA(1) <= '\ufffe')) && (true)) {
695 matchNot(EOF_CHAR);
696 self.error("missing region "+t+" <@end> tag");
697 }
698 else {
699 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
700 }
701
702 }
703 {
704 if (((LA(1)=='\n'||LA(1)=='\r'))&&(atLeft)) {
705 {
706 switch ( LA(1)) {
707 case '\r':
708 {
709 _saveIndex=text.length();
710 match('\r');
711 text.setLength(_saveIndex);
712 break;
713 }
714 case '\n':
715 {
716 break;
717 }
718 default:
719 {
720 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
721 }
722 }
723 }
724 _saveIndex=text.length();
725 match('\n');
726 text.setLength(_saveIndex);
727 newline();
728 }
729 else {
730 }
731
732 }
733 break;
734 }
735 default:
736 {
737 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
738 }
739 }
740 }
741 }
742 else if ((LA(1)=='<') && (_tokenSet_5.member(LA(2))) && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && (true) && (true) && (true) && (true)) {
743 _saveIndex=text.length();
744 match('<');
745 text.setLength(_saveIndex);
746 mEXPR(false);
747 _saveIndex=text.length();
748 match('>');
749 text.setLength(_saveIndex);
750 }
751 else {
752 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
753 }
754
755 }
756
757 ChunkToken t = new ChunkToken(_ttype, new String(text.getBuffer(),_begin,text.length()-_begin), currentIndent);
758 _token = t;
759
760 }
761 else {
762 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
763 }
764
765 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
766 _token = makeToken(_ttype);
767 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
768 }
769 _returnToken = _token;
770 }
771
772 protected final void mLINE_BREAK(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
773 int _ttype; Token _token=null; int _begin=text.length();
774 _ttype = LINE_BREAK;
775 int _saveIndex;
776
777 match("<\\\\>");
778 {
779 switch ( LA(1)) {
780 case '\t': case ' ':
781 {
782 mINDENT(false);
783 break;
784 }
785 case '\n': case '\r':
786 {
787 break;
788 }
789 default:
790 {
791 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
792 }
793 }
794 }
795 {
796 switch ( LA(1)) {
797 case '\r':
798 {
799 match('\r');
800 break;
801 }
802 case '\n':
803 {
804 break;
805 }
806 default:
807 {
808 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
809 }
810 }
811 }
812 match('\n');
813 newline();
814 {
815 if ((LA(1)=='\t'||LA(1)==' ')) {
816 mINDENT(false);
817 }
818 else {
819 }
820
821 }
822 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
823 _token = makeToken(_ttype);
824 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
825 }
826 _returnToken = _token;
827 }
828
829 protected final char mESC_CHAR(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
830 char uc='\u0000';
831 int _ttype; Token _token=null; int _begin=text.length();
832 _ttype = ESC_CHAR;
833 int _saveIndex;
834 Token a=null;
835 Token b=null;
836 Token c=null;
837 Token d=null;
838
839 if ((LA(1)=='\\') && (LA(2)=='n')) {
840 _saveIndex=text.length();
841 match("\\n");
842 text.setLength(_saveIndex);
843 uc = '\n';
844 }
845 else if ((LA(1)=='\\') && (LA(2)=='r')) {
846 _saveIndex=text.length();
847 match("\\r");
848 text.setLength(_saveIndex);
849 uc = '\r';
850 }
851 else if ((LA(1)=='\\') && (LA(2)=='t')) {
852 _saveIndex=text.length();
853 match("\\t");
854 text.setLength(_saveIndex);
855 uc = '\t';
856 }
857 else if ((LA(1)=='\\') && (LA(2)==' ')) {
858 _saveIndex=text.length();
859 match("\\ ");
860 text.setLength(_saveIndex);
861 uc = ' ';
862 }
863 else if ((LA(1)=='\\') && (LA(2)=='u')) {
864 _saveIndex=text.length();
865 match("\\u");
866 text.setLength(_saveIndex);
867 _saveIndex=text.length();
868 mHEX(true);
869 text.setLength(_saveIndex);
870 a=_returnToken;
871 _saveIndex=text.length();
872 mHEX(true);
873 text.setLength(_saveIndex);
874 b=_returnToken;
875 _saveIndex=text.length();
876 mHEX(true);
877 text.setLength(_saveIndex);
878 c=_returnToken;
879 _saveIndex=text.length();
880 mHEX(true);
881 text.setLength(_saveIndex);
882 d=_returnToken;
883 uc = (char)Integer.parseInt(a.getText()+b.getText()+c.getText()+d.getText(), 16);
884 }
885 else {
886 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
887 }
888
889 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
890 _token = makeToken(_ttype);
891 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
892 }
893 _returnToken = _token;
894 return uc;
895 }
896
897 protected final void mCOMMENT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
898 int _ttype; Token _token=null; int _begin=text.length();
899 _ttype = COMMENT;
900 int _saveIndex;
901
902 int startCol = getColumn();
903
904
905 match("<!");
906 {
907 _loop74:
908 do {
909 // nongreedy exit test
910 if ((LA(1)=='!') && (LA(2)=='>') && (true) && (true) && (true) && (true) && (true)) break _loop74;
911 if ((LA(1)=='\n'||LA(1)=='\r') && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && (true) && (true) && (true) && (true)) {
912 {
913 switch ( LA(1)) {
914 case '\r':
915 {
916 match('\r');
917 break;
918 }
919 case '\n':
920 {
921 break;
922 }
923 default:
924 {
925 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
926 }
927 }
928 }
929 match('\n');
930 newline();
931 }
932 else if (((LA(1) >= '\u0001' && LA(1) <= '\ufffe')) && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && (true) && (true) && (true) && (true)) {
933 matchNot(EOF_CHAR);
934 }
935 else {
936 break _loop74;
937 }
938
939 } while (true);
940 }
941 match("!>");
942 {
943 if (((LA(1)=='\n'||LA(1)=='\r'))&&(startCol==1)) {
944 {
945 switch ( LA(1)) {
946 case '\r':
947 {
948 match('\r');
949 break;
950 }
951 case '\n':
952 {
953 break;
954 }
955 default:
956 {
957 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
958 }
959 }
960 }
961 match('\n');
962 newline();
963 }
964 else {
965 }
966
967 }
968 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
969 _token = makeToken(_ttype);
970 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
971 }
972 _returnToken = _token;
973 }
974
975 protected final void mIF_EXPR(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
976 int _ttype; Token _token=null; int _begin=text.length();
977 _ttype = IF_EXPR;
978 int _saveIndex;
979
980 {
981 int _cnt61=0;
982 _loop61:
983 do {
984 switch ( LA(1)) {
985 case '\\':
986 {
987 mESC(false);
988 break;
989 }
990 case '\n': case '\r':
991 {
992 {
993 switch ( LA(1)) {
994 case '\r':
995 {
996 match('\r');
997 break;
998 }
999 case '\n':
1000 {
1001 break;
1002 }
1003 default:
1004 {
1005 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
1006 }
1007 }
1008 }
1009 match('\n');
1010 newline();
1011 break;
1012 }
1013 case '{':
1014 {
1015 mSUBTEMPLATE(false);
1016 break;
1017 }
1018 case '(':
1019 {
1020 mNESTED_PARENS(false);
1021 break;
1022 }
1023 default:
1024 if ((_tokenSet_8.member(LA(1)))) {
1025 matchNot(')');
1026 }
1027 else {
1028 if ( _cnt61>=1 ) { break _loop61; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
1029 }
1030 }
1031 _cnt61++;
1032 } while (true);
1033 }
1034 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
1035 _token = makeToken(_ttype);
1036 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
1037 }
1038 _returnToken = _token;
1039 }
1040
1041 protected final void mEXPR(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
1042 int _ttype; Token _token=null; int _begin=text.length();
1043 _ttype = EXPR;
1044 int _saveIndex;
1045
1046 {
1047 int _cnt49=0;
1048 _loop49:
1049 do {
1050 switch ( LA(1)) {
1051 case '\\':
1052 {
1053 mESC(false);
1054 break;
1055 }
1056 case '\n': case '\r':
1057 {
1058 {
1059 switch ( LA(1)) {
1060 case '\r':
1061 {
1062 match('\r');
1063 break;
1064 }
1065 case '\n':
1066 {
1067 break;
1068 }
1069 default:
1070 {
1071 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
1072 }
1073 }
1074 }
1075 match('\n');
1076 newline();
1077 break;
1078 }
1079 case '{':
1080 {
1081 mSUBTEMPLATE(false);
1082 break;
1083 }
1084 default:
1085 if ((LA(1)=='+'||LA(1)=='=') && (LA(2)=='"'||LA(2)=='<')) {
1086 {
1087 switch ( LA(1)) {
1088 case '=':
1089 {
1090 match('=');
1091 break;
1092 }
1093 case '+':
1094 {
1095 match('+');
1096 break;
1097 }
1098 default:
1099 {
1100 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
1101 }
1102 }
1103 }
1104 mTEMPLATE(false);
1105 }
1106 else if ((LA(1)=='+'||LA(1)=='=') && (LA(2)=='{')) {
1107 {
1108 switch ( LA(1)) {
1109 case '=':
1110 {
1111 match('=');
1112 break;
1113 }
1114 case '+':
1115 {
1116 match('+');
1117 break;
1118 }
1119 default:
1120 {
1121 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
1122 }
1123 }
1124 }
1125 mSUBTEMPLATE(false);
1126 }
1127 else if ((LA(1)=='+'||LA(1)=='=') && (_tokenSet_9.member(LA(2)))) {
1128 {
1129 switch ( LA(1)) {
1130 case '=':
1131 {
1132 match('=');
1133 break;
1134 }
1135 case '+':
1136 {
1137 match('+');
1138 break;
1139 }
1140 default:
1141 {
1142 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
1143 }
1144 }
1145 }
1146 {
1147 match(_tokenSet_9);
1148 }
1149 }
1150 else if ((_tokenSet_10.member(LA(1)))) {
1151 matchNot('>');
1152 }
1153 else {
1154 if ( _cnt49>=1 ) { break _loop49; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
1155 }
1156 }
1157 _cnt49++;
1158 } while (true);
1159 }
1160 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
1161 _token = makeToken(_ttype);
1162 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
1163 }
1164 _returnToken = _token;
1165 }
1166
1167 protected final void mESC(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
1168 int _ttype; Token _token=null; int _begin=text.length();
1169 _ttype = ESC;
1170 int _saveIndex;
1171
1172 match('\\');
1173 matchNot(EOF_CHAR);
1174 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
1175 _token = makeToken(_ttype);
1176 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
1177 }
1178 _returnToken = _token;
1179 }
1180
1181 protected final void mSUBTEMPLATE(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
1182 int _ttype; Token _token=null; int _begin=text.length();
1183 _ttype = SUBTEMPLATE;
1184 int _saveIndex;
1185
1186 match('{');
1187 {
1188 _loop67:
1189 do {
1190 switch ( LA(1)) {
1191 case '{':
1192 {
1193 mSUBTEMPLATE(false);
1194 break;
1195 }
1196 case '\\':
1197 {
1198 mESC(false);
1199 break;
1200 }
1201 default:
1202 if ((_tokenSet_11.member(LA(1)))) {
1203 matchNot('}');
1204 }
1205 else {
1206 break _loop67;
1207 }
1208 }
1209 } while (true);
1210 }
1211 match('}');
1212 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
1213 _token = makeToken(_ttype);
1214 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
1215 }
1216 _returnToken = _token;
1217 }
1218
1219 protected final void mTEMPLATE(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
1220 int _ttype; Token _token=null; int _begin=text.length();
1221 _ttype = TEMPLATE;
1222 int _saveIndex;
1223
1224 switch ( LA(1)) {
1225 case '"':
1226 {
1227 match('"');
1228 {
1229 _loop52:
1230 do {
1231 if ((LA(1)=='\\')) {
1232 mESC(false);
1233 }
1234 else if ((_tokenSet_12.member(LA(1)))) {
1235 matchNot('"');
1236 }
1237 else {
1238 break _loop52;
1239 }
1240
1241 } while (true);
1242 }
1243 match('"');
1244 break;
1245 }
1246 case '<':
1247 {
1248 match("<<");
1249 {
1250 if ((LA(1)=='\n'||LA(1)=='\r') && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && ((LA(4) >= '\u0001' && LA(4) <= '\ufffe')) && (true) && (true) && (true)) {
1251 {
1252 switch ( LA(1)) {
1253 case '\r':
1254 {
1255 _saveIndex=text.length();
1256 match('\r');
1257 text.setLength(_saveIndex);
1258 break;
1259 }
1260 case '\n':
1261 {
1262 break;
1263 }
1264 default:
1265 {
1266 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
1267 }
1268 }
1269 }
1270 _saveIndex=text.length();
1271 match('\n');
1272 text.setLength(_saveIndex);
1273 newline();
1274 }
1275 else if (((LA(1) >= '\u0001' && LA(1) <= '\ufffe')) && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && (true) && (true) && (true) && (true)) {
1276 }
1277 else {
1278 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
1279 }
1280
1281 }
1282 {
1283 _loop57:
1284 do {
1285 // nongreedy exit test
1286 if ((LA(1)=='>') && (LA(2)=='>') && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && (true) && (true) && (true) && (true)) break _loop57;
1287 if (((LA(1)=='\r') && (LA(2)=='\n') && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && ((LA(4) >= '\u0001' && LA(4) <= '\ufffe')) && ((LA(5) >= '\u0001' && LA(5) <= '\ufffe')) && (true) && (true))&&(LA(3)=='>'&&LA(4)=='>')) {
1288 _saveIndex=text.length();
1289 match('\r');
1290 text.setLength(_saveIndex);
1291 _saveIndex=text.length();
1292 match('\n');
1293 text.setLength(_saveIndex);
1294 newline();
1295 }
1296 else if (((LA(1)=='\n') && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && ((LA(4) >= '\u0001' && LA(4) <= '\ufffe')) && (true) && (true) && (true))&&(LA(2)=='>'&&LA(3)=='>')) {
1297 _saveIndex=text.length();
1298 match('\n');
1299 text.setLength(_saveIndex);
1300 newline();
1301 }
1302 else if ((LA(1)=='\n'||LA(1)=='\r') && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && ((LA(4) >= '\u0001' && LA(4) <= '\ufffe')) && (true) && (true) && (true)) {
1303 {
1304 switch ( LA(1)) {
1305 case '\r':
1306 {
1307 match('\r');
1308 break;
1309 }
1310 case '\n':
1311 {
1312 break;
1313 }
1314 default:
1315 {
1316 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
1317 }
1318 }
1319 }
1320 match('\n');
1321 newline();
1322 }
1323 else if (((LA(1) >= '\u0001' && LA(1) <= '\ufffe')) && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && ((LA(4) >= '\u0001' && LA(4) <= '\ufffe')) && (true) && (true) && (true)) {
1324 matchNot(EOF_CHAR);
1325 }
1326 else {
1327 break _loop57;
1328 }
1329
1330 } while (true);
1331 }
1332 match(">>");
1333 break;
1334 }
1335 default:
1336 {
1337 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
1338 }
1339 }
1340 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
1341 _token = makeToken(_ttype);
1342 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
1343 }
1344 _returnToken = _token;
1345 }
1346
1347 protected final void mNESTED_PARENS(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
1348 int _ttype; Token _token=null; int _begin=text.length();
1349 _ttype = NESTED_PARENS;
1350 int _saveIndex;
1351
1352 match('(');
1353 {
1354 int _cnt70=0;
1355 _loop70:
1356 do {
1357 switch ( LA(1)) {
1358 case '(':
1359 {
1360 mNESTED_PARENS(false);
1361 break;
1362 }
1363 case '\\':
1364 {
1365 mESC(false);
1366 break;
1367 }
1368 default:
1369 if ((_tokenSet_13.member(LA(1)))) {
1370 matchNot(')');
1371 }
1372 else {
1373 if ( _cnt70>=1 ) { break _loop70; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
1374 }
1375 }
1376 _cnt70++;
1377 } while (true);
1378 }
1379 match(')');
1380 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
1381 _token = makeToken(_ttype);
1382 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
1383 }
1384 _returnToken = _token;
1385 }
1386
1387 protected final void mHEX(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
1388 int _ttype; Token _token=null; int _begin=text.length();
1389 _ttype = HEX;
1390 int _saveIndex;
1391
1392 switch ( LA(1)) {
1393 case '0': case '1': case '2': case '3':
1394 case '4': case '5': case '6': case '7':
1395 case '8': case '9':
1396 {
1397 matchRange('0','9');
1398 break;
1399 }
1400 case 'A': case 'B': case 'C': case 'D':
1401 case 'E': case 'F':
1402 {
1403 matchRange('A','F');
1404 break;
1405 }
1406 case 'a': case 'b': case 'c': case 'd':
1407 case 'e': case 'f':
1408 {
1409 matchRange('a','f');
1410 break;
1411 }
1412 default:
1413 {
1414 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
1415 }
1416 }
1417 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
1418 _token = makeToken(_ttype);
1419 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
1420 }
1421 _returnToken = _token;
1422 }
1423
1424
1425 private static final long[] mk_tokenSet_0() {
1426 long[] data = new long[2048];
1427 data[0]=-1152921504606856194L;
1428 for (int i = 1; i<=1022; i++) { data[i]=-1L; }
1429 data[1023]=9223372036854775807L;
1430 return data;
1431 }
1432 public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0());
1433 private static final long[] mk_tokenSet_1() {
1434 long[] data = new long[2048];
1435 data[0]=-5764607523034234882L;
1436 for (int i = 1; i<=1022; i++) { data[i]=-1L; }
1437 data[1023]=9223372036854775807L;
1438 return data;
1439 }
1440 public static final BitSet _tokenSet_1 = new BitSet(mk_tokenSet_1());
1441 private static final long[] mk_tokenSet_2() {
1442 long[] data = new long[1025];
1443 data[0]=4294977024L;
1444 return data;
1445 }
1446 public static final BitSet _tokenSet_2 = new BitSet(mk_tokenSet_2());
1447 private static final long[] mk_tokenSet_3() {
1448 long[] data = new long[1025];
1449 data[0]=4294967296L;
1450 data[1]=14707067533131776L;
1451 return data;
1452 }
1453 public static final BitSet _tokenSet_3 = new BitSet(mk_tokenSet_3());
1454 private static final long[] mk_tokenSet_4() {
1455 long[] data = new long[1025];
1456 data[0]=4899634919602388992L;
1457 data[1]=541434314878L;
1458 return data;
1459 }
1460 public static final BitSet _tokenSet_4 = new BitSet(mk_tokenSet_4());
1461 private static final long[] mk_tokenSet_5() {
1462 long[] data = new long[2048];
1463 data[0]=-4611686018427387906L;
1464 for (int i = 1; i<=1022; i++) { data[i]=-1L; }
1465 data[1023]=9223372036854775807L;
1466 return data;
1467 }
1468 public static final BitSet _tokenSet_5 = new BitSet(mk_tokenSet_5());
1469 private static final long[] mk_tokenSet_6() {
1470 long[] data = new long[2048];
1471 data[0]=-2199023255554L;
1472 for (int i = 1; i<=1022; i++) { data[i]=-1L; }
1473 data[1023]=9223372036854775807L;
1474 return data;
1475 }
1476 public static final BitSet _tokenSet_6 = new BitSet(mk_tokenSet_6());
1477 private static final long[] mk_tokenSet_7() {
1478 long[] data = new long[2048];
1479 data[0]=-4611687117939015682L;
1480 for (int i = 1; i<=1022; i++) { data[i]=-1L; }
1481 data[1023]=9223372036854775807L;
1482 return data;
1483 }
1484 public static final BitSet _tokenSet_7 = new BitSet(mk_tokenSet_7());
1485 private static final long[] mk_tokenSet_8() {
1486 long[] data = new long[2048];
1487 data[0]=-3298534892546L;
1488 data[1]=-576460752571858945L;
1489 for (int i = 2; i<=1022; i++) { data[i]=-1L; }
1490 data[1023]=9223372036854775807L;
1491 return data;
1492 }
1493 public static final BitSet _tokenSet_8 = new BitSet(mk_tokenSet_8());
1494 private static final long[] mk_tokenSet_9() {
1495 long[] data = new long[2048];
1496 data[0]=-1152921521786716162L;
1497 data[1]=-576460752303423489L;
1498 for (int i = 2; i<=1022; i++) { data[i]=-1L; }
1499 data[1023]=9223372036854775807L;
1500 return data;
1501 }
1502 public static final BitSet _tokenSet_9 = new BitSet(mk_tokenSet_9());
1503 private static final long[] mk_tokenSet_10() {
1504 long[] data = new long[2048];
1505 data[0]=-6917537823734113282L;
1506 data[1]=-576460752571858945L;
1507 for (int i = 2; i<=1022; i++) { data[i]=-1L; }
1508 data[1023]=9223372036854775807L;
1509 return data;
1510 }
1511 public static final BitSet _tokenSet_10 = new BitSet(mk_tokenSet_10());
1512 private static final long[] mk_tokenSet_11() {
1513 long[] data = new long[2048];
1514 data[0]=-2L;
1515 data[1]=-2882303761785552897L;
1516 for (int i = 2; i<=1022; i++) { data[i]=-1L; }
1517 data[1023]=9223372036854775807L;
1518 return data;
1519 }
1520 public static final BitSet _tokenSet_11 = new BitSet(mk_tokenSet_11());
1521 private static final long[] mk_tokenSet_12() {
1522 long[] data = new long[2048];
1523 data[0]=-17179869186L;
1524 data[1]=-268435457L;
1525 for (int i = 2; i<=1022; i++) { data[i]=-1L; }
1526 data[1023]=9223372036854775807L;
1527 return data;
1528 }
1529 public static final BitSet _tokenSet_12 = new BitSet(mk_tokenSet_12());
1530 private static final long[] mk_tokenSet_13() {
1531 long[] data = new long[2048];
1532 data[0]=-3298534883330L;
1533 data[1]=-268435457L;
1534 for (int i = 2; i<=1022; i++) { data[i]=-1L; }
1535 data[1023]=9223372036854775807L;
1536 return data;
1537 }
1538 public static final BitSet _tokenSet_13 = new BitSet(mk_tokenSet_13());
1539
1540 }
0 SMAP
1 AngleBracketTemplateLexer.java
2 G
3 *S G
4 *F
5 + 0 angle.bracket.template.g
6 angle.bracket.template.g
7 *L
8 0:122
9 0:128
10 0:134
11 1:3
12 1:4
13 1:5
14 1:6
15 1:8
16 1:9
17 1:10
18 1:11
19 1:12
20 1:13
21 1:14
22 1:15
23 1:16
24 1:17
25 1:19
26 1:20
27 1:21
28 1:22
29 1:23
30 1:24
31 1:25
32 1:26
33 1:27
34 1:28
35 1:29
36 1:30
37 1:31
38 1:32
39 47:65
40 48:66
41 50:68
42 51:69
43 52:70
44 53:71
45 55:73
46 56:74
47 57:75
48 59:77
49 60:78
50 61:79
51 62:80
52 64:82
53 65:83
54 66:84
55 67:85
56 69:87
57 70:88
58 71:89
59 73:91
60 74:92
61 75:93
62 78:163
63 78:164
64 78:165
65 78:166
66 78:169
67 78:170
68 78:228
69 78:229
70 78:230
71 78:231
72 78:232
73 78:233
74 80:172
75 80:173
76 80:174
77 80:184
78 80:190
79 80:196
80 80:202
81 80:214
82 80:219
83 80:220
84 80:221
85 80:222
86 80:224
87 80:225
88 80:226
89 81:176
90 82:177
91 85:179
92 85:180
93 85:181
94 85:182
95 85:183
96 86:185
97 86:186
98 86:187
99 86:188
100 86:189
101 87:191
102 87:192
103 87:193
104 87:194
105 87:195
106 88:197
107 88:198
108 88:200
109 89:167
110 89:203
111 89:204
112 89:205
113 91:207
114 92:208
115 93:209
116 94:210
117 95:211
118 96:212
119 98:215
120 98:217
121 100:227
122 104:235
123 104:236
124 104:237
125 104:238
126 104:257
127 104:258
128 104:259
129 104:260
130 104:261
131 104:262
132 105:241
133 105:242
134 105:243
135 105:244
136 105:245
137 105:246
138 105:247
139 105:248
140 105:249
141 105:250
142 105:251
143 105:252
144 105:254
145 105:255
146 105:256
147 108:264
148 108:265
149 108:266
150 108:267
151 108:288
152 108:289
153 108:290
154 108:291
155 108:292
156 108:293
157 109:270
158 109:271
159 109:272
160 109:273
161 109:280
162 109:281
163 109:282
164 109:283
165 109:284
166 109:286
167 109:287
168 112:295
169 112:296
170 112:297
171 112:298
172 112:306
173 112:331
174 112:335
175 112:761
176 112:762
177 112:763
178 112:764
179 112:766
180 112:767
181 112:768
182 112:769
183 112:770
184 112:771
185 113:300
186 119:303
187 119:304
188 119:305
189 121:307
190 121:308
191 122:309
192 122:310
193 122:311
194 122:313
195 122:314
196 122:315
197 122:316
198 122:317
199 122:318
200 122:319
201 122:320
202 122:321
203 122:322
204 122:324
205 122:325
206 122:326
207 122:327
208 122:328
209 122:329
210 123:330
211 124:332
212 124:333
213 124:334
214 125:336
215 125:394
216 125:451
217 125:491
218 125:531
219 125:742
220 125:751
221 125:752
222 125:753
223 125:754
224 129:338
225 129:339
226 129:340
227 129:341
228 129:342
229 129:343
230 129:344
231 129:345
232 129:346
233 129:347
234 129:348
235 129:349
236 129:350
237 129:351
238 129:352
239 129:353
240 129:355
241 129:356
242 129:357
243 129:358
244 129:359
245 129:360
246 129:361
247 129:362
248 129:363
249 130:365
250 130:367
251 130:368
252 130:369
253 130:370
254 130:371
255 130:372
256 130:379
257 130:380
258 130:381
259 130:382
260 130:383
261 130:385
262 130:386
263 130:387
264 130:388
265 130:389
266 130:391
267 131:395
268 131:396
269 131:397
270 131:398
271 131:399
272 131:400
273 131:401
274 131:402
275 131:403
276 131:404
277 131:405
278 131:406
279 131:407
280 131:408
281 131:409
282 131:410
283 131:412
284 131:413
285 131:414
286 131:415
287 131:416
288 131:417
289 131:418
290 131:419
291 131:420
292 132:422
293 132:424
294 132:425
295 132:426
296 132:427
297 132:428
298 132:429
299 132:436
300 132:437
301 132:438
302 132:439
303 132:440
304 132:442
305 132:443
306 132:444
307 132:445
308 132:446
309 132:448
310 133:492
311 133:493
312 133:494
313 133:495
314 133:496
315 133:497
316 133:498
317 133:499
318 133:500
319 134:502
320 134:504
321 134:505
322 134:506
323 134:507
324 134:508
325 134:509
326 134:516
327 134:517
328 134:518
329 134:519
330 134:520
331 134:522
332 134:523
333 134:524
334 134:525
335 134:526
336 134:528
337 135:452
338 135:453
339 135:454
340 135:455
341 135:456
342 135:457
343 135:458
344 135:459
345 135:460
346 136:462
347 136:464
348 136:465
349 136:466
350 136:467
351 136:468
352 136:469
353 136:476
354 136:477
355 136:478
356 136:479
357 136:480
358 136:482
359 136:483
360 136:484
361 136:485
362 136:486
363 136:488
364 140:532
365 140:533
366 140:534
367 140:535
368 140:536
369 140:537
370 140:538
371 140:540
372 140:541
373 140:542
374 140:543
375 140:545
376 140:547
377 140:548
378 140:549
379 140:550
380 140:552
381 140:553
382 140:554
383 141:556
384 141:557
385 141:558
386 141:559
387 141:560
388 141:561
389 141:562
390 141:563
391 141:564
392 141:565
393 141:736
394 141:737
395 141:738
396 141:739
397 141:740
398 142:568
399 142:569
400 142:570
401 142:571
402 142:572
403 144:574
404 145:575
405 146:576
406 148:579
407 148:581
408 148:582
409 148:583
410 148:584
411 148:585
412 148:586
413 148:593
414 148:594
415 148:595
416 148:596
417 148:597
418 148:599
419 148:600
420 148:601
421 148:602
422 148:603
423 148:605
424 148:606
425 148:607
426 148:608
427 149:611
428 150:613
429 150:614
430 150:615
431 150:648
432 150:649
433 150:650
434 150:651
435 150:653
436 150:654
437 150:655
438 153:616
439 153:618
440 153:620
441 153:621
442 153:622
443 153:623
444 153:630
445 153:631
446 153:632
447 153:633
448 153:634
449 153:636
450 153:637
451 153:638
452 153:642
453 153:643
454 153:644
455 153:645
456 154:639
457 154:640
458 154:641
459 157:657
460 157:659
461 157:660
462 157:661
463 157:662
464 157:663
465 157:664
466 157:671
467 157:672
468 157:673
469 157:674
470 157:675
471 157:677
472 157:678
473 157:679
474 157:680
475 157:681
476 157:683
477 157:684
478 157:685
479 157:686
480 158:690
481 158:691
482 158:692
483 158:693
484 158:694
485 158:698
486 158:699
487 158:700
488 158:701
489 159:695
490 159:696
491 159:697
492 161:705
493 161:707
494 161:708
495 161:709
496 161:710
497 161:711
498 161:712
499 161:719
500 161:720
501 161:721
502 161:722
503 161:723
504 161:725
505 161:726
506 161:727
507 161:728
508 161:729
509 161:731
510 164:743
511 164:744
512 164:745
513 164:746
514 164:747
515 164:748
516 164:749
517 164:750
518 167:758
519 168:759
520 173:1042
521 173:1043
522 173:1044
523 173:1045
524 173:1048
525 173:1049
526 173:1050
527 173:1051
528 173:1052
529 173:1053
530 173:1054
531 173:1085
532 173:1106
533 173:1127
534 173:1150
535 173:1153
536 173:1154
537 173:1155
538 173:1156
539 173:1157
540 173:1158
541 173:1159
542 173:1160
543 173:1161
544 173:1162
545 173:1163
546 173:1164
547 173:1165
548 173:1166
549 174:1057
550 174:1058
551 174:1060
552 174:1061
553 174:1062
554 174:1063
555 174:1070
556 174:1071
557 174:1072
558 174:1073
559 174:1074
560 174:1076
561 174:1077
562 175:1080
563 175:1081
564 175:1082
565 176:1086
566 176:1088
567 176:1089
568 176:1090
569 176:1091
570 176:1094
571 176:1095
572 176:1096
573 176:1099
574 176:1100
575 176:1101
576 176:1102
577 176:1103
578 176:1105
579 177:1107
580 177:1109
581 177:1110
582 177:1111
583 177:1112
584 177:1115
585 177:1116
586 177:1117
587 177:1120
588 177:1121
589 177:1122
590 177:1123
591 177:1124
592 177:1126
593 178:1128
594 178:1130
595 178:1131
596 178:1132
597 178:1133
598 178:1136
599 178:1137
600 178:1138
601 178:1141
602 178:1142
603 178:1143
604 178:1144
605 178:1145
606 178:1148
607 179:1151
608 179:1152
609 184:1220
610 184:1221
611 184:1222
612 184:1223
613 184:1225
614 184:1336
615 184:1337
616 184:1338
617 184:1339
618 184:1340
619 184:1341
620 184:1342
621 184:1343
622 184:1344
623 184:1345
624 184:1346
625 185:1226
626 185:1227
627 185:1228
628 185:1229
629 185:1230
630 185:1231
631 185:1232
632 185:1233
633 185:1234
634 185:1235
635 185:1236
636 185:1237
637 185:1238
638 185:1239
639 185:1240
640 185:1242
641 185:1243
642 185:1244
643 186:1247
644 186:1248
645 186:1249
646 187:1251
647 187:1253
648 187:1254
649 187:1255
650 187:1256
651 187:1257
652 187:1258
653 187:1265
654 187:1266
655 187:1267
656 187:1268
657 187:1269
658 187:1271
659 187:1272
660 187:1273
661 187:1274
662 187:1275
663 187:1277
664 187:1278
665 187:1279
666 187:1280
667 188:1283
668 188:1284
669 188:1285
670 188:1286
671 188:1287
672 188:1296
673 188:1302
674 188:1323
675 188:1326
676 188:1327
677 188:1328
678 188:1329
679 188:1331
680 188:1332
681 189:1288
682 189:1289
683 189:1290
684 189:1291
685 189:1292
686 189:1293
687 189:1294
688 189:1295
689 190:1297
690 190:1298
691 190:1299
692 190:1300
693 190:1301
694 191:1303
695 191:1305
696 191:1306
697 191:1307
698 191:1308
699 191:1315
700 191:1316
701 191:1317
702 191:1318
703 191:1319
704 191:1321
705 191:1322
706 192:1324
707 192:1325
708 194:1333
709 198:976
710 198:977
711 198:978
712 198:979
713 198:982
714 198:983
715 198:984
716 198:985
717 198:986
718 198:987
719 198:988
720 198:1024
721 198:1027
722 198:1028
723 198:1029
724 198:1030
725 198:1031
726 198:1032
727 198:1033
728 198:1034
729 198:1035
730 198:1036
731 198:1037
732 198:1038
733 198:1039
734 198:1040
735 199:991
736 199:992
737 199:994
738 199:995
739 199:996
740 199:997
741 199:1004
742 199:1005
743 199:1006
744 199:1007
745 199:1008
746 199:1010
747 199:1011
748 200:1014
749 200:1015
750 200:1016
751 201:1019
752 201:1020
753 201:1021
754 202:1025
755 202:1026
756 207:830
757 207:831
758 207:832
759 207:833
760 207:834
761 207:845
762 207:851
763 207:857
764 207:863
765 207:885
766 207:886
767 207:887
768 207:888
769 207:890
770 207:891
771 207:892
772 207:893
773 207:894
774 207:895
775 207:896
776 208:840
777 208:841
778 208:842
779 208:843
780 208:844
781 209:846
782 209:847
783 209:848
784 209:849
785 209:850
786 210:852
787 210:853
788 210:854
789 210:855
790 210:856
791 211:858
792 211:859
793 211:860
794 211:861
795 211:862
796 212:835
797 212:836
798 212:837
799 212:838
800 212:864
801 212:865
802 212:866
803 212:867
804 212:868
805 212:869
806 212:870
807 212:871
808 212:872
809 212:873
810 212:874
811 212:875
812 212:876
813 212:877
814 212:878
815 212:879
816 212:880
817 212:881
818 212:882
819 212:883
820 213:884
821 218:1168
822 218:1169
823 218:1170
824 218:1171
825 218:1173
826 218:1174
827 218:1175
828 218:1176
829 218:1177
830 218:1178
831 218:1179
832 218:1180
833 222:1388
834 222:1389
835 222:1390
836 222:1391
837 222:1393
838 222:1394
839 222:1395
840 222:1396
841 222:1397
842 222:1398
843 222:1401
844 222:1402
845 222:1403
846 222:1404
847 222:1407
848 222:1408
849 222:1409
850 222:1410
851 222:1413
852 222:1414
853 222:1415
854 222:1416
855 222:1417
856 222:1418
857 222:1419
858 222:1420
859 222:1421
860 222:1422
861 222:1423
862 226:1182
863 226:1183
864 226:1184
865 226:1185
866 226:1213
867 226:1214
868 226:1215
869 226:1216
870 226:1217
871 226:1218
872 227:1187
873 227:1188
874 227:1189
875 227:1190
876 227:1191
877 227:1192
878 227:1193
879 227:1194
880 227:1197
881 227:1198
882 227:1199
883 227:1202
884 227:1203
885 227:1204
886 227:1205
887 227:1206
888 227:1207
889 227:1208
890 227:1209
891 227:1210
892 227:1211
893 227:1212
894 231:1348
895 231:1349
896 231:1350
897 231:1351
898 231:1381
899 231:1382
900 231:1383
901 231:1384
902 231:1385
903 231:1386
904 232:1353
905 232:1355
906 232:1356
907 232:1357
908 232:1358
909 232:1359
910 232:1360
911 232:1361
912 232:1364
913 232:1365
914 232:1366
915 232:1369
916 232:1370
917 232:1371
918 232:1372
919 232:1373
920 232:1374
921 232:1375
922 232:1376
923 232:1377
924 232:1378
925 232:1379
926 232:1380
927 236:898
928 236:899
929 236:900
930 236:901
931 236:969
932 236:970
933 236:971
934 236:972
935 236:973
936 236:974
937 237:903
938 240:906
939 241:907
940 241:908
941 241:909
942 241:910
943 241:911
944 241:932
945 241:935
946 241:936
947 241:937
948 241:938
949 241:940
950 241:941
951 242:912
952 242:914
953 242:915
954 242:916
955 242:917
956 242:924
957 242:925
958 242:926
959 242:927
960 242:928
961 242:930
962 242:931
963 243:933
964 243:934
965 245:942
966 245:944
967 245:946
968 245:947
969 245:948
970 245:949
971 245:956
972 245:957
973 245:958
974 245:959
975 245:960
976 245:962
977 245:963
978 245:964
979 245:966
980 249:773
981 249:774
982 249:775
983 249:776
984 249:823
985 249:824
986 249:825
987 249:826
988 249:827
989 249:828
990 250:778
991 250:780
992 250:781
993 250:782
994 250:783
995 250:790
996 250:791
997 250:792
998 250:793
999 250:794
1000 250:797
1001 250:798
1002 250:799
1003 250:800
1004 250:807
1005 250:808
1006 250:809
1007 250:810
1008 250:811
1009 250:813
1010 250:814
1011 250:816
1012 250:817
1013 250:818
1014 250:820
1015 *E
0 // $ANTLR 2.7.7 (20060906): "angle.bracket.template.g" -> "AngleBracketTemplateLexer.java"$
1
2 /*
3 [The "BSD licence"]
4 Copyright (c) 2003-2004 Terence Parr
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 package org.antlr.stringtemplate.language;
30 import org.antlr.stringtemplate.*;
31 import java.io.*;
32
33 public interface AngleBracketTemplateLexerTokenTypes {
34 int EOF = 1;
35 int NULL_TREE_LOOKAHEAD = 3;
36 int LITERAL = 4;
37 int NEWLINE = 5;
38 int ACTION = 6;
39 int IF = 7;
40 int ELSEIF = 8;
41 int ELSE = 9;
42 int ENDIF = 10;
43 int REGION_REF = 11;
44 int REGION_DEF = 12;
45 int EXPR = 13;
46 int TEMPLATE = 14;
47 int IF_EXPR = 15;
48 int ESC_CHAR = 16;
49 int ESC = 17;
50 int HEX = 18;
51 int SUBTEMPLATE = 19;
52 int NESTED_PARENS = 20;
53 int INDENT = 21;
54 int COMMENT = 22;
55 int LINE_BREAK = 23;
56 }
0 // $ANTLR 2.7.7 (20060906): angle.bracket.template.g -> AngleBracketTemplateLexerTokenTypes.txt$
1 AngleBracketTemplateLexer // output token vocab name
2 LITERAL=4
3 NEWLINE=5
4 ACTION=6
5 IF=7
6 ELSEIF=8
7 ELSE=9
8 ENDIF=10
9 REGION_REF=11
10 REGION_DEF=12
11 EXPR=13
12 TEMPLATE=14
13 IF_EXPR=15
14 ESC_CHAR=16
15 ESC=17
16 HEX=18
17 SUBTEMPLATE=19
18 NESTED_PARENS=20
19 INDENT=21
20 COMMENT=22
21 LINE_BREAK=23
0 // $ANTLR 2.7.7 (20060906): "template.g" -> "DefaultTemplateLexer.java"$
1
2 /*
3 [The "BSD licence"]
4 Copyright (c) 2003-2004 Terence Parr
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 package org.antlr.stringtemplate.language;
30 import org.antlr.stringtemplate.*;
31 import java.io.*;
32
33 import java.io.InputStream;
34 import antlr.TokenStreamException;
35 import antlr.TokenStreamIOException;
36 import antlr.TokenStreamRecognitionException;
37 import antlr.CharStreamException;
38 import antlr.CharStreamIOException;
39 import antlr.ANTLRException;
40 import java.io.Reader;
41 import java.util.Hashtable;
42 import antlr.CharScanner;
43 import antlr.InputBuffer;
44 import antlr.ByteBuffer;
45 import antlr.CharBuffer;
46 import antlr.Token;
47 import antlr.CommonToken;
48 import antlr.RecognitionException;
49 import antlr.NoViableAltForCharException;
50 import antlr.MismatchedCharException;
51 import antlr.TokenStream;
52 import antlr.ANTLRHashString;
53 import antlr.LexerSharedInputState;
54 import antlr.collections.impl.BitSet;
55 import antlr.SemanticException;
56
57 /** Break up an input text stream into chunks of either plain text
58 * or template actions in "$...$". Treat IF and ENDIF tokens
59 * specially.
60 */
61 public class DefaultTemplateLexer extends antlr.CharScanner implements TemplateParserTokenTypes, TokenStream
62 {
63
64 protected String currentIndent = null;
65 protected StringTemplate self;
66
67 public DefaultTemplateLexer(StringTemplate self, Reader r) {
68 this(r);
69 this.self = self;
70 }
71
72 public void reportError(RecognitionException e) {
73 self.error("$...$ chunk lexer error", e);
74 }
75
76 protected boolean upcomingELSE(int i) throws CharStreamException {
77 return LA(i)=='$'&&LA(i+1)=='e'&&LA(i+2)=='l'&&LA(i+3)=='s'&&LA(i+4)=='e'&&
78 LA(i+5)=='$';
79 }
80
81 protected boolean upcomingENDIF(int i) throws CharStreamException {
82 return LA(i)=='$'&&LA(i+1)=='e'&&LA(i+2)=='n'&&LA(i+3)=='d'&&LA(i+4)=='i'&&
83 LA(i+5)=='f'&&LA(i+6)=='$';
84 }
85
86 protected boolean upcomingAtEND(int i) throws CharStreamException {
87 return LA(i)=='$'&&LA(i+1)=='@'&&LA(i+2)=='e'&&LA(i+3)=='n'&&LA(i+4)=='d'&&LA(i+5)=='$';
88 }
89
90 protected boolean upcomingNewline(int i) throws CharStreamException {
91 return (LA(i)=='\r'&&LA(i+1)=='\n')||LA(i)=='\n';
92 }
93 public DefaultTemplateLexer(InputStream in) {
94 this(new ByteBuffer(in));
95 }
96 public DefaultTemplateLexer(Reader in) {
97 this(new CharBuffer(in));
98 }
99 public DefaultTemplateLexer(InputBuffer ib) {
100 this(new LexerSharedInputState(ib));
101 }
102 public DefaultTemplateLexer(LexerSharedInputState state) {
103 super(state);
104 caseSensitiveLiterals = true;
105 setCaseSensitive(true);
106 literals = new Hashtable();
107 }
108
109 public Token nextToken() throws TokenStreamException {
110 Token theRetToken=null;
111 tryAgain:
112 for (;;) {
113 Token _token = null;
114 int _ttype = Token.INVALID_TYPE;
115 resetText();
116 try { // for char stream error handling
117 try { // for lexical error handling
118 switch ( LA(1)) {
119 case '\n': case '\r':
120 {
121 mNEWLINE(true);
122 theRetToken=_returnToken;
123 break;
124 }
125 case '$':
126 {
127 mACTION(true);
128 theRetToken=_returnToken;
129 break;
130 }
131 default:
132 if (((_tokenSet_0.member(LA(1))))&&(LA(1)!='\r'&&LA(1)!='\n')) {
133 mLITERAL(true);
134 theRetToken=_returnToken;
135 }
136 else {
137 if (LA(1)==EOF_CHAR) {uponEOF(); _returnToken = makeToken(Token.EOF_TYPE);}
138 else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
139 }
140 }
141 if ( _returnToken==null ) continue tryAgain; // found SKIP token
142 _ttype = _returnToken.getType();
143 _ttype = testLiteralsTable(_ttype);
144 _returnToken.setType(_ttype);
145 return _returnToken;
146 }
147 catch (RecognitionException e) {
148 throw new TokenStreamRecognitionException(e);
149 }
150 }
151 catch (CharStreamException cse) {
152 if ( cse instanceof CharStreamIOException ) {
153 throw new TokenStreamIOException(((CharStreamIOException)cse).io);
154 }
155 else {
156 throw new TokenStreamException(cse.getMessage());
157 }
158 }
159 }
160 }
161
162 public final void mLITERAL(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
163 int _ttype; Token _token=null; int _begin=text.length();
164 _ttype = LITERAL;
165 int _saveIndex;
166 Token ind=null;
167
168 if (!(LA(1)!='\r'&&LA(1)!='\n'))
169 throw new SemanticException("LA(1)!='\\r'&&LA(1)!='\\n'");
170 {
171 int _cnt11=0;
172 _loop11:
173 do {
174
175 int loopStartIndex=text.length();
176 int col=getColumn();
177
178 if ((LA(1)=='\\') && (LA(2)=='$')) {
179 _saveIndex=text.length();
180 match('\\');
181 text.setLength(_saveIndex);
182 match('$');
183 }
184 else if ((LA(1)=='\\') && (LA(2)=='\\') && (true) && (true) && (true) && (true) && (true)) {
185 _saveIndex=text.length();
186 match('\\');
187 text.setLength(_saveIndex);
188 match('\\');
189 }
190 else if ((LA(1)=='\\') && (_tokenSet_1.member(LA(2))) && (true) && (true) && (true) && (true) && (true)) {
191 match('\\');
192 matchNot('$');
193 }
194 else if ((LA(1)=='\t'||LA(1)==' ') && (true) && (true) && (true) && (true) && (true) && (true)) {
195 mINDENT(true);
196 ind=_returnToken;
197
198 if ( col==1 && LA(1)=='$' ) {
199 // store indent in ASTExpr not in a literal
200 currentIndent=ind.getText();
201 text.setLength(loopStartIndex); // reset length to wack text
202 }
203 else currentIndent=null;
204
205 }
206 else if ((_tokenSet_0.member(LA(1))) && (true) && (true) && (true) && (true) && (true) && (true)) {
207 {
208 match(_tokenSet_0);
209 }
210 }
211 else {
212 if ( _cnt11>=1 ) { break _loop11; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
213 }
214
215 _cnt11++;
216 } while (true);
217 }
218 if ((new String(text.getBuffer(),_begin,text.length()-_begin)).length()==0) {_ttype = Token.SKIP;}
219 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
220 _token = makeToken(_ttype);
221 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
222 }
223 _returnToken = _token;
224 }
225
226 protected final void mINDENT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
227 int _ttype; Token _token=null; int _begin=text.length();
228 _ttype = INDENT;
229 int _saveIndex;
230
231 {
232 int _cnt76=0;
233 _loop76:
234 do {
235 if ((LA(1)==' ') && (true) && (true) && (true) && (true) && (true) && (true)) {
236 match(' ');
237 }
238 else if ((LA(1)=='\t') && (true) && (true) && (true) && (true) && (true) && (true)) {
239 match('\t');
240 }
241 else {
242 if ( _cnt76>=1 ) { break _loop76; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
243 }
244
245 _cnt76++;
246 } while (true);
247 }
248 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
249 _token = makeToken(_ttype);
250 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
251 }
252 _returnToken = _token;
253 }
254
255 public final void mNEWLINE(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
256 int _ttype; Token _token=null; int _begin=text.length();
257 _ttype = NEWLINE;
258 int _saveIndex;
259
260 {
261 switch ( LA(1)) {
262 case '\r':
263 {
264 match('\r');
265 break;
266 }
267 case '\n':
268 {
269 break;
270 }
271 default:
272 {
273 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
274 }
275 }
276 }
277 match('\n');
278 newline(); currentIndent=null;
279 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
280 _token = makeToken(_ttype);
281 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
282 }
283 _returnToken = _token;
284 }
285
286 public final void mACTION(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
287 int _ttype; Token _token=null; int _begin=text.length();
288 _ttype = ACTION;
289 int _saveIndex;
290
291 int startCol = getColumn();
292
293
294 if ((LA(1)=='$') && (LA(2)=='\\') && (LA(3)=='\\') && (LA(4)=='$') && (_tokenSet_2.member(LA(5))) && (true) && (true)) {
295 mLINE_BREAK(false);
296 _ttype = Token.SKIP;
297 }
298 else if ((LA(1)=='$') && (LA(2)=='\\') && (_tokenSet_3.member(LA(3))) && (_tokenSet_4.member(LA(4))) && (true) && (true) && (true)) {
299 StringBuffer buf = new StringBuffer(); char uc = '\u0000';
300 _saveIndex=text.length();
301 match('$');
302 text.setLength(_saveIndex);
303 {
304 int _cnt16=0;
305 _loop16:
306 do {
307 if ((LA(1)=='\\')) {
308 uc=mESC_CHAR(false);
309 buf.append(uc);
310 }
311 else {
312 if ( _cnt16>=1 ) { break _loop16; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
313 }
314
315 _cnt16++;
316 } while (true);
317 }
318 _saveIndex=text.length();
319 match('$');
320 text.setLength(_saveIndex);
321 text.setLength(_begin); text.append(buf.toString()); _ttype = LITERAL;
322 }
323 else if ((LA(1)=='$') && (LA(2)=='!') && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && ((LA(4) >= '\u0001' && LA(4) <= '\ufffe')) && (true) && (true) && (true)) {
324 mCOMMENT(false);
325 _ttype = Token.SKIP;
326 }
327 else if ((LA(1)=='$') && (_tokenSet_1.member(LA(2))) && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && (true) && (true) && (true) && (true)) {
328 {
329 if ((LA(1)=='$') && (LA(2)=='i') && (LA(3)=='f') && (LA(4)==' '||LA(4)=='(') && (_tokenSet_5.member(LA(5))) && ((LA(6) >= '\u0001' && LA(6) <= '\ufffe')) && ((LA(7) >= '\u0001' && LA(7) <= '\ufffe'))) {
330 _saveIndex=text.length();
331 match('$');
332 text.setLength(_saveIndex);
333 match("if");
334 {
335 _loop19:
336 do {
337 if ((LA(1)==' ')) {
338 _saveIndex=text.length();
339 match(' ');
340 text.setLength(_saveIndex);
341 }
342 else {
343 break _loop19;
344 }
345
346 } while (true);
347 }
348 match("(");
349 mIF_EXPR(false);
350 match(")");
351 _saveIndex=text.length();
352 match('$');
353 text.setLength(_saveIndex);
354 _ttype = TemplateParser.IF;
355 {
356 if ((LA(1)=='\n'||LA(1)=='\r')) {
357 {
358 switch ( LA(1)) {
359 case '\r':
360 {
361 _saveIndex=text.length();
362 match('\r');
363 text.setLength(_saveIndex);
364 break;
365 }
366 case '\n':
367 {
368 break;
369 }
370 default:
371 {
372 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
373 }
374 }
375 }
376 _saveIndex=text.length();
377 match('\n');
378 text.setLength(_saveIndex);
379 newline();
380 }
381 else {
382 }
383
384 }
385 }
386 else if ((LA(1)=='$') && (LA(2)=='e') && (LA(3)=='l') && (LA(4)=='s') && (LA(5)=='e') && (LA(6)=='i') && (LA(7)=='f')) {
387 _saveIndex=text.length();
388 match('$');
389 text.setLength(_saveIndex);
390 match("elseif");
391 {
392 _loop23:
393 do {
394 if ((LA(1)==' ')) {
395 _saveIndex=text.length();
396 match(' ');
397 text.setLength(_saveIndex);
398 }
399 else {
400 break _loop23;
401 }
402
403 } while (true);
404 }
405 match("(");
406 mIF_EXPR(false);
407 match(")");
408 _saveIndex=text.length();
409 match('$');
410 text.setLength(_saveIndex);
411 _ttype = TemplateParser.ELSEIF;
412 {
413 if ((LA(1)=='\n'||LA(1)=='\r')) {
414 {
415 switch ( LA(1)) {
416 case '\r':
417 {
418 _saveIndex=text.length();
419 match('\r');
420 text.setLength(_saveIndex);
421 break;
422 }
423 case '\n':
424 {
425 break;
426 }
427 default:
428 {
429 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
430 }
431 }
432 }
433 _saveIndex=text.length();
434 match('\n');
435 text.setLength(_saveIndex);
436 newline();
437 }
438 else {
439 }
440
441 }
442 }
443 else if ((LA(1)=='$') && (LA(2)=='e') && (LA(3)=='n') && (LA(4)=='d') && (LA(5)=='i') && (LA(6)=='f') && (LA(7)=='$')) {
444 _saveIndex=text.length();
445 match('$');
446 text.setLength(_saveIndex);
447 match("endif");
448 _saveIndex=text.length();
449 match('$');
450 text.setLength(_saveIndex);
451 _ttype = TemplateParser.ENDIF;
452 {
453 if (((LA(1)=='\n'||LA(1)=='\r'))&&(startCol==1)) {
454 {
455 switch ( LA(1)) {
456 case '\r':
457 {
458 _saveIndex=text.length();
459 match('\r');
460 text.setLength(_saveIndex);
461 break;
462 }
463 case '\n':
464 {
465 break;
466 }
467 default:
468 {
469 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
470 }
471 }
472 }
473 _saveIndex=text.length();
474 match('\n');
475 text.setLength(_saveIndex);
476 newline();
477 }
478 else {
479 }
480
481 }
482 }
483 else if ((LA(1)=='$') && (LA(2)=='e') && (LA(3)=='l') && (LA(4)=='s') && (LA(5)=='e') && (LA(6)=='$') && (true)) {
484 _saveIndex=text.length();
485 match('$');
486 text.setLength(_saveIndex);
487 match("else");
488 _saveIndex=text.length();
489 match('$');
490 text.setLength(_saveIndex);
491 _ttype = TemplateParser.ELSE;
492 {
493 if ((LA(1)=='\n'||LA(1)=='\r')) {
494 {
495 switch ( LA(1)) {
496 case '\r':
497 {
498 _saveIndex=text.length();
499 match('\r');
500 text.setLength(_saveIndex);
501 break;
502 }
503 case '\n':
504 {
505 break;
506 }
507 default:
508 {
509 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
510 }
511 }
512 }
513 _saveIndex=text.length();
514 match('\n');
515 text.setLength(_saveIndex);
516 newline();
517 }
518 else {
519 }
520
521 }
522 }
523 else if ((LA(1)=='$') && (LA(2)=='@') && (_tokenSet_6.member(LA(3))) && ((LA(4) >= '\u0001' && LA(4) <= '\ufffe')) && ((LA(5) >= '\u0001' && LA(5) <= '\ufffe')) && ((LA(6) >= '\u0001' && LA(6) <= '\ufffe')) && (true)) {
524 _saveIndex=text.length();
525 match('$');
526 text.setLength(_saveIndex);
527 _saveIndex=text.length();
528 match('@');
529 text.setLength(_saveIndex);
530 {
531 int _cnt32=0;
532 _loop32:
533 do {
534 if ((_tokenSet_6.member(LA(1)))) {
535 {
536 match(_tokenSet_6);
537 }
538 }
539 else {
540 if ( _cnt32>=1 ) { break _loop32; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
541 }
542
543 _cnt32++;
544 } while (true);
545 }
546 {
547 switch ( LA(1)) {
548 case '(':
549 {
550 _saveIndex=text.length();
551 match("()");
552 text.setLength(_saveIndex);
553 _saveIndex=text.length();
554 match('$');
555 text.setLength(_saveIndex);
556 _ttype = TemplateParser.REGION_REF;
557 break;
558 }
559 case '$':
560 {
561 _saveIndex=text.length();
562 match('$');
563 text.setLength(_saveIndex);
564 _ttype = TemplateParser.REGION_DEF;
565 String t=new String(text.getBuffer(),_begin,text.length()-_begin);
566 text.setLength(_begin); text.append(t+"::=");
567
568 {
569 if ((LA(1)=='\n'||LA(1)=='\r') && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && (true) && (true) && (true) && (true)) {
570 {
571 switch ( LA(1)) {
572 case '\r':
573 {
574 _saveIndex=text.length();
575 match('\r');
576 text.setLength(_saveIndex);
577 break;
578 }
579 case '\n':
580 {
581 break;
582 }
583 default:
584 {
585 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
586 }
587 }
588 }
589 _saveIndex=text.length();
590 match('\n');
591 text.setLength(_saveIndex);
592 newline();
593 }
594 else if (((LA(1) >= '\u0001' && LA(1) <= '\ufffe')) && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && (true) && (true) && (true) && (true) && (true)) {
595 }
596 else {
597 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
598 }
599
600 }
601 boolean atLeft = false;
602 {
603 int _cnt39=0;
604 _loop39:
605 do {
606 if ((((LA(1) >= '\u0001' && LA(1) <= '\ufffe')) && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && (true) && (true) && (true) && (true) && (true))&&(!(upcomingAtEND(1)||(upcomingNewline(1)&&upcomingAtEND(2))))) {
607 {
608 if ((LA(1)=='\n'||LA(1)=='\r') && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && (true) && (true) && (true) && (true) && (true)) {
609 {
610 switch ( LA(1)) {
611 case '\r':
612 {
613 match('\r');
614 break;
615 }
616 case '\n':
617 {
618 break;
619 }
620 default:
621 {
622 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
623 }
624 }
625 }
626 match('\n');
627 newline(); atLeft = true;
628 }
629 else if (((LA(1) >= '\u0001' && LA(1) <= '\ufffe')) && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && (true) && (true) && (true) && (true) && (true)) {
630 matchNot(EOF_CHAR);
631 atLeft = false;
632 }
633 else {
634 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
635 }
636
637 }
638 }
639 else {
640 if ( _cnt39>=1 ) { break _loop39; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
641 }
642
643 _cnt39++;
644 } while (true);
645 }
646 {
647 if ((LA(1)=='\n'||LA(1)=='\r') && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && (true) && (true) && (true) && (true) && (true)) {
648 {
649 switch ( LA(1)) {
650 case '\r':
651 {
652 _saveIndex=text.length();
653 match('\r');
654 text.setLength(_saveIndex);
655 break;
656 }
657 case '\n':
658 {
659 break;
660 }
661 default:
662 {
663 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
664 }
665 }
666 }
667 _saveIndex=text.length();
668 match('\n');
669 text.setLength(_saveIndex);
670 newline(); atLeft = true;
671 }
672 else if (((LA(1) >= '\u0001' && LA(1) <= '\ufffe')) && (true) && (true) && (true) && (true) && (true) && (true)) {
673 }
674 else {
675 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
676 }
677
678 }
679 {
680 if ((LA(1)=='$') && (LA(2)=='@')) {
681 _saveIndex=text.length();
682 match("$@end$");
683 text.setLength(_saveIndex);
684 }
685 else if (((LA(1) >= '\u0001' && LA(1) <= '\ufffe')) && (true)) {
686 matchNot(EOF_CHAR);
687 self.error("missing region "+t+" $@end$ tag");
688 }
689 else {
690 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
691 }
692
693 }
694 {
695 if (((LA(1)=='\n'||LA(1)=='\r'))&&(atLeft)) {
696 {
697 switch ( LA(1)) {
698 case '\r':
699 {
700 _saveIndex=text.length();
701 match('\r');
702 text.setLength(_saveIndex);
703 break;
704 }
705 case '\n':
706 {
707 break;
708 }
709 default:
710 {
711 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
712 }
713 }
714 }
715 _saveIndex=text.length();
716 match('\n');
717 text.setLength(_saveIndex);
718 newline();
719 }
720 else {
721 }
722
723 }
724 break;
725 }
726 default:
727 {
728 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
729 }
730 }
731 }
732 }
733 else if ((LA(1)=='$') && (_tokenSet_1.member(LA(2))) && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && (true) && (true) && (true) && (true)) {
734 _saveIndex=text.length();
735 match('$');
736 text.setLength(_saveIndex);
737 mEXPR(false);
738 _saveIndex=text.length();
739 match('$');
740 text.setLength(_saveIndex);
741 }
742 else {
743 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
744 }
745
746 }
747
748 ChunkToken t = new ChunkToken(_ttype, new String(text.getBuffer(),_begin,text.length()-_begin), currentIndent);
749 _token = t;
750
751 }
752 else {
753 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
754 }
755
756 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
757 _token = makeToken(_ttype);
758 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
759 }
760 _returnToken = _token;
761 }
762
763 protected final void mLINE_BREAK(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
764 int _ttype; Token _token=null; int _begin=text.length();
765 _ttype = LINE_BREAK;
766 int _saveIndex;
767
768 match("$\\\\$");
769 {
770 switch ( LA(1)) {
771 case '\t': case ' ':
772 {
773 mINDENT(false);
774 break;
775 }
776 case '\n': case '\r':
777 {
778 break;
779 }
780 default:
781 {
782 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
783 }
784 }
785 }
786 {
787 switch ( LA(1)) {
788 case '\r':
789 {
790 match('\r');
791 break;
792 }
793 case '\n':
794 {
795 break;
796 }
797 default:
798 {
799 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
800 }
801 }
802 }
803 match('\n');
804 newline();
805 {
806 if ((LA(1)=='\t'||LA(1)==' ')) {
807 mINDENT(false);
808 }
809 else {
810 }
811
812 }
813 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
814 _token = makeToken(_ttype);
815 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
816 }
817 _returnToken = _token;
818 }
819
820 protected final char mESC_CHAR(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
821 char uc='\u0000';
822 int _ttype; Token _token=null; int _begin=text.length();
823 _ttype = ESC_CHAR;
824 int _saveIndex;
825 Token a=null;
826 Token b=null;
827 Token c=null;
828 Token d=null;
829
830 if ((LA(1)=='\\') && (LA(2)=='n')) {
831 _saveIndex=text.length();
832 match("\\n");
833 text.setLength(_saveIndex);
834 uc = '\n';
835 }
836 else if ((LA(1)=='\\') && (LA(2)=='r')) {
837 _saveIndex=text.length();
838 match("\\r");
839 text.setLength(_saveIndex);
840 uc = '\r';
841 }
842 else if ((LA(1)=='\\') && (LA(2)=='t')) {
843 _saveIndex=text.length();
844 match("\\t");
845 text.setLength(_saveIndex);
846 uc = '\t';
847 }
848 else if ((LA(1)=='\\') && (LA(2)==' ')) {
849 _saveIndex=text.length();
850 match("\\ ");
851 text.setLength(_saveIndex);
852 uc = ' ';
853 }
854 else if ((LA(1)=='\\') && (LA(2)=='u')) {
855 _saveIndex=text.length();
856 match("\\u");
857 text.setLength(_saveIndex);
858 _saveIndex=text.length();
859 mHEX(true);
860 text.setLength(_saveIndex);
861 a=_returnToken;
862 _saveIndex=text.length();
863 mHEX(true);
864 text.setLength(_saveIndex);
865 b=_returnToken;
866 _saveIndex=text.length();
867 mHEX(true);
868 text.setLength(_saveIndex);
869 c=_returnToken;
870 _saveIndex=text.length();
871 mHEX(true);
872 text.setLength(_saveIndex);
873 d=_returnToken;
874 uc = (char)Integer.parseInt(a.getText()+b.getText()+c.getText()+d.getText(), 16);
875 }
876 else {
877 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
878 }
879
880 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
881 _token = makeToken(_ttype);
882 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
883 }
884 _returnToken = _token;
885 return uc;
886 }
887
888 protected final void mCOMMENT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
889 int _ttype; Token _token=null; int _begin=text.length();
890 _ttype = COMMENT;
891 int _saveIndex;
892
893 int startCol = getColumn();
894
895
896 match("$!");
897 {
898 _loop80:
899 do {
900 // nongreedy exit test
901 if ((LA(1)=='!') && (LA(2)=='$') && (true) && (true) && (true) && (true) && (true)) break _loop80;
902 if ((LA(1)=='\n'||LA(1)=='\r') && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && (true) && (true) && (true) && (true)) {
903 {
904 switch ( LA(1)) {
905 case '\r':
906 {
907 match('\r');
908 break;
909 }
910 case '\n':
911 {
912 break;
913 }
914 default:
915 {
916 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
917 }
918 }
919 }
920 match('\n');
921 newline();
922 }
923 else if (((LA(1) >= '\u0001' && LA(1) <= '\ufffe')) && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && (true) && (true) && (true) && (true)) {
924 matchNot(EOF_CHAR);
925 }
926 else {
927 break _loop80;
928 }
929
930 } while (true);
931 }
932 match("!$");
933 {
934 if (((LA(1)=='\n'||LA(1)=='\r'))&&(startCol==1)) {
935 {
936 switch ( LA(1)) {
937 case '\r':
938 {
939 match('\r');
940 break;
941 }
942 case '\n':
943 {
944 break;
945 }
946 default:
947 {
948 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
949 }
950 }
951 }
952 match('\n');
953 newline();
954 }
955 else {
956 }
957
958 }
959 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
960 _token = makeToken(_ttype);
961 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
962 }
963 _returnToken = _token;
964 }
965
966 protected final void mIF_EXPR(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
967 int _ttype; Token _token=null; int _begin=text.length();
968 _ttype = IF_EXPR;
969 int _saveIndex;
970
971 {
972 int _cnt64=0;
973 _loop64:
974 do {
975 switch ( LA(1)) {
976 case '\\':
977 {
978 mESC(false);
979 break;
980 }
981 case '\n': case '\r':
982 {
983 {
984 switch ( LA(1)) {
985 case '\r':
986 {
987 match('\r');
988 break;
989 }
990 case '\n':
991 {
992 break;
993 }
994 default:
995 {
996 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
997 }
998 }
999 }
1000 match('\n');
1001 newline();
1002 break;
1003 }
1004 case '{':
1005 {
1006 mSUBTEMPLATE(false);
1007 break;
1008 }
1009 case '(':
1010 {
1011 mNESTED_PARENS(false);
1012 break;
1013 }
1014 default:
1015 if ((_tokenSet_7.member(LA(1)))) {
1016 matchNot(')');
1017 }
1018 else {
1019 if ( _cnt64>=1 ) { break _loop64; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
1020 }
1021 }
1022 _cnt64++;
1023 } while (true);
1024 }
1025 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
1026 _token = makeToken(_ttype);
1027 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
1028 }
1029 _returnToken = _token;
1030 }
1031
1032 protected final void mEXPR(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
1033 int _ttype; Token _token=null; int _begin=text.length();
1034 _ttype = EXPR;
1035 int _saveIndex;
1036
1037 {
1038 int _cnt52=0;
1039 _loop52:
1040 do {
1041 switch ( LA(1)) {
1042 case '\\':
1043 {
1044 mESC(false);
1045 break;
1046 }
1047 case '\n': case '\r':
1048 {
1049 {
1050 switch ( LA(1)) {
1051 case '\r':
1052 {
1053 match('\r');
1054 break;
1055 }
1056 case '\n':
1057 {
1058 break;
1059 }
1060 default:
1061 {
1062 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
1063 }
1064 }
1065 }
1066 match('\n');
1067 newline();
1068 break;
1069 }
1070 case '{':
1071 {
1072 mSUBTEMPLATE(false);
1073 break;
1074 }
1075 default:
1076 if ((LA(1)=='+'||LA(1)=='=') && (LA(2)=='"'||LA(2)=='<')) {
1077 {
1078 switch ( LA(1)) {
1079 case '=':
1080 {
1081 match('=');
1082 break;
1083 }
1084 case '+':
1085 {
1086 match('+');
1087 break;
1088 }
1089 default:
1090 {
1091 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
1092 }
1093 }
1094 }
1095 mTEMPLATE(false);
1096 }
1097 else if ((LA(1)=='+'||LA(1)=='=') && (LA(2)=='{')) {
1098 {
1099 switch ( LA(1)) {
1100 case '=':
1101 {
1102 match('=');
1103 break;
1104 }
1105 case '+':
1106 {
1107 match('+');
1108 break;
1109 }
1110 default:
1111 {
1112 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
1113 }
1114 }
1115 }
1116 mSUBTEMPLATE(false);
1117 }
1118 else if ((LA(1)=='+'||LA(1)=='=') && (_tokenSet_8.member(LA(2)))) {
1119 {
1120 switch ( LA(1)) {
1121 case '=':
1122 {
1123 match('=');
1124 break;
1125 }
1126 case '+':
1127 {
1128 match('+');
1129 break;
1130 }
1131 default:
1132 {
1133 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
1134 }
1135 }
1136 }
1137 {
1138 match(_tokenSet_8);
1139 }
1140 }
1141 else if ((_tokenSet_9.member(LA(1)))) {
1142 matchNot('$');
1143 }
1144 else {
1145 if ( _cnt52>=1 ) { break _loop52; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
1146 }
1147 }
1148 _cnt52++;
1149 } while (true);
1150 }
1151 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
1152 _token = makeToken(_ttype);
1153 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
1154 }
1155 _returnToken = _token;
1156 }
1157
1158 protected final void mESC(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
1159 int _ttype; Token _token=null; int _begin=text.length();
1160 _ttype = ESC;
1161 int _saveIndex;
1162
1163 match('\\');
1164 matchNot(EOF_CHAR);
1165 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
1166 _token = makeToken(_ttype);
1167 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
1168 }
1169 _returnToken = _token;
1170 }
1171
1172 protected final void mSUBTEMPLATE(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
1173 int _ttype; Token _token=null; int _begin=text.length();
1174 _ttype = SUBTEMPLATE;
1175 int _saveIndex;
1176
1177 match('{');
1178 {
1179 _loop70:
1180 do {
1181 switch ( LA(1)) {
1182 case '{':
1183 {
1184 mSUBTEMPLATE(false);
1185 break;
1186 }
1187 case '\\':
1188 {
1189 mESC(false);
1190 break;
1191 }
1192 default:
1193 if ((_tokenSet_10.member(LA(1)))) {
1194 matchNot('}');
1195 }
1196 else {
1197 break _loop70;
1198 }
1199 }
1200 } while (true);
1201 }
1202 match('}');
1203 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
1204 _token = makeToken(_ttype);
1205 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
1206 }
1207 _returnToken = _token;
1208 }
1209
1210 protected final void mTEMPLATE(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
1211 int _ttype; Token _token=null; int _begin=text.length();
1212 _ttype = TEMPLATE;
1213 int _saveIndex;
1214
1215 switch ( LA(1)) {
1216 case '"':
1217 {
1218 match('"');
1219 {
1220 _loop55:
1221 do {
1222 if ((LA(1)=='\\')) {
1223 mESC(false);
1224 }
1225 else if ((_tokenSet_11.member(LA(1)))) {
1226 matchNot('"');
1227 }
1228 else {
1229 break _loop55;
1230 }
1231
1232 } while (true);
1233 }
1234 match('"');
1235 break;
1236 }
1237 case '<':
1238 {
1239 match("<<");
1240 {
1241 if ((LA(1)=='\n'||LA(1)=='\r') && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && ((LA(4) >= '\u0001' && LA(4) <= '\ufffe')) && (true) && (true) && (true)) {
1242 {
1243 switch ( LA(1)) {
1244 case '\r':
1245 {
1246 _saveIndex=text.length();
1247 match('\r');
1248 text.setLength(_saveIndex);
1249 break;
1250 }
1251 case '\n':
1252 {
1253 break;
1254 }
1255 default:
1256 {
1257 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
1258 }
1259 }
1260 }
1261 _saveIndex=text.length();
1262 match('\n');
1263 text.setLength(_saveIndex);
1264 newline();
1265 }
1266 else if (((LA(1) >= '\u0001' && LA(1) <= '\ufffe')) && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && (true) && (true) && (true) && (true)) {
1267 }
1268 else {
1269 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
1270 }
1271
1272 }
1273 {
1274 _loop60:
1275 do {
1276 // nongreedy exit test
1277 if ((LA(1)=='>') && (LA(2)=='>') && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && (true) && (true) && (true) && (true)) break _loop60;
1278 if (((LA(1)=='\r') && (LA(2)=='\n') && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && ((LA(4) >= '\u0001' && LA(4) <= '\ufffe')) && ((LA(5) >= '\u0001' && LA(5) <= '\ufffe')) && (true) && (true))&&(LA(3)=='>'&&LA(4)=='>')) {
1279 _saveIndex=text.length();
1280 match('\r');
1281 text.setLength(_saveIndex);
1282 _saveIndex=text.length();
1283 match('\n');
1284 text.setLength(_saveIndex);
1285 newline();
1286 }
1287 else if (((LA(1)=='\n') && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && ((LA(4) >= '\u0001' && LA(4) <= '\ufffe')) && (true) && (true) && (true))&&(LA(2)=='>'&&LA(3)=='>')) {
1288 _saveIndex=text.length();
1289 match('\n');
1290 text.setLength(_saveIndex);
1291 newline();
1292 }
1293 else if ((LA(1)=='\n'||LA(1)=='\r') && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && ((LA(4) >= '\u0001' && LA(4) <= '\ufffe')) && (true) && (true) && (true)) {
1294 {
1295 switch ( LA(1)) {
1296 case '\r':
1297 {
1298 match('\r');
1299 break;
1300 }
1301 case '\n':
1302 {
1303 break;
1304 }
1305 default:
1306 {
1307 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
1308 }
1309 }
1310 }
1311 match('\n');
1312 newline();
1313 }
1314 else if (((LA(1) >= '\u0001' && LA(1) <= '\ufffe')) && ((LA(2) >= '\u0001' && LA(2) <= '\ufffe')) && ((LA(3) >= '\u0001' && LA(3) <= '\ufffe')) && ((LA(4) >= '\u0001' && LA(4) <= '\ufffe')) && (true) && (true) && (true)) {
1315 matchNot(EOF_CHAR);
1316 }
1317 else {
1318 break _loop60;
1319 }
1320
1321 } while (true);
1322 }
1323 match(">>");
1324 break;
1325 }
1326 default:
1327 {
1328 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
1329 }
1330 }
1331 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
1332 _token = makeToken(_ttype);
1333 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
1334 }
1335 _returnToken = _token;
1336 }
1337
1338 protected final void mNESTED_PARENS(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
1339 int _ttype; Token _token=null; int _begin=text.length();
1340 _ttype = NESTED_PARENS;
1341 int _saveIndex;
1342
1343 match('(');
1344 {
1345 int _cnt73=0;
1346 _loop73:
1347 do {
1348 switch ( LA(1)) {
1349 case '(':
1350 {
1351 mNESTED_PARENS(false);
1352 break;
1353 }
1354 case '\\':
1355 {
1356 mESC(false);
1357 break;
1358 }
1359 default:
1360 if ((_tokenSet_12.member(LA(1)))) {
1361 matchNot(')');
1362 }
1363 else {
1364 if ( _cnt73>=1 ) { break _loop73; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
1365 }
1366 }
1367 _cnt73++;
1368 } while (true);
1369 }
1370 match(')');
1371 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
1372 _token = makeToken(_ttype);
1373 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
1374 }
1375 _returnToken = _token;
1376 }
1377
1378 protected final void mHEX(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
1379 int _ttype; Token _token=null; int _begin=text.length();
1380 _ttype = HEX;
1381 int _saveIndex;
1382
1383 switch ( LA(1)) {
1384 case '0': case '1': case '2': case '3':
1385 case '4': case '5': case '6': case '7':
1386 case '8': case '9':
1387 {
1388 matchRange('0','9');
1389 break;
1390 }
1391 case 'A': case 'B': case 'C': case 'D':
1392 case 'E': case 'F':
1393 {
1394 matchRange('A','F');
1395 break;
1396 }
1397 case 'a': case 'b': case 'c': case 'd':
1398 case 'e': case 'f':
1399 {
1400 matchRange('a','f');
1401 break;
1402 }
1403 default:
1404 {
1405 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
1406 }
1407 }
1408 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
1409 _token = makeToken(_ttype);
1410 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
1411 }
1412 _returnToken = _token;
1413 }
1414
1415
1416 private static final long[] mk_tokenSet_0() {
1417 long[] data = new long[2048];
1418 data[0]=-68719485954L;
1419 for (int i = 1; i<=1022; i++) { data[i]=-1L; }
1420 data[1023]=9223372036854775807L;
1421 return data;
1422 }
1423 public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0());
1424 private static final long[] mk_tokenSet_1() {
1425 long[] data = new long[2048];
1426 data[0]=-68719476738L;
1427 for (int i = 1; i<=1022; i++) { data[i]=-1L; }
1428 data[1023]=9223372036854775807L;
1429 return data;
1430 }
1431 public static final BitSet _tokenSet_1 = new BitSet(mk_tokenSet_1());
1432 private static final long[] mk_tokenSet_2() {
1433 long[] data = new long[1025];
1434 data[0]=4294977024L;
1435 return data;
1436 }
1437 public static final BitSet _tokenSet_2 = new BitSet(mk_tokenSet_2());
1438 private static final long[] mk_tokenSet_3() {
1439 long[] data = new long[1025];
1440 data[0]=4294967296L;
1441 data[1]=14707067533131776L;
1442 return data;
1443 }
1444 public static final BitSet _tokenSet_3 = new BitSet(mk_tokenSet_3());
1445 private static final long[] mk_tokenSet_4() {
1446 long[] data = new long[1025];
1447 data[0]=287948969894477824L;
1448 data[1]=541434314878L;
1449 return data;
1450 }
1451 public static final BitSet _tokenSet_4 = new BitSet(mk_tokenSet_4());
1452 private static final long[] mk_tokenSet_5() {
1453 long[] data = new long[2048];
1454 data[0]=-2199023255554L;
1455 for (int i = 1; i<=1022; i++) { data[i]=-1L; }
1456 data[1023]=9223372036854775807L;
1457 return data;
1458 }
1459 public static final BitSet _tokenSet_5 = new BitSet(mk_tokenSet_5());
1460 private static final long[] mk_tokenSet_6() {
1461 long[] data = new long[2048];
1462 data[0]=-1168231104514L;
1463 for (int i = 1; i<=1022; i++) { data[i]=-1L; }
1464 data[1023]=9223372036854775807L;
1465 return data;
1466 }
1467 public static final BitSet _tokenSet_6 = new BitSet(mk_tokenSet_6());
1468 private static final long[] mk_tokenSet_7() {
1469 long[] data = new long[2048];
1470 data[0]=-3298534892546L;
1471 data[1]=-576460752571858945L;
1472 for (int i = 2; i<=1022; i++) { data[i]=-1L; }
1473 data[1023]=9223372036854775807L;
1474 return data;
1475 }
1476 public static final BitSet _tokenSet_7 = new BitSet(mk_tokenSet_7());
1477 private static final long[] mk_tokenSet_8() {
1478 long[] data = new long[2048];
1479 data[0]=-1152921521786716162L;
1480 data[1]=-576460752303423489L;
1481 for (int i = 2; i<=1022; i++) { data[i]=-1L; }
1482 data[1023]=9223372036854775807L;
1483 return data;
1484 }
1485 public static final BitSet _tokenSet_8 = new BitSet(mk_tokenSet_8());
1486 private static final long[] mk_tokenSet_9() {
1487 long[] data = new long[2048];
1488 data[0]=-2305851874026202114L;
1489 data[1]=-576460752571858945L;
1490 for (int i = 2; i<=1022; i++) { data[i]=-1L; }
1491 data[1023]=9223372036854775807L;
1492 return data;
1493 }
1494 public static final BitSet _tokenSet_9 = new BitSet(mk_tokenSet_9());
1495 private static final long[] mk_tokenSet_10() {
1496 long[] data = new long[2048];
1497 data[0]=-2L;
1498 data[1]=-2882303761785552897L;
1499 for (int i = 2; i<=1022; i++) { data[i]=-1L; }
1500 data[1023]=9223372036854775807L;
1501 return data;
1502 }
1503 public static final BitSet _tokenSet_10 = new BitSet(mk_tokenSet_10());
1504 private static final long[] mk_tokenSet_11() {
1505 long[] data = new long[2048];
1506 data[0]=-17179869186L;
1507 data[1]=-268435457L;
1508 for (int i = 2; i<=1022; i++) { data[i]=-1L; }
1509 data[1023]=9223372036854775807L;
1510 return data;
1511 }
1512 public static final BitSet _tokenSet_11 = new BitSet(mk_tokenSet_11());
1513 private static final long[] mk_tokenSet_12() {
1514 long[] data = new long[2048];
1515 data[0]=-3298534883330L;
1516 data[1]=-268435457L;
1517 for (int i = 2; i<=1022; i++) { data[i]=-1L; }
1518 data[1023]=9223372036854775807L;
1519 return data;
1520 }
1521 public static final BitSet _tokenSet_12 = new BitSet(mk_tokenSet_12());
1522
1523 }
0 SMAP
1 DefaultTemplateLexer.java
2 G
3 *S G
4 *F
5 + 0 template.g
6 template.g
7 *L
8 0:122
9 0:128
10 0:134
11 1:3
12 1:4
13 1:5
14 1:6
15 1:8
16 1:9
17 1:10
18 1:11
19 1:12
20 1:13
21 1:14
22 1:15
23 1:16
24 1:17
25 1:19
26 1:20
27 1:21
28 1:22
29 1:23
30 1:24
31 1:25
32 1:26
33 1:27
34 1:28
35 1:29
36 1:30
37 1:31
38 1:32
39 206:65
40 207:66
41 209:68
42 210:69
43 211:70
44 212:71
45 214:73
46 215:74
47 216:75
48 218:77
49 219:78
50 220:79
51 221:80
52 223:82
53 224:83
54 225:84
55 226:85
56 228:87
57 229:88
58 230:89
59 232:91
60 233:92
61 234:93
62 237:163
63 237:164
64 237:165
65 237:166
66 237:169
67 237:170
68 237:220
69 237:221
70 237:222
71 237:223
72 237:224
73 237:225
74 239:172
75 239:173
76 239:174
77 239:184
78 239:190
79 239:194
80 239:206
81 239:211
82 239:212
83 239:213
84 239:214
85 239:216
86 239:217
87 239:218
88 240:176
89 241:177
90 244:179
91 244:180
92 244:181
93 244:182
94 244:183
95 245:185
96 245:186
97 245:187
98 245:188
99 245:189
100 246:191
101 246:192
102 246:193
103 247:167
104 247:195
105 247:196
106 247:197
107 249:199
108 250:200
109 251:201
110 252:202
111 253:203
112 254:204
113 256:207
114 256:209
115 258:219
116 261:256
117 261:257
118 261:258
119 261:259
120 261:280
121 261:281
122 261:282
123 261:283
124 261:284
125 261:285
126 262:262
127 262:263
128 262:264
129 262:265
130 262:272
131 262:273
132 262:274
133 262:275
134 262:276
135 262:278
136 262:279
137 265:287
138 265:288
139 265:289
140 265:290
141 265:298
142 265:323
143 265:327
144 265:752
145 265:753
146 265:754
147 265:755
148 265:757
149 265:758
150 265:759
151 265:760
152 265:761
153 265:762
154 266:292
155 272:295
156 272:296
157 272:297
158 274:299
159 274:300
160 275:301
161 275:302
162 275:303
163 275:305
164 275:306
165 275:307
166 275:308
167 275:309
168 275:310
169 275:311
170 275:312
171 275:313
172 275:314
173 275:316
174 275:317
175 275:318
176 275:319
177 275:320
178 275:321
179 276:322
180 277:324
181 277:325
182 277:326
183 278:328
184 278:386
185 278:443
186 278:483
187 278:523
188 278:733
189 278:742
190 278:743
191 278:744
192 278:745
193 282:330
194 282:331
195 282:332
196 282:333
197 282:334
198 282:335
199 282:336
200 282:337
201 282:338
202 282:339
203 282:340
204 282:341
205 282:342
206 282:343
207 282:344
208 282:345
209 282:347
210 282:348
211 282:349
212 282:350
213 282:351
214 282:352
215 282:353
216 282:354
217 282:355
218 283:357
219 283:359
220 283:360
221 283:361
222 283:362
223 283:363
224 283:364
225 283:371
226 283:372
227 283:373
228 283:374
229 283:375
230 283:377
231 283:378
232 283:379
233 283:380
234 283:381
235 283:383
236 284:387
237 284:388
238 284:389
239 284:390
240 284:391
241 284:392
242 284:393
243 284:394
244 284:395
245 284:396
246 284:397
247 284:398
248 284:399
249 284:400
250 284:401
251 284:402
252 284:404
253 284:405
254 284:406
255 284:407
256 284:408
257 284:409
258 284:410
259 284:411
260 284:412
261 285:414
262 285:416
263 285:417
264 285:418
265 285:419
266 285:420
267 285:421
268 285:428
269 285:429
270 285:430
271 285:431
272 285:432
273 285:434
274 285:435
275 285:436
276 285:437
277 285:438
278 285:440
279 286:484
280 286:485
281 286:486
282 286:487
283 286:488
284 286:489
285 286:490
286 286:491
287 286:492
288 287:494
289 287:496
290 287:497
291 287:498
292 287:499
293 287:500
294 287:501
295 287:508
296 287:509
297 287:510
298 287:511
299 287:512
300 287:514
301 287:515
302 287:516
303 287:517
304 287:518
305 287:520
306 288:444
307 288:445
308 288:446
309 288:447
310 288:448
311 288:449
312 288:450
313 288:451
314 288:452
315 289:454
316 289:456
317 289:457
318 289:458
319 289:459
320 289:460
321 289:461
322 289:468
323 289:469
324 289:470
325 289:471
326 289:472
327 289:474
328 289:475
329 289:476
330 289:477
331 289:478
332 289:480
333 293:524
334 293:525
335 293:526
336 293:527
337 293:528
338 293:529
339 293:530
340 293:532
341 293:533
342 293:534
343 293:535
344 293:537
345 293:539
346 293:540
347 293:541
348 293:542
349 293:544
350 293:545
351 293:546
352 294:548
353 294:549
354 294:550
355 294:551
356 294:552
357 294:553
358 294:554
359 294:555
360 294:556
361 294:557
362 294:727
363 294:728
364 294:729
365 294:730
366 294:731
367 295:560
368 295:561
369 295:562
370 295:563
371 295:564
372 296:565
373 297:566
374 298:567
375 300:570
376 300:572
377 300:573
378 300:574
379 300:575
380 300:576
381 300:577
382 300:584
383 300:585
384 300:586
385 300:587
386 300:588
387 300:590
388 300:591
389 300:592
390 300:593
391 300:594
392 300:596
393 300:597
394 300:598
395 300:599
396 301:602
397 302:604
398 302:605
399 302:606
400 302:639
401 302:640
402 302:641
403 302:642
404 302:644
405 302:645
406 302:646
407 305:607
408 305:609
409 305:611
410 305:612
411 305:613
412 305:614
413 305:621
414 305:622
415 305:623
416 305:624
417 305:625
418 305:627
419 305:628
420 305:629
421 305:633
422 305:634
423 305:635
424 305:636
425 306:630
426 306:631
427 306:632
428 309:648
429 309:650
430 309:651
431 309:652
432 309:653
433 309:654
434 309:655
435 309:662
436 309:663
437 309:664
438 309:665
439 309:666
440 309:668
441 309:669
442 309:670
443 309:671
444 309:672
445 309:674
446 309:675
447 309:676
448 309:677
449 310:681
450 310:682
451 310:683
452 310:684
453 310:685
454 310:689
455 310:690
456 310:691
457 310:692
458 311:686
459 311:687
460 311:688
461 313:696
462 313:698
463 313:699
464 313:700
465 313:701
466 313:702
467 313:703
468 313:710
469 313:711
470 313:712
471 313:713
472 313:714
473 313:716
474 313:717
475 313:718
476 313:719
477 313:720
478 313:722
479 316:734
480 316:735
481 316:736
482 316:737
483 316:738
484 316:739
485 316:740
486 316:741
487 319:749
488 320:750
489 325:1033
490 325:1034
491 325:1035
492 325:1036
493 325:1039
494 325:1040
495 325:1041
496 325:1042
497 325:1043
498 325:1044
499 325:1045
500 325:1076
501 325:1097
502 325:1118
503 325:1141
504 325:1144
505 325:1145
506 325:1146
507 325:1147
508 325:1148
509 325:1149
510 325:1150
511 325:1151
512 325:1152
513 325:1153
514 325:1154
515 325:1155
516 325:1156
517 325:1157
518 326:1048
519 326:1049
520 326:1051
521 326:1052
522 326:1053
523 326:1054
524 326:1061
525 326:1062
526 326:1063
527 326:1064
528 326:1065
529 326:1067
530 326:1068
531 327:1071
532 327:1072
533 327:1073
534 328:1077
535 328:1079
536 328:1080
537 328:1081
538 328:1082
539 328:1085
540 328:1086
541 328:1087
542 328:1090
543 328:1091
544 328:1092
545 328:1093
546 328:1094
547 328:1096
548 329:1098
549 329:1100
550 329:1101
551 329:1102
552 329:1103
553 329:1106
554 329:1107
555 329:1108
556 329:1111
557 329:1112
558 329:1113
559 329:1114
560 329:1115
561 329:1117
562 330:1119
563 330:1121
564 330:1122
565 330:1123
566 330:1124
567 330:1127
568 330:1128
569 330:1129
570 330:1132
571 330:1133
572 330:1134
573 330:1135
574 330:1136
575 330:1139
576 331:1142
577 331:1143
578 336:1211
579 336:1212
580 336:1213
581 336:1214
582 336:1216
583 336:1327
584 336:1328
585 336:1329
586 336:1330
587 336:1331
588 336:1332
589 336:1333
590 336:1334
591 336:1335
592 336:1336
593 336:1337
594 337:1217
595 337:1218
596 337:1219
597 337:1220
598 337:1221
599 337:1222
600 337:1223
601 337:1224
602 337:1225
603 337:1226
604 337:1227
605 337:1228
606 337:1229
607 337:1230
608 337:1231
609 337:1233
610 337:1234
611 337:1235
612 338:1238
613 338:1239
614 338:1240
615 339:1242
616 339:1244
617 339:1245
618 339:1246
619 339:1247
620 339:1248
621 339:1249
622 339:1256
623 339:1257
624 339:1258
625 339:1259
626 339:1260
627 339:1262
628 339:1263
629 339:1264
630 339:1265
631 339:1266
632 339:1268
633 339:1269
634 339:1270
635 339:1271
636 340:1274
637 340:1275
638 340:1276
639 340:1277
640 340:1278
641 340:1287
642 340:1293
643 340:1314
644 340:1317
645 340:1318
646 340:1319
647 340:1320
648 340:1322
649 340:1323
650 341:1279
651 341:1280
652 341:1281
653 341:1282
654 341:1283
655 341:1284
656 341:1285
657 341:1286
658 342:1288
659 342:1289
660 342:1290
661 342:1291
662 342:1292
663 343:1294
664 343:1296
665 343:1297
666 343:1298
667 343:1299
668 343:1306
669 343:1307
670 343:1308
671 343:1309
672 343:1310
673 343:1312
674 343:1313
675 344:1315
676 344:1316
677 346:1324
678 350:967
679 350:968
680 350:969
681 350:970
682 350:973
683 350:974
684 350:975
685 350:976
686 350:977
687 350:978
688 350:979
689 350:1015
690 350:1018
691 350:1019
692 350:1020
693 350:1021
694 350:1022
695 350:1023
696 350:1024
697 350:1025
698 350:1026
699 350:1027
700 350:1028
701 350:1029
702 350:1030
703 350:1031
704 351:982
705 351:983
706 351:985
707 351:986
708 351:987
709 351:988
710 351:995
711 351:996
712 351:997
713 351:998
714 351:999
715 351:1001
716 351:1002
717 352:1005
718 352:1006
719 352:1007
720 353:1010
721 353:1011
722 353:1012
723 354:1016
724 354:1017
725 359:821
726 359:822
727 359:823
728 359:824
729 359:825
730 359:836
731 359:842
732 359:848
733 359:854
734 359:876
735 359:877
736 359:878
737 359:879
738 359:881
739 359:882
740 359:883
741 359:884
742 359:885
743 359:886
744 359:887
745 360:831
746 360:832
747 360:833
748 360:834
749 360:835
750 361:837
751 361:838
752 361:839
753 361:840
754 361:841
755 362:843
756 362:844
757 362:845
758 362:846
759 362:847
760 363:849
761 363:850
762 363:851
763 363:852
764 363:853
765 364:826
766 364:827
767 364:828
768 364:829
769 364:855
770 364:856
771 364:857
772 364:858
773 364:859
774 364:860
775 364:861
776 364:862
777 364:863
778 364:864
779 364:865
780 364:866
781 364:867
782 364:868
783 364:869
784 364:870
785 364:871
786 364:872
787 364:873
788 364:874
789 365:875
790 369:1159
791 369:1160
792 369:1161
793 369:1162
794 369:1164
795 369:1165
796 369:1166
797 369:1167
798 369:1168
799 369:1169
800 369:1170
801 369:1171
802 373:1379
803 373:1380
804 373:1381
805 373:1382
806 373:1384
807 373:1385
808 373:1386
809 373:1387
810 373:1388
811 373:1389
812 373:1392
813 373:1393
814 373:1394
815 373:1395
816 373:1398
817 373:1399
818 373:1400
819 373:1401
820 373:1404
821 373:1405
822 373:1406
823 373:1407
824 373:1408
825 373:1409
826 373:1410
827 373:1411
828 373:1412
829 373:1413
830 373:1414
831 377:1173
832 377:1174
833 377:1175
834 377:1176
835 377:1204
836 377:1205
837 377:1206
838 377:1207
839 377:1208
840 377:1209
841 378:1178
842 378:1179
843 378:1180
844 378:1181
845 378:1182
846 378:1183
847 378:1184
848 378:1185
849 378:1188
850 378:1189
851 378:1190
852 378:1193
853 378:1194
854 378:1195
855 378:1196
856 378:1197
857 378:1198
858 378:1199
859 378:1200
860 378:1201
861 378:1202
862 378:1203
863 382:1339
864 382:1340
865 382:1341
866 382:1342
867 382:1372
868 382:1373
869 382:1374
870 382:1375
871 382:1376
872 382:1377
873 383:1344
874 383:1346
875 383:1347
876 383:1348
877 383:1349
878 383:1350
879 383:1351
880 383:1352
881 383:1355
882 383:1356
883 383:1357
884 383:1360
885 383:1361
886 383:1362
887 383:1363
888 383:1364
889 383:1365
890 383:1366
891 383:1367
892 383:1368
893 383:1369
894 383:1370
895 383:1371
896 387:227
897 387:228
898 387:229
899 387:230
900 387:249
901 387:250
902 387:251
903 387:252
904 387:253
905 387:254
906 388:233
907 388:234
908 388:235
909 388:236
910 388:237
911 388:238
912 388:239
913 388:240
914 388:241
915 388:242
916 388:243
917 388:244
918 388:246
919 388:247
920 388:248
921 392:889
922 392:890
923 392:891
924 392:892
925 392:960
926 392:961
927 392:962
928 392:963
929 392:964
930 392:965
931 393:894
932 396:897
933 397:898
934 397:899
935 397:900
936 397:901
937 397:902
938 397:923
939 397:926
940 397:927
941 397:928
942 397:929
943 397:931
944 397:932
945 398:903
946 398:905
947 398:906
948 398:907
949 398:908
950 398:915
951 398:916
952 398:917
953 398:918
954 398:919
955 398:921
956 398:922
957 399:924
958 399:925
959 401:933
960 401:935
961 401:937
962 401:938
963 401:939
964 401:940
965 401:947
966 401:948
967 401:949
968 401:950
969 401:951
970 401:953
971 401:954
972 401:955
973 401:957
974 406:764
975 406:765
976 406:766
977 406:767
978 406:814
979 406:815
980 406:816
981 406:817
982 406:818
983 406:819
984 407:769
985 407:771
986 407:772
987 407:773
988 407:774
989 407:781
990 407:782
991 407:783
992 407:784
993 407:785
994 407:788
995 407:789
996 407:790
997 407:791
998 407:798
999 407:799
1000 407:800
1001 407:801
1002 407:802
1003 407:804
1004 407:805
1005 407:807
1006 407:808
1007 407:809
1008 407:811
1009 *E
0 // $ANTLR 2.7.7 (20060906): "group.g" -> "GroupLexer.java"$
1
2 /*
3 [The "BSD licence"]
4 Copyright (c) 2003-2004 Terence Parr
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 package org.antlr.stringtemplate.language;
30 import org.antlr.stringtemplate.*;
31 import java.util.*;
32
33 import java.io.InputStream;
34 import antlr.TokenStreamException;
35 import antlr.TokenStreamIOException;
36 import antlr.TokenStreamRecognitionException;
37 import antlr.CharStreamException;
38 import antlr.CharStreamIOException;
39 import antlr.ANTLRException;
40 import java.io.Reader;
41 import java.util.Hashtable;
42 import antlr.CharScanner;
43 import antlr.InputBuffer;
44 import antlr.ByteBuffer;
45 import antlr.CharBuffer;
46 import antlr.Token;
47 import antlr.CommonToken;
48 import antlr.RecognitionException;
49 import antlr.NoViableAltForCharException;
50 import antlr.MismatchedCharException;
51 import antlr.TokenStream;
52 import antlr.ANTLRHashString;
53 import antlr.LexerSharedInputState;
54 import antlr.collections.impl.BitSet;
55 import antlr.SemanticException;
56
57 public class GroupLexer extends antlr.CharScanner implements GroupParserTokenTypes, TokenStream
58 {
59 public GroupLexer(InputStream in) {
60 this(new ByteBuffer(in));
61 }
62 public GroupLexer(Reader in) {
63 this(new CharBuffer(in));
64 }
65 public GroupLexer(InputBuffer ib) {
66 this(new LexerSharedInputState(ib));
67 }
68 public GroupLexer(LexerSharedInputState state) {
69 super(state);
70 caseSensitiveLiterals = true;
71 setCaseSensitive(true);
72 literals = new Hashtable();
73 literals.put(new ANTLRHashString("default", this), new Integer(21));
74 literals.put(new ANTLRHashString("group", this), new Integer(4));
75 literals.put(new ANTLRHashString("implements", this), new Integer(7));
76 }
77
78 public Token nextToken() throws TokenStreamException {
79 Token theRetToken=null;
80 tryAgain:
81 for (;;) {
82 Token _token = null;
83 int _ttype = Token.INVALID_TYPE;
84 resetText();
85 try { // for char stream error handling
86 try { // for lexical error handling
87 switch ( LA(1)) {
88 case 'A': case 'B': case 'C': case 'D':
89 case 'E': case 'F': case 'G': case 'H':
90 case 'I': case 'J': case 'K': case 'L':
91 case 'M': case 'N': case 'O': case 'P':
92 case 'Q': case 'R': case 'S': case 'T':
93 case 'U': case 'V': case 'W': case 'X':
94 case 'Y': case 'Z': case '_': case 'a':
95 case 'b': case 'c': case 'd': case 'e':
96 case 'f': case 'g': case 'h': case 'i':
97 case 'j': case 'k': case 'l': case 'm':
98 case 'n': case 'o': case 'p': case 'q':
99 case 'r': case 's': case 't': case 'u':
100 case 'v': case 'w': case 'x': case 'y':
101 case 'z':
102 {
103 mID(true);
104 theRetToken=_returnToken;
105 break;
106 }
107 case '"':
108 {
109 mSTRING(true);
110 theRetToken=_returnToken;
111 break;
112 }
113 case '<':
114 {
115 mBIGSTRING(true);
116 theRetToken=_returnToken;
117 break;
118 }
119 case '{':
120 {
121 mANONYMOUS_TEMPLATE(true);
122 theRetToken=_returnToken;
123 break;
124 }
125 case '@':
126 {
127 mAT(true);
128 theRetToken=_returnToken;
129 break;
130 }
131 case '(':
132 {
133 mLPAREN(true);
134 theRetToken=_returnToken;
135 break;
136 }
137 case ')':
138 {
139 mRPAREN(true);
140 theRetToken=_returnToken;
141 break;
142 }
143 case '[':
144 {
145 mLBRACK(true);
146 theRetToken=_returnToken;
147 break;
148 }
149 case ']':
150 {
151 mRBRACK(true);
152 theRetToken=_returnToken;
153 break;
154 }
155 case ',':
156 {
157 mCOMMA(true);
158 theRetToken=_returnToken;
159 break;
160 }
161 case '.':
162 {
163 mDOT(true);
164 theRetToken=_returnToken;
165 break;
166 }
167 case ';':
168 {
169 mSEMI(true);
170 theRetToken=_returnToken;
171 break;
172 }
173 case '*':
174 {
175 mSTAR(true);
176 theRetToken=_returnToken;
177 break;
178 }
179 case '+':
180 {
181 mPLUS(true);
182 theRetToken=_returnToken;
183 break;
184 }
185 case '=':
186 {
187 mASSIGN(true);
188 theRetToken=_returnToken;
189 break;
190 }
191 case '?':
192 {
193 mOPTIONAL(true);
194 theRetToken=_returnToken;
195 break;
196 }
197 case '\t': case '\n': case '\u000c': case '\r':
198 case ' ':
199 {
200 mWS(true);
201 theRetToken=_returnToken;
202 break;
203 }
204 default:
205 if ((LA(1)==':') && (LA(2)==':')) {
206 mDEFINED_TO_BE(true);
207 theRetToken=_returnToken;
208 }
209 else if ((LA(1)=='/') && (LA(2)=='/')) {
210 mSL_COMMENT(true);
211 theRetToken=_returnToken;
212 }
213 else if ((LA(1)=='/') && (LA(2)=='*')) {
214 mML_COMMENT(true);
215 theRetToken=_returnToken;
216 }
217 else if ((LA(1)==':') && (true)) {
218 mCOLON(true);
219 theRetToken=_returnToken;
220 }
221 else {
222 if (LA(1)==EOF_CHAR) {uponEOF(); _returnToken = makeToken(Token.EOF_TYPE);}
223 else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
224 }
225 }
226 if ( _returnToken==null ) continue tryAgain; // found SKIP token
227 _ttype = _returnToken.getType();
228 _returnToken.setType(_ttype);
229 return _returnToken;
230 }
231 catch (RecognitionException e) {
232 throw new TokenStreamRecognitionException(e);
233 }
234 }
235 catch (CharStreamException cse) {
236 if ( cse instanceof CharStreamIOException ) {
237 throw new TokenStreamIOException(((CharStreamIOException)cse).io);
238 }
239 else {
240 throw new TokenStreamException(cse.getMessage());
241 }
242 }
243 }
244 }
245
246 public final void mID(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
247 int _ttype; Token _token=null; int _begin=text.length();
248 _ttype = ID;
249 int _saveIndex;
250
251 {
252 switch ( LA(1)) {
253 case 'a': case 'b': case 'c': case 'd':
254 case 'e': case 'f': case 'g': case 'h':
255 case 'i': case 'j': case 'k': case 'l':
256 case 'm': case 'n': case 'o': case 'p':
257 case 'q': case 'r': case 's': case 't':
258 case 'u': case 'v': case 'w': case 'x':
259 case 'y': case 'z':
260 {
261 matchRange('a','z');
262 break;
263 }
264 case 'A': case 'B': case 'C': case 'D':
265 case 'E': case 'F': case 'G': case 'H':
266 case 'I': case 'J': case 'K': case 'L':
267 case 'M': case 'N': case 'O': case 'P':
268 case 'Q': case 'R': case 'S': case 'T':
269 case 'U': case 'V': case 'W': case 'X':
270 case 'Y': case 'Z':
271 {
272 matchRange('A','Z');
273 break;
274 }
275 case '_':
276 {
277 match('_');
278 break;
279 }
280 default:
281 {
282 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
283 }
284 }
285 }
286 {
287 _loop29:
288 do {
289 switch ( LA(1)) {
290 case 'a': case 'b': case 'c': case 'd':
291 case 'e': case 'f': case 'g': case 'h':
292 case 'i': case 'j': case 'k': case 'l':
293 case 'm': case 'n': case 'o': case 'p':
294 case 'q': case 'r': case 's': case 't':
295 case 'u': case 'v': case 'w': case 'x':
296 case 'y': case 'z':
297 {
298 matchRange('a','z');
299 break;
300 }
301 case 'A': case 'B': case 'C': case 'D':
302 case 'E': case 'F': case 'G': case 'H':
303 case 'I': case 'J': case 'K': case 'L':
304 case 'M': case 'N': case 'O': case 'P':
305 case 'Q': case 'R': case 'S': case 'T':
306 case 'U': case 'V': case 'W': case 'X':
307 case 'Y': case 'Z':
308 {
309 matchRange('A','Z');
310 break;
311 }
312 case '0': case '1': case '2': case '3':
313 case '4': case '5': case '6': case '7':
314 case '8': case '9':
315 {
316 matchRange('0','9');
317 break;
318 }
319 case '-':
320 {
321 match('-');
322 break;
323 }
324 case '_':
325 {
326 match('_');
327 break;
328 }
329 default:
330 {
331 break _loop29;
332 }
333 }
334 } while (true);
335 }
336 _ttype = testLiteralsTable(_ttype);
337 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
338 _token = makeToken(_ttype);
339 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
340 }
341 _returnToken = _token;
342 }
343
344 public final void mSTRING(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
345 int _ttype; Token _token=null; int _begin=text.length();
346 _ttype = STRING;
347 int _saveIndex;
348
349 _saveIndex=text.length();
350 match('"');
351 text.setLength(_saveIndex);
352 {
353 _loop32:
354 do {
355 if ((LA(1)=='\\') && (LA(2)=='"')) {
356 _saveIndex=text.length();
357 match('\\');
358 text.setLength(_saveIndex);
359 match('"');
360 }
361 else if ((LA(1)=='\\') && (_tokenSet_0.member(LA(2)))) {
362 match('\\');
363 matchNot('"');
364 }
365 else if ((_tokenSet_1.member(LA(1)))) {
366 matchNot('"');
367 }
368 else {
369 break _loop32;
370 }
371
372 } while (true);
373 }
374 _saveIndex=text.length();
375 match('"');
376 text.setLength(_saveIndex);
377 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
378 _token = makeToken(_ttype);
379 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
380 }
381 _returnToken = _token;
382 }
383
384 public final void mBIGSTRING(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
385 int _ttype; Token _token=null; int _begin=text.length();
386 _ttype = BIGSTRING;
387 int _saveIndex;
388
389 _saveIndex=text.length();
390 match("<<");
391 text.setLength(_saveIndex);
392 {
393 if ((LA(1)=='\n'||LA(1)=='\r') && ((LA(2) >= '\u0000' && LA(2) <= '\ufffe'))) {
394 {
395 switch ( LA(1)) {
396 case '\r':
397 {
398 _saveIndex=text.length();
399 match('\r');
400 text.setLength(_saveIndex);
401 break;
402 }
403 case '\n':
404 {
405 break;
406 }
407 default:
408 {
409 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
410 }
411 }
412 }
413 _saveIndex=text.length();
414 match('\n');
415 text.setLength(_saveIndex);
416 newline();
417 }
418 else if (((LA(1) >= '\u0000' && LA(1) <= '\ufffe')) && ((LA(2) >= '\u0000' && LA(2) <= '\ufffe'))) {
419 }
420 else {
421 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
422 }
423
424 }
425 {
426 _loop38:
427 do {
428 // nongreedy exit test
429 if ((LA(1)=='>') && (LA(2)=='>')) break _loop38;
430 if (((LA(1)=='\r') && (LA(2)=='\n'))&&(LA(3)=='>'&&LA(4)=='>')) {
431 _saveIndex=text.length();
432 match('\r');
433 text.setLength(_saveIndex);
434 _saveIndex=text.length();
435 match('\n');
436 text.setLength(_saveIndex);
437 newline();
438 }
439 else if (((LA(1)=='\n') && ((LA(2) >= '\u0000' && LA(2) <= '\ufffe')))&&(LA(2)=='>'&&LA(3)=='>')) {
440 _saveIndex=text.length();
441 match('\n');
442 text.setLength(_saveIndex);
443 newline();
444 }
445 else if ((LA(1)=='\n'||LA(1)=='\r') && ((LA(2) >= '\u0000' && LA(2) <= '\ufffe'))) {
446 {
447 switch ( LA(1)) {
448 case '\r':
449 {
450 match('\r');
451 break;
452 }
453 case '\n':
454 {
455 break;
456 }
457 default:
458 {
459 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
460 }
461 }
462 }
463 match('\n');
464 newline();
465 }
466 else if ((LA(1)=='\\') && (LA(2)=='>')) {
467 _saveIndex=text.length();
468 match('\\');
469 text.setLength(_saveIndex);
470 match('>');
471 }
472 else if (((LA(1) >= '\u0000' && LA(1) <= '\ufffe')) && ((LA(2) >= '\u0000' && LA(2) <= '\ufffe'))) {
473 matchNot(EOF_CHAR);
474 }
475 else {
476 break _loop38;
477 }
478
479 } while (true);
480 }
481 _saveIndex=text.length();
482 match(">>");
483 text.setLength(_saveIndex);
484 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
485 _token = makeToken(_ttype);
486 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
487 }
488 _returnToken = _token;
489 }
490
491 public final void mANONYMOUS_TEMPLATE(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
492 int _ttype; Token _token=null; int _begin=text.length();
493 _ttype = ANONYMOUS_TEMPLATE;
494 int _saveIndex;
495
496 List args=null;
497 StringTemplateToken t = null;
498
499
500 _saveIndex=text.length();
501 match('{');
502 text.setLength(_saveIndex);
503 {
504 _loop42:
505 do {
506 // nongreedy exit test
507 if ((LA(1)=='}') && (true)) break _loop42;
508 if ((LA(1)=='\n'||LA(1)=='\r') && ((LA(2) >= '\u0000' && LA(2) <= '\ufffe'))) {
509 {
510 switch ( LA(1)) {
511 case '\r':
512 {
513 match('\r');
514 break;
515 }
516 case '\n':
517 {
518 break;
519 }
520 default:
521 {
522 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
523 }
524 }
525 }
526 match('\n');
527 newline();
528 }
529 else if ((LA(1)=='\\') && (LA(2)=='}')) {
530 _saveIndex=text.length();
531 match('\\');
532 text.setLength(_saveIndex);
533 match('}');
534 }
535 else if (((LA(1) >= '\u0000' && LA(1) <= '\ufffe')) && ((LA(2) >= '\u0000' && LA(2) <= '\ufffe'))) {
536 matchNot(EOF_CHAR);
537 }
538 else {
539 break _loop42;
540 }
541
542 } while (true);
543 }
544 _saveIndex=text.length();
545 match('}');
546 text.setLength(_saveIndex);
547 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
548 _token = makeToken(_ttype);
549 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
550 }
551 _returnToken = _token;
552 }
553
554 public final void mAT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
555 int _ttype; Token _token=null; int _begin=text.length();
556 _ttype = AT;
557 int _saveIndex;
558
559 match('@');
560 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
561 _token = makeToken(_ttype);
562 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
563 }
564 _returnToken = _token;
565 }
566
567 public final void mLPAREN(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
568 int _ttype; Token _token=null; int _begin=text.length();
569 _ttype = LPAREN;
570 int _saveIndex;
571
572 match('(');
573 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
574 _token = makeToken(_ttype);
575 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
576 }
577 _returnToken = _token;
578 }
579
580 public final void mRPAREN(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
581 int _ttype; Token _token=null; int _begin=text.length();
582 _ttype = RPAREN;
583 int _saveIndex;
584
585 match(')');
586 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
587 _token = makeToken(_ttype);
588 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
589 }
590 _returnToken = _token;
591 }
592
593 public final void mLBRACK(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
594 int _ttype; Token _token=null; int _begin=text.length();
595 _ttype = LBRACK;
596 int _saveIndex;
597
598 match('[');
599 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
600 _token = makeToken(_ttype);
601 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
602 }
603 _returnToken = _token;
604 }
605
606 public final void mRBRACK(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
607 int _ttype; Token _token=null; int _begin=text.length();
608 _ttype = RBRACK;
609 int _saveIndex;
610
611 match(']');
612 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
613 _token = makeToken(_ttype);
614 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
615 }
616 _returnToken = _token;
617 }
618
619 public final void mCOMMA(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
620 int _ttype; Token _token=null; int _begin=text.length();
621 _ttype = COMMA;
622 int _saveIndex;
623
624 match(',');
625 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
626 _token = makeToken(_ttype);
627 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
628 }
629 _returnToken = _token;
630 }
631
632 public final void mDOT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
633 int _ttype; Token _token=null; int _begin=text.length();
634 _ttype = DOT;
635 int _saveIndex;
636
637 match('.');
638 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
639 _token = makeToken(_ttype);
640 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
641 }
642 _returnToken = _token;
643 }
644
645 public final void mDEFINED_TO_BE(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
646 int _ttype; Token _token=null; int _begin=text.length();
647 _ttype = DEFINED_TO_BE;
648 int _saveIndex;
649
650 match("::=");
651 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
652 _token = makeToken(_ttype);
653 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
654 }
655 _returnToken = _token;
656 }
657
658 public final void mSEMI(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
659 int _ttype; Token _token=null; int _begin=text.length();
660 _ttype = SEMI;
661 int _saveIndex;
662
663 match(';');
664 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
665 _token = makeToken(_ttype);
666 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
667 }
668 _returnToken = _token;
669 }
670
671 public final void mCOLON(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
672 int _ttype; Token _token=null; int _begin=text.length();
673 _ttype = COLON;
674 int _saveIndex;
675
676 match(':');
677 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
678 _token = makeToken(_ttype);
679 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
680 }
681 _returnToken = _token;
682 }
683
684 public final void mSTAR(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
685 int _ttype; Token _token=null; int _begin=text.length();
686 _ttype = STAR;
687 int _saveIndex;
688
689 match('*');
690 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
691 _token = makeToken(_ttype);
692 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
693 }
694 _returnToken = _token;
695 }
696
697 public final void mPLUS(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
698 int _ttype; Token _token=null; int _begin=text.length();
699 _ttype = PLUS;
700 int _saveIndex;
701
702 match('+');
703 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
704 _token = makeToken(_ttype);
705 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
706 }
707 _returnToken = _token;
708 }
709
710 public final void mASSIGN(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
711 int _ttype; Token _token=null; int _begin=text.length();
712 _ttype = ASSIGN;
713 int _saveIndex;
714
715 match('=');
716 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
717 _token = makeToken(_ttype);
718 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
719 }
720 _returnToken = _token;
721 }
722
723 public final void mOPTIONAL(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
724 int _ttype; Token _token=null; int _begin=text.length();
725 _ttype = OPTIONAL;
726 int _saveIndex;
727
728 match('?');
729 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
730 _token = makeToken(_ttype);
731 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
732 }
733 _returnToken = _token;
734 }
735
736 public final void mSL_COMMENT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
737 int _ttype; Token _token=null; int _begin=text.length();
738 _ttype = SL_COMMENT;
739 int _saveIndex;
740
741 match("//");
742 {
743 _loop60:
744 do {
745 if ((_tokenSet_2.member(LA(1)))) {
746 {
747 match(_tokenSet_2);
748 }
749 }
750 else {
751 break _loop60;
752 }
753
754 } while (true);
755 }
756 {
757 if ((LA(1)=='\n'||LA(1)=='\r')) {
758 {
759 switch ( LA(1)) {
760 case '\r':
761 {
762 match('\r');
763 break;
764 }
765 case '\n':
766 {
767 break;
768 }
769 default:
770 {
771 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
772 }
773 }
774 }
775 match('\n');
776 }
777 else {
778 }
779
780 }
781 _ttype = Token.SKIP; newline();
782 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
783 _token = makeToken(_ttype);
784 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
785 }
786 _returnToken = _token;
787 }
788
789 public final void mML_COMMENT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
790 int _ttype; Token _token=null; int _begin=text.length();
791 _ttype = ML_COMMENT;
792 int _saveIndex;
793
794 match("/*");
795 {
796 _loop66:
797 do {
798 // nongreedy exit test
799 if ((LA(1)=='*') && (LA(2)=='/')) break _loop66;
800 if ((LA(1)=='\n'||LA(1)=='\r') && ((LA(2) >= '\u0000' && LA(2) <= '\ufffe'))) {
801 {
802 switch ( LA(1)) {
803 case '\r':
804 {
805 match('\r');
806 break;
807 }
808 case '\n':
809 {
810 break;
811 }
812 default:
813 {
814 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
815 }
816 }
817 }
818 match('\n');
819 newline();
820 }
821 else if (((LA(1) >= '\u0000' && LA(1) <= '\ufffe')) && ((LA(2) >= '\u0000' && LA(2) <= '\ufffe'))) {
822 matchNot(EOF_CHAR);
823 }
824 else {
825 break _loop66;
826 }
827
828 } while (true);
829 }
830 match("*/");
831 _ttype = Token.SKIP;
832 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
833 _token = makeToken(_ttype);
834 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
835 }
836 _returnToken = _token;
837 }
838
839 public final void mWS(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
840 int _ttype; Token _token=null; int _begin=text.length();
841 _ttype = WS;
842 int _saveIndex;
843
844 {
845 int _cnt70=0;
846 _loop70:
847 do {
848 switch ( LA(1)) {
849 case ' ':
850 {
851 match(' ');
852 break;
853 }
854 case '\t':
855 {
856 match('\t');
857 break;
858 }
859 case '\u000c':
860 {
861 match('\f');
862 break;
863 }
864 case '\n': case '\r':
865 {
866 {
867 switch ( LA(1)) {
868 case '\r':
869 {
870 match('\r');
871 break;
872 }
873 case '\n':
874 {
875 break;
876 }
877 default:
878 {
879 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
880 }
881 }
882 }
883 match('\n');
884 newline();
885 break;
886 }
887 default:
888 {
889 if ( _cnt70>=1 ) { break _loop70; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
890 }
891 }
892 _cnt70++;
893 } while (true);
894 }
895 _ttype = Token.SKIP;
896 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
897 _token = makeToken(_ttype);
898 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
899 }
900 _returnToken = _token;
901 }
902
903
904 private static final long[] mk_tokenSet_0() {
905 long[] data = new long[2048];
906 data[0]=-17179869185L;
907 for (int i = 1; i<=1022; i++) { data[i]=-1L; }
908 data[1023]=9223372036854775807L;
909 return data;
910 }
911 public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0());
912 private static final long[] mk_tokenSet_1() {
913 long[] data = new long[2048];
914 data[0]=-17179869185L;
915 data[1]=-268435457L;
916 for (int i = 2; i<=1022; i++) { data[i]=-1L; }
917 data[1023]=9223372036854775807L;
918 return data;
919 }
920 public static final BitSet _tokenSet_1 = new BitSet(mk_tokenSet_1());
921 private static final long[] mk_tokenSet_2() {
922 long[] data = new long[2048];
923 data[0]=-9217L;
924 for (int i = 1; i<=1022; i++) { data[i]=-1L; }
925 data[1023]=9223372036854775807L;
926 return data;
927 }
928 public static final BitSet _tokenSet_2 = new BitSet(mk_tokenSet_2());
929
930 }
0 SMAP
1 GroupLexer.java
2 G
3 *S G
4 *F
5 + 0 group.g
6 group.g
7 *L
8 0:104
9 0:110
10 0:116
11 0:122
12 0:128
13 0:134
14 0:140
15 0:146
16 0:152
17 0:158
18 0:164
19 0:170
20 0:176
21 0:182
22 0:188
23 0:194
24 0:201
25 0:207
26 0:211
27 0:215
28 0:219
29 1:3
30 1:4
31 1:5
32 1:6
33 1:8
34 1:9
35 1:10
36 1:11
37 1:12
38 1:13
39 1:14
40 1:15
41 1:16
42 1:17
43 1:19
44 1:20
45 1:21
46 1:22
47 1:23
48 1:24
49 1:25
50 1:26
51 1:27
52 1:28
53 1:29
54 1:30
55 1:31
56 1:32
57 247:247
58 247:248
59 247:249
60 247:250
61 247:337
62 247:338
63 247:339
64 247:340
65 247:341
66 247:342
67 247:343
68 251:253
69 251:254
70 251:255
71 251:256
72 251:257
73 251:258
74 251:259
75 251:260
76 251:261
77 251:262
78 251:265
79 251:266
80 251:267
81 251:268
82 251:269
83 251:270
84 251:271
85 251:272
86 251:273
87 251:276
88 251:277
89 251:278
90 251:281
91 251:282
92 251:283
93 251:284
94 251:285
95 251:287
96 251:288
97 251:289
98 251:290
99 251:291
100 251:292
101 251:293
102 251:294
103 251:295
104 251:296
105 251:297
106 251:298
107 251:299
108 251:302
109 251:303
110 251:304
111 251:305
112 251:306
113 251:307
114 251:308
115 251:309
116 251:310
117 251:313
118 251:314
119 251:315
120 251:316
121 251:317
122 251:320
123 251:321
124 251:322
125 251:325
126 251:326
127 251:327
128 251:330
129 251:331
130 251:332
131 251:333
132 251:334
133 251:335
134 251:336
135 254:345
136 254:346
137 254:347
138 254:348
139 254:378
140 254:379
141 254:380
142 254:381
143 254:382
144 254:383
145 255:350
146 255:351
147 255:352
148 255:353
149 255:354
150 255:355
151 255:356
152 255:357
153 255:358
154 255:359
155 255:360
156 255:361
157 255:362
158 255:363
159 255:364
160 255:365
161 255:366
162 255:367
163 255:368
164 255:369
165 255:370
166 255:371
167 255:373
168 255:374
169 255:375
170 255:376
171 255:377
172 258:385
173 258:386
174 258:387
175 258:388
176 258:485
177 258:486
178 258:487
179 258:488
180 258:489
181 258:490
182 259:390
183 259:391
184 259:392
185 260:394
186 260:396
187 260:397
188 260:398
189 260:399
190 260:400
191 260:401
192 260:408
193 260:409
194 260:410
195 260:411
196 260:412
197 260:414
198 260:415
199 260:416
200 260:417
201 260:418
202 260:420
203 260:421
204 260:422
205 260:423
206 261:426
207 261:427
208 261:428
209 261:429
210 261:430
211 261:439
212 261:445
213 261:466
214 261:472
215 261:475
216 261:476
217 261:477
218 261:478
219 261:480
220 261:481
221 262:431
222 262:432
223 262:433
224 262:434
225 262:435
226 262:436
227 262:437
228 262:438
229 263:440
230 263:441
231 263:442
232 263:443
233 263:444
234 264:446
235 264:448
236 264:449
237 264:450
238 264:451
239 264:458
240 264:459
241 264:460
242 264:461
243 264:462
244 264:464
245 264:465
246 265:467
247 265:468
248 265:469
249 265:470
250 265:471
251 266:473
252 266:474
253 268:482
254 268:483
255 268:484
256 271:492
257 271:493
258 271:494
259 271:495
260 271:548
261 271:549
262 271:550
263 271:551
264 271:552
265 271:553
266 272:497
267 273:498
268 276:501
269 276:502
270 276:503
271 277:504
272 277:505
273 277:506
274 277:507
275 277:508
276 277:529
277 277:535
278 277:538
279 277:539
280 277:540
281 277:541
282 277:543
283 277:544
284 278:509
285 278:511
286 278:512
287 278:513
288 278:514
289 278:521
290 278:522
291 278:523
292 278:524
293 278:525
294 278:527
295 278:528
296 279:530
297 279:531
298 279:532
299 279:533
300 279:534
301 280:536
302 280:537
303 282:545
304 282:546
305 282:547
306 286:555
307 286:556
308 286:557
309 286:558
310 286:560
311 286:561
312 286:562
313 286:563
314 286:564
315 286:565
316 286:566
317 287:568
318 287:569
319 287:570
320 287:571
321 287:573
322 287:574
323 287:575
324 287:576
325 287:577
326 287:578
327 287:579
328 288:581
329 288:582
330 288:583
331 288:584
332 288:586
333 288:587
334 288:588
335 288:589
336 288:590
337 288:591
338 288:592
339 289:594
340 289:595
341 289:596
342 289:597
343 289:599
344 289:600
345 289:601
346 289:602
347 289:603
348 289:604
349 289:605
350 290:607
351 290:608
352 290:609
353 290:610
354 290:612
355 290:613
356 290:614
357 290:615
358 290:616
359 290:617
360 290:618
361 291:620
362 291:621
363 291:622
364 291:623
365 291:625
366 291:626
367 291:627
368 291:628
369 291:629
370 291:630
371 291:631
372 292:633
373 292:634
374 292:635
375 292:636
376 292:638
377 292:639
378 292:640
379 292:641
380 292:642
381 292:643
382 292:644
383 293:646
384 293:647
385 293:648
386 293:649
387 293:651
388 293:652
389 293:653
390 293:654
391 293:655
392 293:656
393 293:657
394 294:659
395 294:660
396 294:661
397 294:662
398 294:664
399 294:665
400 294:666
401 294:667
402 294:668
403 294:669
404 294:670
405 295:672
406 295:673
407 295:674
408 295:675
409 295:677
410 295:678
411 295:679
412 295:680
413 295:681
414 295:682
415 295:683
416 296:685
417 296:686
418 296:687
419 296:688
420 296:690
421 296:691
422 296:692
423 296:693
424 296:694
425 296:695
426 296:696
427 297:698
428 297:699
429 297:700
430 297:701
431 297:703
432 297:704
433 297:705
434 297:706
435 297:707
436 297:708
437 297:709
438 298:711
439 298:712
440 298:713
441 298:714
442 298:716
443 298:717
444 298:718
445 298:719
446 298:720
447 298:721
448 298:722
449 299:724
450 299:725
451 299:726
452 299:727
453 299:729
454 299:730
455 299:731
456 299:732
457 299:733
458 299:734
459 299:735
460 302:737
461 302:738
462 302:739
463 302:740
464 302:783
465 302:784
466 302:785
467 302:786
468 302:787
469 302:788
470 303:742
471 304:743
472 304:744
473 304:745
474 304:746
475 304:748
476 304:750
477 304:751
478 304:752
479 304:753
480 304:755
481 304:756
482 304:758
483 304:760
484 304:761
485 304:762
486 304:763
487 304:770
488 304:771
489 304:772
490 304:773
491 304:774
492 304:776
493 304:777
494 304:779
495 305:782
496 309:790
497 309:791
498 309:792
499 309:793
500 309:833
501 309:834
502 309:835
503 309:836
504 309:837
505 309:838
506 310:795
507 311:796
508 311:797
509 311:798
510 311:799
511 311:800
512 311:821
513 311:824
514 311:825
515 311:826
516 311:827
517 311:829
518 311:830
519 315:801
520 315:803
521 315:804
522 315:805
523 315:806
524 315:813
525 315:814
526 315:815
527 315:816
528 315:817
529 315:819
530 315:820
531 316:822
532 316:823
533 318:831
534 319:832
535 323:840
536 323:841
537 323:842
538 323:843
539 323:846
540 323:847
541 323:848
542 323:849
543 323:850
544 323:851
545 323:852
546 323:888
547 323:889
548 323:890
549 323:891
550 323:892
551 323:893
552 323:894
553 323:895
554 323:897
555 323:898
556 323:899
557 323:900
558 323:901
559 323:902
560 324:855
561 324:856
562 324:857
563 325:860
564 325:861
565 325:862
566 326:865
567 326:866
568 326:868
569 326:869
570 326:870
571 326:871
572 326:878
573 326:879
574 326:880
575 326:881
576 326:882
577 326:884
578 326:885
579 328:896
580 *E
0 // $ANTLR 2.7.7 (20060906): "group.g" -> "GroupParser.java"$
1
2 /*
3 [The "BSD licence"]
4 Copyright (c) 2003-2004 Terence Parr
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 package org.antlr.stringtemplate.language;
30 import org.antlr.stringtemplate.*;
31 import java.util.*;
32
33 import antlr.TokenBuffer;
34 import antlr.TokenStreamException;
35 import antlr.TokenStreamIOException;
36 import antlr.ANTLRException;
37 import antlr.LLkParser;
38 import antlr.Token;
39 import antlr.TokenStream;
40 import antlr.RecognitionException;
41 import antlr.NoViableAltException;
42 import antlr.MismatchedTokenException;
43 import antlr.SemanticException;
44 import antlr.ParserSharedInputState;
45 import antlr.collections.impl.BitSet;
46
47 /** Match a group of template definitions beginning
48 * with a group name declaration. Templates are enclosed
49 * in double-quotes or <<...>> quotes for multi-line templates.
50 * Template names have arg lists that indicate the cardinality
51 * of the attribute: present, optional, zero-or-more, one-or-more.
52 * Here is a sample group file:
53
54 group nfa;
55
56 // an NFA has edges and states
57 nfa(states,edges) ::= <<
58 digraph NFA {
59 rankdir=LR;
60 <states; separator="\\n">
61 <edges; separator="\\n">
62 }
63 >>
64
65 state(name) ::= "node [shape = circle]; <name>;"
66
67 */
68 public class GroupParser extends antlr.LLkParser implements GroupParserTokenTypes
69 {
70
71 protected StringTemplateGroup group;
72
73 public void reportError(RecognitionException e) {
74 if ( group!=null ) {
75 group.error("template group parse error", e);
76 }
77 else {
78 System.err.println("template group parse error: "+e);
79 e.printStackTrace(System.err);
80 }
81 }
82
83 protected GroupParser(TokenBuffer tokenBuf, int k) {
84 super(tokenBuf,k);
85 tokenNames = _tokenNames;
86 }
87
88 public GroupParser(TokenBuffer tokenBuf) {
89 this(tokenBuf,3);
90 }
91
92 protected GroupParser(TokenStream lexer, int k) {
93 super(lexer,k);
94 tokenNames = _tokenNames;
95 }
96
97 public GroupParser(TokenStream lexer) {
98 this(lexer,3);
99 }
100
101 public GroupParser(ParserSharedInputState state) {
102 super(state,3);
103 tokenNames = _tokenNames;
104 }
105
106 public final void group(
107 StringTemplateGroup g
108 ) throws RecognitionException, TokenStreamException {
109
110 Token name = null;
111 Token s = null;
112 Token i = null;
113 Token i2 = null;
114
115 this.group = g;
116
117
118 try { // for error handling
119 match(LITERAL_group);
120 name = LT(1);
121 match(ID);
122 g.setName(name.getText());
123 {
124 switch ( LA(1)) {
125 case COLON:
126 {
127 match(COLON);
128 s = LT(1);
129 match(ID);
130 g.setSuperGroup(s.getText());
131 break;
132 }
133 case LITERAL_implements:
134 case SEMI:
135 {
136 break;
137 }
138 default:
139 {
140 throw new NoViableAltException(LT(1), getFilename());
141 }
142 }
143 }
144 {
145 switch ( LA(1)) {
146 case LITERAL_implements:
147 {
148 match(LITERAL_implements);
149 i = LT(1);
150 match(ID);
151 g.implementInterface(i.getText());
152 {
153 _loop5:
154 do {
155 if ((LA(1)==COMMA)) {
156 match(COMMA);
157 i2 = LT(1);
158 match(ID);
159 g.implementInterface(i2.getText());
160 }
161 else {
162 break _loop5;
163 }
164
165 } while (true);
166 }
167 break;
168 }
169 case SEMI:
170 {
171 break;
172 }
173 default:
174 {
175 throw new NoViableAltException(LT(1), getFilename());
176 }
177 }
178 }
179 match(SEMI);
180 {
181 int _cnt7=0;
182 _loop7:
183 do {
184 if ((LA(1)==ID||LA(1)==AT) && (LA(2)==ID||LA(2)==LPAREN||LA(2)==DEFINED_TO_BE) && (LA(3)==ID||LA(3)==DOT||LA(3)==RPAREN)) {
185 template(g);
186 }
187 else if ((LA(1)==ID) && (LA(2)==DEFINED_TO_BE) && (LA(3)==LBRACK)) {
188 mapdef(g);
189 }
190 else {
191 if ( _cnt7>=1 ) { break _loop7; } else {throw new NoViableAltException(LT(1), getFilename());}
192 }
193
194 _cnt7++;
195 } while (true);
196 }
197 }
198 catch (RecognitionException ex) {
199 reportError(ex);
200 recover(ex,_tokenSet_0);
201 }
202 }
203
204 public final void template(
205 StringTemplateGroup g
206 ) throws RecognitionException, TokenStreamException {
207
208 Token scope = null;
209 Token region = null;
210 Token name = null;
211 Token t = null;
212 Token bt = null;
213 Token alias = null;
214 Token target = null;
215
216 Map formalArgs = null;
217 StringTemplate st = null;
218 boolean ignore = false;
219 String templateName=null;
220 int line = LT(1).getLine();
221
222
223 try { // for error handling
224 if ((LA(1)==ID||LA(1)==AT) && (LA(2)==ID||LA(2)==LPAREN)) {
225 {
226 switch ( LA(1)) {
227 case AT:
228 {
229 match(AT);
230 scope = LT(1);
231 match(ID);
232 match(DOT);
233 region = LT(1);
234 match(ID);
235
236 templateName=g.getMangledRegionName(scope.getText(),region.getText());
237 if ( g.isDefinedInThisGroup(templateName) ) {
238 g.error("group "+g.getName()+" line "+line+": redefinition of template region: @"+
239 scope.getText()+"."+region.getText());
240 st = new StringTemplate(); // create bogus template to fill in
241 }
242 else {
243 boolean err = false;
244 // @template.region() ::= "..."
245 StringTemplate scopeST = g.lookupTemplate(scope.getText());
246 if ( scopeST==null ) {
247 g.error("group "+g.getName()+" line "+line+": reference to region within undefined template: "+
248 scope.getText());
249 err=true;
250 }
251 if ( !scopeST.containsRegionName(region.getText()) ) {
252 g.error("group "+g.getName()+" line "+line+": template "+scope.getText()+" has no region called "+
253 region.getText());
254 err=true;
255 }
256 if ( err ) {
257 st = new StringTemplate();
258 }
259 else {
260 st = g.defineRegionTemplate(scope.getText(),
261 region.getText(),
262 null,
263 StringTemplate.REGION_EXPLICIT);
264 }
265 }
266
267 break;
268 }
269 case ID:
270 {
271 name = LT(1);
272 match(ID);
273 templateName = name.getText();
274
275 if ( g.isDefinedInThisGroup(templateName) ) {
276 g.error("redefinition of template: "+templateName);
277 st = new StringTemplate(); // create bogus template to fill in
278 }
279 else {
280 st = g.defineTemplate(templateName, null);
281 }
282
283 break;
284 }
285 default:
286 {
287 throw new NoViableAltException(LT(1), getFilename());
288 }
289 }
290 }
291 if ( st!=null ) {st.setGroupFileLine(line);}
292 match(LPAREN);
293 {
294 switch ( LA(1)) {
295 case ID:
296 {
297 args(st);
298 break;
299 }
300 case RPAREN:
301 {
302 st.defineEmptyFormalArgumentList();
303 break;
304 }
305 default:
306 {
307 throw new NoViableAltException(LT(1), getFilename());
308 }
309 }
310 }
311 match(RPAREN);
312 match(DEFINED_TO_BE);
313 {
314 switch ( LA(1)) {
315 case STRING:
316 {
317 t = LT(1);
318 match(STRING);
319 st.setTemplate(t.getText());
320 break;
321 }
322 case BIGSTRING:
323 {
324 bt = LT(1);
325 match(BIGSTRING);
326 st.setTemplate(bt.getText());
327 break;
328 }
329 default:
330 {
331 throw new NoViableAltException(LT(1), getFilename());
332 }
333 }
334 }
335 }
336 else if ((LA(1)==ID) && (LA(2)==DEFINED_TO_BE)) {
337 alias = LT(1);
338 match(ID);
339 match(DEFINED_TO_BE);
340 target = LT(1);
341 match(ID);
342 g.defineTemplateAlias(alias.getText(), target.getText());
343 }
344 else {
345 throw new NoViableAltException(LT(1), getFilename());
346 }
347
348 }
349 catch (RecognitionException ex) {
350 reportError(ex);
351 recover(ex,_tokenSet_1);
352 }
353 }
354
355 public final void mapdef(
356 StringTemplateGroup g
357 ) throws RecognitionException, TokenStreamException {
358
359 Token name = null;
360
361 Map m=null;
362
363
364 try { // for error handling
365 name = LT(1);
366 match(ID);
367 match(DEFINED_TO_BE);
368 m=map();
369
370 if ( g.getMap(name.getText())!=null ) {
371 g.error("redefinition of map: "+name.getText());
372 }
373 else if ( g.isDefinedInThisGroup(name.getText()) ) {
374 g.error("redefinition of template as map: "+name.getText());
375 }
376 else {
377 g.defineMap(name.getText(), m);
378 }
379
380 }
381 catch (RecognitionException ex) {
382 reportError(ex);
383 recover(ex,_tokenSet_1);
384 }
385 }
386
387 public final void args(
388 StringTemplate st
389 ) throws RecognitionException, TokenStreamException {
390
391
392 try { // for error handling
393 arg(st);
394 {
395 _loop14:
396 do {
397 if ((LA(1)==COMMA)) {
398 match(COMMA);
399 arg(st);
400 }
401 else {
402 break _loop14;
403 }
404
405 } while (true);
406 }
407 }
408 catch (RecognitionException ex) {
409 reportError(ex);
410 recover(ex,_tokenSet_2);
411 }
412 }
413
414 public final void arg(
415 StringTemplate st
416 ) throws RecognitionException, TokenStreamException {
417
418 Token name = null;
419 Token s = null;
420 Token bs = null;
421
422 StringTemplate defaultValue = null;
423
424
425 try { // for error handling
426 name = LT(1);
427 match(ID);
428 {
429 if ((LA(1)==ASSIGN) && (LA(2)==STRING)) {
430 match(ASSIGN);
431 s = LT(1);
432 match(STRING);
433
434 defaultValue=new StringTemplate("$_val_$");
435 defaultValue.setAttribute("_val_", s.getText());
436 defaultValue.defineFormalArgument("_val_");
437 defaultValue.setName("<"+st.getName()+"'s arg "+name.getText()+" default value subtemplate>");
438
439 }
440 else if ((LA(1)==ASSIGN) && (LA(2)==ANONYMOUS_TEMPLATE)) {
441 match(ASSIGN);
442 bs = LT(1);
443 match(ANONYMOUS_TEMPLATE);
444
445 defaultValue=new StringTemplate(st.getGroup(), bs.getText());
446 defaultValue.setName("<"+st.getName()+"'s arg "+name.getText()+" default value subtemplate>");
447
448 }
449 else if ((LA(1)==COMMA||LA(1)==RPAREN)) {
450 }
451 else {
452 throw new NoViableAltException(LT(1), getFilename());
453 }
454
455 }
456 st.defineFormalArgument(name.getText(), defaultValue);
457 }
458 catch (RecognitionException ex) {
459 reportError(ex);
460 recover(ex,_tokenSet_3);
461 }
462 }
463
464 public final Map map() throws RecognitionException, TokenStreamException {
465 Map mapping=new HashMap();
466
467
468 try { // for error handling
469 match(LBRACK);
470 mapPairs(mapping);
471 match(RBRACK);
472 }
473 catch (RecognitionException ex) {
474 reportError(ex);
475 recover(ex,_tokenSet_1);
476 }
477 return mapping;
478 }
479
480 public final void mapPairs(
481 Map mapping
482 ) throws RecognitionException, TokenStreamException {
483
484
485 try { // for error handling
486 switch ( LA(1)) {
487 case STRING:
488 {
489 keyValuePair(mapping);
490 {
491 _loop21:
492 do {
493 if ((LA(1)==COMMA) && (LA(2)==STRING)) {
494 match(COMMA);
495 keyValuePair(mapping);
496 }
497 else {
498 break _loop21;
499 }
500
501 } while (true);
502 }
503 {
504 switch ( LA(1)) {
505 case COMMA:
506 {
507 match(COMMA);
508 defaultValuePair(mapping);
509 break;
510 }
511 case RBRACK:
512 {
513 break;
514 }
515 default:
516 {
517 throw new NoViableAltException(LT(1), getFilename());
518 }
519 }
520 }
521 break;
522 }
523 case LITERAL_default:
524 {
525 defaultValuePair(mapping);
526 break;
527 }
528 default:
529 {
530 throw new NoViableAltException(LT(1), getFilename());
531 }
532 }
533 }
534 catch (RecognitionException ex) {
535 reportError(ex);
536 recover(ex,_tokenSet_4);
537 }
538 }
539
540 public final void keyValuePair(
541 Map mapping
542 ) throws RecognitionException, TokenStreamException {
543
544 Token key = null;
545
546 StringTemplate v = null;
547
548
549 try { // for error handling
550 key = LT(1);
551 match(STRING);
552 match(COLON);
553 v=keyValue();
554 mapping.put(key.getText(), v);
555 }
556 catch (RecognitionException ex) {
557 reportError(ex);
558 recover(ex,_tokenSet_5);
559 }
560 }
561
562 public final void defaultValuePair(
563 Map mapping
564 ) throws RecognitionException, TokenStreamException {
565
566
567 StringTemplate v = null;
568
569
570 try { // for error handling
571 match(LITERAL_default);
572 match(COLON);
573 v=keyValue();
574 mapping.put(ASTExpr.DEFAULT_MAP_VALUE_NAME, v);
575 }
576 catch (RecognitionException ex) {
577 reportError(ex);
578 recover(ex,_tokenSet_4);
579 }
580 }
581
582 public final StringTemplate keyValue() throws RecognitionException, TokenStreamException {
583 StringTemplate value=null;
584
585 Token s1 = null;
586 Token s2 = null;
587 Token k = null;
588
589 try { // for error handling
590 switch ( LA(1)) {
591 case BIGSTRING:
592 {
593 s1 = LT(1);
594 match(BIGSTRING);
595 value = new StringTemplate(group,s1.getText());
596 break;
597 }
598 case STRING:
599 {
600 s2 = LT(1);
601 match(STRING);
602 value = new StringTemplate(group,s2.getText());
603 break;
604 }
605 case ID:
606 {
607 k = LT(1);
608 match(ID);
609 if (!(k.getText().equals("key")))
610 throw new SemanticException("k.getText().equals(\"key\")");
611 value = ASTExpr.MAP_KEY_VALUE;
612 break;
613 }
614 case COMMA:
615 case RBRACK:
616 {
617 value = null;
618 break;
619 }
620 default:
621 {
622 throw new NoViableAltException(LT(1), getFilename());
623 }
624 }
625 }
626 catch (RecognitionException ex) {
627 reportError(ex);
628 recover(ex,_tokenSet_5);
629 }
630 return value;
631 }
632
633
634 public static final String[] _tokenNames = {
635 "<0>",
636 "EOF",
637 "<2>",
638 "NULL_TREE_LOOKAHEAD",
639 "\"group\"",
640 "ID",
641 "COLON",
642 "\"implements\"",
643 "COMMA",
644 "SEMI",
645 "AT",
646 "DOT",
647 "LPAREN",
648 "RPAREN",
649 "DEFINED_TO_BE",
650 "STRING",
651 "BIGSTRING",
652 "ASSIGN",
653 "ANONYMOUS_TEMPLATE",
654 "LBRACK",
655 "RBRACK",
656 "\"default\"",
657 "STAR",
658 "PLUS",
659 "OPTIONAL",
660 "SL_COMMENT",
661 "ML_COMMENT",
662 "WS"
663 };
664
665 private static final long[] mk_tokenSet_0() {
666 long[] data = { 2L, 0L};
667 return data;
668 }
669 public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0());
670 private static final long[] mk_tokenSet_1() {
671 long[] data = { 1058L, 0L};
672 return data;
673 }
674 public static final BitSet _tokenSet_1 = new BitSet(mk_tokenSet_1());
675 private static final long[] mk_tokenSet_2() {
676 long[] data = { 8192L, 0L};
677 return data;
678 }
679 public static final BitSet _tokenSet_2 = new BitSet(mk_tokenSet_2());
680 private static final long[] mk_tokenSet_3() {
681 long[] data = { 8448L, 0L};
682 return data;
683 }
684 public static final BitSet _tokenSet_3 = new BitSet(mk_tokenSet_3());
685 private static final long[] mk_tokenSet_4() {
686 long[] data = { 1048576L, 0L};
687 return data;
688 }
689 public static final BitSet _tokenSet_4 = new BitSet(mk_tokenSet_4());
690 private static final long[] mk_tokenSet_5() {
691 long[] data = { 1048832L, 0L};
692 return data;
693 }
694 public static final BitSet _tokenSet_5 = new BitSet(mk_tokenSet_5());
695
696 }
0 SMAP
1 GroupParser.java
2 G
3 *S G
4 *F
5 + 0 group.g
6 group.g
7 *L
8 1:3
9 1:4
10 1:5
11 1:6
12 1:8
13 1:9
14 1:10
15 1:11
16 1:12
17 1:13
18 1:14
19 1:15
20 1:16
21 1:17
22 1:19
23 1:20
24 1:21
25 1:22
26 1:23
27 1:24
28 1:25
29 1:26
30 1:27
31 1:28
32 1:29
33 1:30
34 1:31
35 1:32
36 62:72
37 64:74
38 65:75
39 66:76
40 67:77
41 68:78
42 69:79
43 70:80
44 71:81
45 72:82
46 75:107
47 75:108
48 75:109
49 75:119
50 75:198
51 75:199
52 75:200
53 75:201
54 75:202
55 75:203
56 76:116
57 79:111
58 79:120
59 79:121
60 79:122
61 79:123
62 80:112
63 80:125
64 80:126
65 80:127
66 80:128
67 80:129
68 80:130
69 80:131
70 80:139
71 80:140
72 80:141
73 80:142
74 80:143
75 81:113
76 81:146
77 81:147
78 81:148
79 81:149
80 81:150
81 81:151
82 81:152
83 81:174
84 81:175
85 81:176
86 81:177
87 81:178
88 82:114
89 82:153
90 82:154
91 82:155
92 82:156
93 82:157
94 82:158
95 82:159
96 82:160
97 82:161
98 82:162
99 82:163
100 82:164
101 82:166
102 82:167
103 84:180
104 85:182
105 85:183
106 85:184
107 85:185
108 85:186
109 85:187
110 85:188
111 85:189
112 85:190
113 85:191
114 85:192
115 85:193
116 85:195
117 85:196
118 85:197
119 88:205
120 88:206
121 88:207
122 88:224
123 88:336
124 88:344
125 88:345
126 88:346
127 88:347
128 88:349
129 88:350
130 88:351
131 88:352
132 88:353
133 88:354
134 89:217
135 90:218
136 91:219
137 92:220
138 93:221
139 96:209
140 96:210
141 96:225
142 96:227
143 96:228
144 96:229
145 96:230
146 96:231
147 96:232
148 96:233
149 96:234
150 96:235
151 96:286
152 96:287
153 96:288
154 96:289
155 96:290
156 98:237
157 99:238
158 100:239
159 101:240
160 102:241
161 103:242
162 104:243
163 105:244
164 106:245
165 107:246
166 108:247
167 109:248
168 110:249
169 111:250
170 112:251
171 113:252
172 114:253
173 115:254
174 116:255
175 117:256
176 118:257
177 119:258
178 120:259
179 121:260
180 122:261
181 123:262
182 124:263
183 125:264
184 126:265
185 127:266
186 129:211
187 129:270
188 129:271
189 129:272
190 129:273
191 129:274
192 131:276
193 132:277
194 133:278
195 134:279
196 135:280
197 136:281
198 137:282
199 140:292
200 141:293
201 142:295
202 142:296
203 142:297
204 142:298
205 142:301
206 142:302
207 142:303
208 142:306
209 142:307
210 142:308
211 142:309
212 142:310
213 143:312
214 144:313
215 145:212
216 145:315
217 145:316
218 145:317
219 145:318
220 145:319
221 145:320
222 145:330
223 145:331
224 145:332
225 145:333
226 145:334
227 146:213
228 146:323
229 146:324
230 146:325
231 146:326
232 146:327
233 149:214
234 149:215
235 149:337
236 149:338
237 149:339
238 149:340
239 149:341
240 149:342
241 150:343
242 153:388
243 153:389
244 153:390
245 153:393
246 153:408
247 153:409
248 153:410
249 153:411
250 153:412
251 153:413
252 154:394
253 154:395
254 154:396
255 154:397
256 154:398
257 154:399
258 154:400
259 154:401
260 154:402
261 154:403
262 154:404
263 154:406
264 154:407
265 157:415
266 157:416
267 157:417
268 157:426
269 157:458
270 157:459
271 157:460
272 157:461
273 157:462
274 157:463
275 158:423
276 161:419
277 161:427
278 161:428
279 162:420
280 162:430
281 162:431
282 162:432
283 162:433
284 162:440
285 162:449
286 162:451
287 162:452
288 162:453
289 162:454
290 164:435
291 165:436
292 166:437
293 167:438
294 169:421
295 169:441
296 169:442
297 169:443
298 169:444
299 171:446
300 172:447
301 175:457
302 187:356
303 187:357
304 187:358
305 187:365
306 187:381
307 187:382
308 187:383
309 187:384
310 187:385
311 187:386
312 188:362
313 191:360
314 191:366
315 191:367
316 192:368
317 192:369
318 194:371
319 195:372
320 196:373
321 197:374
322 198:375
323 199:376
324 200:377
325 201:378
326 202:379
327 206:465
328 206:466
329 206:469
330 206:473
331 206:474
332 206:475
333 206:476
334 206:477
335 206:478
336 206:479
337 207:470
338 207:471
339 207:472
340 210:481
341 210:482
342 210:483
343 210:486
344 210:487
345 210:529
346 210:530
347 210:531
348 210:532
349 210:533
350 210:534
351 210:535
352 210:536
353 210:537
354 210:538
355 210:539
356 211:488
357 211:489
358 211:490
359 211:491
360 211:492
361 211:493
362 211:494
363 211:495
364 211:496
365 211:497
366 211:498
367 211:499
368 211:500
369 211:502
370 211:503
371 212:505
372 212:506
373 212:507
374 212:508
375 212:509
376 212:516
377 212:517
378 212:518
379 212:519
380 212:520
381 213:524
382 213:525
383 213:526
384 216:563
385 216:564
386 216:565
387 216:571
388 216:576
389 216:577
390 216:578
391 216:579
392 216:580
393 216:581
394 217:568
395 220:572
396 220:573
397 220:574
398 221:575
399 224:541
400 224:542
401 224:543
402 224:550
403 224:556
404 224:557
405 224:558
406 224:559
407 224:560
408 224:561
409 225:547
410 228:545
411 228:551
412 228:552
413 228:553
414 228:554
415 228:555
416 231:583
417 231:584
418 231:590
419 231:591
420 231:621
421 231:622
422 231:623
423 231:624
424 231:625
425 231:626
426 231:627
427 231:628
428 231:629
429 231:630
430 231:631
431 231:632
432 232:586
433 232:592
434 232:593
435 232:594
436 232:595
437 232:596
438 233:587
439 233:599
440 233:600
441 233:601
442 233:602
443 233:603
444 234:588
445 234:606
446 234:607
447 234:608
448 234:609
449 234:610
450 234:611
451 235:612
452 236:615
453 236:616
454 236:617
455 236:618
456 *E
0 // $ANTLR 2.7.7 (20060906): "group.g" -> "GroupParser.java"$
1
2 /*
3 [The "BSD licence"]
4 Copyright (c) 2003-2004 Terence Parr
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 package org.antlr.stringtemplate.language;
30 import org.antlr.stringtemplate.*;
31 import java.util.*;
32
33 public interface GroupParserTokenTypes {
34 int EOF = 1;
35 int NULL_TREE_LOOKAHEAD = 3;
36 int LITERAL_group = 4;
37 int ID = 5;
38 int COLON = 6;
39 int LITERAL_implements = 7;
40 int COMMA = 8;
41 int SEMI = 9;
42 int AT = 10;
43 int DOT = 11;
44 int LPAREN = 12;
45 int RPAREN = 13;
46 int DEFINED_TO_BE = 14;
47 int STRING = 15;
48 int BIGSTRING = 16;
49 int ASSIGN = 17;
50 int ANONYMOUS_TEMPLATE = 18;
51 int LBRACK = 19;
52 int RBRACK = 20;
53 int LITERAL_default = 21;
54 int STAR = 22;
55 int PLUS = 23;
56 int OPTIONAL = 24;
57 int SL_COMMENT = 25;
58 int ML_COMMENT = 26;
59 int WS = 27;
60 }
0 // $ANTLR 2.7.7 (20060906): group.g -> GroupParserTokenTypes.txt$
1 GroupParser // output token vocab name
2 LITERAL_group="group"=4
3 ID=5
4 COLON=6
5 LITERAL_implements="implements"=7
6 COMMA=8
7 SEMI=9
8 AT=10
9 DOT=11
10 LPAREN=12
11 RPAREN=13
12 DEFINED_TO_BE=14
13 STRING=15
14 BIGSTRING=16
15 ASSIGN=17
16 ANONYMOUS_TEMPLATE=18
17 LBRACK=19
18 RBRACK=20
19 LITERAL_default="default"=21
20 STAR=22
21 PLUS=23
22 OPTIONAL=24
23 SL_COMMENT=25
24 ML_COMMENT=26
25 WS=27
0 // $ANTLR 2.7.7 (20060906): "interface.g" -> "InterfaceLexer.java"$
1
2 /*
3 [The "BSD licence"]
4 Copyright (c) 2003-2004 Terence Parr
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 package org.antlr.stringtemplate.language;
30 import org.antlr.stringtemplate.*;
31 import java.util.*;
32
33 import java.io.InputStream;
34 import antlr.TokenStreamException;
35 import antlr.TokenStreamIOException;
36 import antlr.TokenStreamRecognitionException;
37 import antlr.CharStreamException;
38 import antlr.CharStreamIOException;
39 import antlr.ANTLRException;
40 import java.io.Reader;
41 import java.util.Hashtable;
42 import antlr.CharScanner;
43 import antlr.InputBuffer;
44 import antlr.ByteBuffer;
45 import antlr.CharBuffer;
46 import antlr.Token;
47 import antlr.CommonToken;
48 import antlr.RecognitionException;
49 import antlr.NoViableAltForCharException;
50 import antlr.MismatchedCharException;
51 import antlr.TokenStream;
52 import antlr.ANTLRHashString;
53 import antlr.LexerSharedInputState;
54 import antlr.collections.impl.BitSet;
55 import antlr.SemanticException;
56
57 public class InterfaceLexer extends antlr.CharScanner implements InterfaceParserTokenTypes, TokenStream
58 {
59 public InterfaceLexer(InputStream in) {
60 this(new ByteBuffer(in));
61 }
62 public InterfaceLexer(Reader in) {
63 this(new CharBuffer(in));
64 }
65 public InterfaceLexer(InputBuffer ib) {
66 this(new LexerSharedInputState(ib));
67 }
68 public InterfaceLexer(LexerSharedInputState state) {
69 super(state);
70 caseSensitiveLiterals = true;
71 setCaseSensitive(true);
72 literals = new Hashtable();
73 literals.put(new ANTLRHashString("interface", this), new Integer(4));
74 literals.put(new ANTLRHashString("optional", this), new Integer(7));
75 }
76
77 public Token nextToken() throws TokenStreamException {
78 Token theRetToken=null;
79 tryAgain:
80 for (;;) {
81 Token _token = null;
82 int _ttype = Token.INVALID_TYPE;
83 resetText();
84 try { // for char stream error handling
85 try { // for lexical error handling
86 switch ( LA(1)) {
87 case 'A': case 'B': case 'C': case 'D':
88 case 'E': case 'F': case 'G': case 'H':
89 case 'I': case 'J': case 'K': case 'L':
90 case 'M': case 'N': case 'O': case 'P':
91 case 'Q': case 'R': case 'S': case 'T':
92 case 'U': case 'V': case 'W': case 'X':
93 case 'Y': case 'Z': case '_': case 'a':
94 case 'b': case 'c': case 'd': case 'e':
95 case 'f': case 'g': case 'h': case 'i':
96 case 'j': case 'k': case 'l': case 'm':
97 case 'n': case 'o': case 'p': case 'q':
98 case 'r': case 's': case 't': case 'u':
99 case 'v': case 'w': case 'x': case 'y':
100 case 'z':
101 {
102 mID(true);
103 theRetToken=_returnToken;
104 break;
105 }
106 case '(':
107 {
108 mLPAREN(true);
109 theRetToken=_returnToken;
110 break;
111 }
112 case ')':
113 {
114 mRPAREN(true);
115 theRetToken=_returnToken;
116 break;
117 }
118 case ',':
119 {
120 mCOMMA(true);
121 theRetToken=_returnToken;
122 break;
123 }
124 case ';':
125 {
126 mSEMI(true);
127 theRetToken=_returnToken;
128 break;
129 }
130 case ':':
131 {
132 mCOLON(true);
133 theRetToken=_returnToken;
134 break;
135 }
136 case '\t': case '\n': case '\u000c': case '\r':
137 case ' ':
138 {
139 mWS(true);
140 theRetToken=_returnToken;
141 break;
142 }
143 default:
144 if ((LA(1)=='/') && (LA(2)=='/')) {
145 mSL_COMMENT(true);
146 theRetToken=_returnToken;
147 }
148 else if ((LA(1)=='/') && (LA(2)=='*')) {
149 mML_COMMENT(true);
150 theRetToken=_returnToken;
151 }
152 else {
153 if (LA(1)==EOF_CHAR) {uponEOF(); _returnToken = makeToken(Token.EOF_TYPE);}
154 else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
155 }
156 }
157 if ( _returnToken==null ) continue tryAgain; // found SKIP token
158 _ttype = _returnToken.getType();
159 _ttype = testLiteralsTable(_ttype);
160 _returnToken.setType(_ttype);
161 return _returnToken;
162 }
163 catch (RecognitionException e) {
164 throw new TokenStreamRecognitionException(e);
165 }
166 }
167 catch (CharStreamException cse) {
168 if ( cse instanceof CharStreamIOException ) {
169 throw new TokenStreamIOException(((CharStreamIOException)cse).io);
170 }
171 else {
172 throw new TokenStreamException(cse.getMessage());
173 }
174 }
175 }
176 }
177
178 public final void mID(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
179 int _ttype; Token _token=null; int _begin=text.length();
180 _ttype = ID;
181 int _saveIndex;
182
183 {
184 switch ( LA(1)) {
185 case 'a': case 'b': case 'c': case 'd':
186 case 'e': case 'f': case 'g': case 'h':
187 case 'i': case 'j': case 'k': case 'l':
188 case 'm': case 'n': case 'o': case 'p':
189 case 'q': case 'r': case 's': case 't':
190 case 'u': case 'v': case 'w': case 'x':
191 case 'y': case 'z':
192 {
193 matchRange('a','z');
194 break;
195 }
196 case 'A': case 'B': case 'C': case 'D':
197 case 'E': case 'F': case 'G': case 'H':
198 case 'I': case 'J': case 'K': case 'L':
199 case 'M': case 'N': case 'O': case 'P':
200 case 'Q': case 'R': case 'S': case 'T':
201 case 'U': case 'V': case 'W': case 'X':
202 case 'Y': case 'Z':
203 {
204 matchRange('A','Z');
205 break;
206 }
207 case '_':
208 {
209 match('_');
210 break;
211 }
212 default:
213 {
214 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
215 }
216 }
217 }
218 {
219 _loop13:
220 do {
221 switch ( LA(1)) {
222 case 'a': case 'b': case 'c': case 'd':
223 case 'e': case 'f': case 'g': case 'h':
224 case 'i': case 'j': case 'k': case 'l':
225 case 'm': case 'n': case 'o': case 'p':
226 case 'q': case 'r': case 's': case 't':
227 case 'u': case 'v': case 'w': case 'x':
228 case 'y': case 'z':
229 {
230 matchRange('a','z');
231 break;
232 }
233 case 'A': case 'B': case 'C': case 'D':
234 case 'E': case 'F': case 'G': case 'H':
235 case 'I': case 'J': case 'K': case 'L':
236 case 'M': case 'N': case 'O': case 'P':
237 case 'Q': case 'R': case 'S': case 'T':
238 case 'U': case 'V': case 'W': case 'X':
239 case 'Y': case 'Z':
240 {
241 matchRange('A','Z');
242 break;
243 }
244 case '0': case '1': case '2': case '3':
245 case '4': case '5': case '6': case '7':
246 case '8': case '9':
247 {
248 matchRange('0','9');
249 break;
250 }
251 case '-':
252 {
253 match('-');
254 break;
255 }
256 case '_':
257 {
258 match('_');
259 break;
260 }
261 default:
262 {
263 break _loop13;
264 }
265 }
266 } while (true);
267 }
268 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
269 _token = makeToken(_ttype);
270 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
271 }
272 _returnToken = _token;
273 }
274
275 public final void mLPAREN(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
276 int _ttype; Token _token=null; int _begin=text.length();
277 _ttype = LPAREN;
278 int _saveIndex;
279
280 match('(');
281 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
282 _token = makeToken(_ttype);
283 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
284 }
285 _returnToken = _token;
286 }
287
288 public final void mRPAREN(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
289 int _ttype; Token _token=null; int _begin=text.length();
290 _ttype = RPAREN;
291 int _saveIndex;
292
293 match(')');
294 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
295 _token = makeToken(_ttype);
296 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
297 }
298 _returnToken = _token;
299 }
300
301 public final void mCOMMA(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
302 int _ttype; Token _token=null; int _begin=text.length();
303 _ttype = COMMA;
304 int _saveIndex;
305
306 match(',');
307 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
308 _token = makeToken(_ttype);
309 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
310 }
311 _returnToken = _token;
312 }
313
314 public final void mSEMI(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
315 int _ttype; Token _token=null; int _begin=text.length();
316 _ttype = SEMI;
317 int _saveIndex;
318
319 match(';');
320 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
321 _token = makeToken(_ttype);
322 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
323 }
324 _returnToken = _token;
325 }
326
327 public final void mCOLON(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
328 int _ttype; Token _token=null; int _begin=text.length();
329 _ttype = COLON;
330 int _saveIndex;
331
332 match(':');
333 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
334 _token = makeToken(_ttype);
335 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
336 }
337 _returnToken = _token;
338 }
339
340 public final void mSL_COMMENT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
341 int _ttype; Token _token=null; int _begin=text.length();
342 _ttype = SL_COMMENT;
343 int _saveIndex;
344
345 match("//");
346 {
347 _loop22:
348 do {
349 if ((_tokenSet_0.member(LA(1)))) {
350 {
351 match(_tokenSet_0);
352 }
353 }
354 else {
355 break _loop22;
356 }
357
358 } while (true);
359 }
360 {
361 if ((LA(1)=='\n'||LA(1)=='\r')) {
362 {
363 switch ( LA(1)) {
364 case '\r':
365 {
366 match('\r');
367 break;
368 }
369 case '\n':
370 {
371 break;
372 }
373 default:
374 {
375 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
376 }
377 }
378 }
379 match('\n');
380 }
381 else {
382 }
383
384 }
385 _ttype = Token.SKIP; newline();
386 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
387 _token = makeToken(_ttype);
388 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
389 }
390 _returnToken = _token;
391 }
392
393 public final void mML_COMMENT(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
394 int _ttype; Token _token=null; int _begin=text.length();
395 _ttype = ML_COMMENT;
396 int _saveIndex;
397
398 match("/*");
399 {
400 _loop28:
401 do {
402 // nongreedy exit test
403 if ((LA(1)=='*') && (LA(2)=='/')) break _loop28;
404 if ((LA(1)=='\n'||LA(1)=='\r') && ((LA(2) >= '\u0000' && LA(2) <= '\ufffe'))) {
405 {
406 switch ( LA(1)) {
407 case '\r':
408 {
409 match('\r');
410 break;
411 }
412 case '\n':
413 {
414 break;
415 }
416 default:
417 {
418 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
419 }
420 }
421 }
422 match('\n');
423 newline();
424 }
425 else if (((LA(1) >= '\u0000' && LA(1) <= '\ufffe')) && ((LA(2) >= '\u0000' && LA(2) <= '\ufffe'))) {
426 matchNot(EOF_CHAR);
427 }
428 else {
429 break _loop28;
430 }
431
432 } while (true);
433 }
434 match("*/");
435 _ttype = Token.SKIP;
436 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
437 _token = makeToken(_ttype);
438 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
439 }
440 _returnToken = _token;
441 }
442
443 public final void mWS(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
444 int _ttype; Token _token=null; int _begin=text.length();
445 _ttype = WS;
446 int _saveIndex;
447
448 {
449 int _cnt32=0;
450 _loop32:
451 do {
452 switch ( LA(1)) {
453 case ' ':
454 {
455 match(' ');
456 break;
457 }
458 case '\t':
459 {
460 match('\t');
461 break;
462 }
463 case '\u000c':
464 {
465 match('\f');
466 break;
467 }
468 case '\n': case '\r':
469 {
470 {
471 switch ( LA(1)) {
472 case '\r':
473 {
474 match('\r');
475 break;
476 }
477 case '\n':
478 {
479 break;
480 }
481 default:
482 {
483 throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
484 }
485 }
486 }
487 match('\n');
488 newline();
489 break;
490 }
491 default:
492 {
493 if ( _cnt32>=1 ) { break _loop32; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
494 }
495 }
496 _cnt32++;
497 } while (true);
498 }
499 _ttype = Token.SKIP;
500 if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
501 _token = makeToken(_ttype);
502 _token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
503 }
504 _returnToken = _token;
505 }
506
507
508 private static final long[] mk_tokenSet_0() {
509 long[] data = new long[2048];
510 data[0]=-9217L;
511 for (int i = 1; i<=1022; i++) { data[i]=-1L; }
512 data[1023]=9223372036854775807L;
513 return data;
514 }
515 public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0());
516
517 }
0 SMAP
1 InterfaceLexer.java
2 G
3 *S G
4 *F
5 + 0 interface.g
6 interface.g
7 *L
8 0:103
9 0:109
10 0:115
11 0:121
12 0:127
13 0:133
14 0:140
15 0:146
16 0:150
17 1:3
18 1:4
19 1:5
20 1:6
21 1:8
22 1:9
23 1:10
24 1:11
25 1:12
26 1:13
27 1:14
28 1:15
29 1:16
30 1:17
31 1:19
32 1:20
33 1:21
34 1:22
35 1:23
36 1:24
37 1:25
38 1:26
39 1:27
40 1:28
41 1:29
42 1:30
43 1:31
44 1:32
45 92:179
46 92:180
47 92:181
48 92:182
49 92:185
50 92:186
51 92:187
52 92:188
53 92:189
54 92:190
55 92:191
56 92:192
57 92:193
58 92:194
59 92:197
60 92:198
61 92:199
62 92:200
63 92:201
64 92:202
65 92:203
66 92:204
67 92:205
68 92:208
69 92:209
70 92:210
71 92:213
72 92:214
73 92:215
74 92:216
75 92:217
76 92:219
77 92:220
78 92:221
79 92:222
80 92:223
81 92:224
82 92:225
83 92:226
84 92:227
85 92:228
86 92:229
87 92:230
88 92:231
89 92:234
90 92:235
91 92:236
92 92:237
93 92:238
94 92:239
95 92:240
96 92:241
97 92:242
98 92:245
99 92:246
100 92:247
101 92:248
102 92:249
103 92:252
104 92:253
105 92:254
106 92:257
107 92:258
108 92:259
109 92:262
110 92:263
111 92:264
112 92:265
113 92:266
114 92:267
115 92:268
116 92:269
117 92:270
118 92:271
119 92:272
120 92:273
121 92:274
122 95:276
123 95:277
124 95:278
125 95:279
126 95:281
127 95:282
128 95:283
129 95:284
130 95:285
131 95:286
132 95:287
133 96:289
134 96:290
135 96:291
136 96:292
137 96:294
138 96:295
139 96:296
140 96:297
141 96:298
142 96:299
143 96:300
144 97:302
145 97:303
146 97:304
147 97:305
148 97:307
149 97:308
150 97:309
151 97:310
152 97:311
153 97:312
154 97:313
155 98:315
156 98:316
157 98:317
158 98:318
159 98:320
160 98:321
161 98:322
162 98:323
163 98:324
164 98:325
165 98:326
166 99:328
167 99:329
168 99:330
169 99:331
170 99:333
171 99:334
172 99:335
173 99:336
174 99:337
175 99:338
176 99:339
177 102:341
178 102:342
179 102:343
180 102:344
181 102:387
182 102:388
183 102:389
184 102:390
185 102:391
186 102:392
187 103:346
188 104:347
189 104:348
190 104:349
191 104:350
192 104:352
193 104:354
194 104:355
195 104:356
196 104:357
197 104:359
198 104:360
199 104:362
200 104:364
201 104:365
202 104:366
203 104:367
204 104:374
205 104:375
206 104:376
207 104:377
208 104:378
209 104:380
210 104:381
211 104:383
212 105:386
213 109:394
214 109:395
215 109:396
216 109:397
217 109:437
218 109:438
219 109:439
220 109:440
221 109:441
222 109:442
223 110:399
224 111:400
225 111:401
226 111:402
227 111:403
228 111:404
229 111:425
230 111:428
231 111:429
232 111:430
233 111:431
234 111:433
235 111:434
236 115:405
237 115:407
238 115:408
239 115:409
240 115:410
241 115:417
242 115:418
243 115:419
244 115:420
245 115:421
246 115:423
247 115:424
248 116:426
249 116:427
250 118:435
251 119:436
252 123:444
253 123:445
254 123:446
255 123:447
256 123:450
257 123:451
258 123:452
259 123:453
260 123:454
261 123:455
262 123:456
263 123:492
264 123:493
265 123:494
266 123:495
267 123:496
268 123:497
269 123:498
270 123:499
271 123:501
272 123:502
273 123:503
274 123:504
275 123:505
276 123:506
277 124:459
278 124:460
279 124:461
280 125:464
281 125:465
282 125:466
283 126:469
284 126:470
285 126:472
286 126:473
287 126:474
288 126:475
289 126:482
290 126:483
291 126:484
292 126:485
293 126:486
294 126:488
295 126:489
296 128:500
297 *E
0 // $ANTLR 2.7.7 (20060906): "interface.g" -> "InterfaceParser.java"$
1
2 /*
3 [The "BSD licence"]
4 Copyright (c) 2003-2004 Terence Parr
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 package org.antlr.stringtemplate.language;
30 import org.antlr.stringtemplate.*;
31 import java.util.*;
32
33 import antlr.TokenBuffer;
34 import antlr.TokenStreamException;
35 import antlr.TokenStreamIOException;
36 import antlr.ANTLRException;
37 import antlr.LLkParser;
38 import antlr.Token;
39 import antlr.TokenStream;
40 import antlr.RecognitionException;
41 import antlr.NoViableAltException;
42 import antlr.MismatchedTokenException;
43 import antlr.SemanticException;
44 import antlr.ParserSharedInputState;
45 import antlr.collections.impl.BitSet;
46
47 /** Match an ST group interface. Just a list of template names with args.
48 * Here is a sample interface file:
49 *
50 * interface nfa;
51 * nfa(states,edges);
52 * optional state(name);
53 */
54 public class InterfaceParser extends antlr.LLkParser implements InterfaceParserTokenTypes
55 {
56
57 protected StringTemplateGroupInterface groupI;
58
59 public void reportError(RecognitionException e) {
60 if ( groupI!=null ) {
61 groupI.error("template group interface parse error", e);
62 }
63 else {
64 System.err.println("template group interface parse error: "+e);
65 e.printStackTrace(System.err);
66 }
67 }
68
69 protected InterfaceParser(TokenBuffer tokenBuf, int k) {
70 super(tokenBuf,k);
71 tokenNames = _tokenNames;
72 }
73
74 public InterfaceParser(TokenBuffer tokenBuf) {
75 this(tokenBuf,3);
76 }
77
78 protected InterfaceParser(TokenStream lexer, int k) {
79 super(lexer,k);
80 tokenNames = _tokenNames;
81 }
82
83 public InterfaceParser(TokenStream lexer) {
84 this(lexer,3);
85 }
86
87 public InterfaceParser(ParserSharedInputState state) {
88 super(state,3);
89 tokenNames = _tokenNames;
90 }
91
92 public final void groupInterface(
93 StringTemplateGroupInterface groupI
94 ) throws RecognitionException, TokenStreamException {
95
96 Token name = null;
97 this.groupI = groupI;
98
99 try { // for error handling
100 match(LITERAL_interface);
101 name = LT(1);
102 match(ID);
103 groupI.setName(name.getText());
104 match(SEMI);
105 {
106 int _cnt3=0;
107 _loop3:
108 do {
109 if ((LA(1)==ID||LA(1)==LITERAL_optional)) {
110 template(groupI);
111 }
112 else {
113 if ( _cnt3>=1 ) { break _loop3; } else {throw new NoViableAltException(LT(1), getFilename());}
114 }
115
116 _cnt3++;
117 } while (true);
118 }
119 }
120 catch (RecognitionException ex) {
121 reportError(ex);
122 recover(ex,_tokenSet_0);
123 }
124 }
125
126 public final void template(
127 StringTemplateGroupInterface groupI
128 ) throws RecognitionException, TokenStreamException {
129
130 Token opt = null;
131 Token name = null;
132
133 LinkedHashMap formalArgs = new LinkedHashMap(); // leave blank if no args
134 String templateName=null;
135
136
137 try { // for error handling
138 {
139 switch ( LA(1)) {
140 case LITERAL_optional:
141 {
142 opt = LT(1);
143 match(LITERAL_optional);
144 break;
145 }
146 case ID:
147 {
148 break;
149 }
150 default:
151 {
152 throw new NoViableAltException(LT(1), getFilename());
153 }
154 }
155 }
156 name = LT(1);
157 match(ID);
158 match(LPAREN);
159 {
160 switch ( LA(1)) {
161 case ID:
162 {
163 formalArgs=args();
164 break;
165 }
166 case RPAREN:
167 {
168 break;
169 }
170 default:
171 {
172 throw new NoViableAltException(LT(1), getFilename());
173 }
174 }
175 }
176 match(RPAREN);
177 match(SEMI);
178
179 templateName = name.getText();
180 groupI.defineTemplate(templateName, formalArgs, opt!=null);
181
182 }
183 catch (RecognitionException ex) {
184 reportError(ex);
185 recover(ex,_tokenSet_1);
186 }
187 }
188
189 public final LinkedHashMap args() throws RecognitionException, TokenStreamException {
190 LinkedHashMap args=new LinkedHashMap();
191
192 Token a = null;
193 Token b = null;
194
195 try { // for error handling
196 a = LT(1);
197 match(ID);
198 args.put(a.getText(), new FormalArgument(a.getText()));
199 {
200 _loop9:
201 do {
202 if ((LA(1)==COMMA)) {
203 match(COMMA);
204 b = LT(1);
205 match(ID);
206 args.put(b.getText(), new FormalArgument(b.getText()));
207 }
208 else {
209 break _loop9;
210 }
211
212 } while (true);
213 }
214 }
215 catch (RecognitionException ex) {
216 reportError(ex);
217 recover(ex,_tokenSet_2);
218 }
219 return args;
220 }
221
222
223 public static final String[] _tokenNames = {
224 "<0>",
225 "EOF",
226 "<2>",
227 "NULL_TREE_LOOKAHEAD",
228 "\"interface\"",
229 "ID",
230 "SEMI",
231 "\"optional\"",
232 "LPAREN",
233 "RPAREN",
234 "COMMA",
235 "COLON",
236 "SL_COMMENT",
237 "ML_COMMENT",
238 "WS"
239 };
240
241 private static final long[] mk_tokenSet_0() {
242 long[] data = { 2L, 0L};
243 return data;
244 }
245 public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0());
246 private static final long[] mk_tokenSet_1() {
247 long[] data = { 162L, 0L};
248 return data;
249 }
250 public static final BitSet _tokenSet_1 = new BitSet(mk_tokenSet_1());
251 private static final long[] mk_tokenSet_2() {
252 long[] data = { 512L, 0L};
253 return data;
254 }
255 public static final BitSet _tokenSet_2 = new BitSet(mk_tokenSet_2());
256
257 }
0 SMAP
1 InterfaceParser.java
2 G
3 *S G
4 *F
5 + 0 interface.g
6 interface.g
7 *L
8 1:3
9 1:4
10 1:5
11 1:6
12 1:8
13 1:9
14 1:10
15 1:11
16 1:12
17 1:13
18 1:14
19 1:15
20 1:16
21 1:17
22 1:19
23 1:20
24 1:21
25 1:22
26 1:23
27 1:24
28 1:25
29 1:26
30 1:27
31 1:28
32 1:29
33 1:30
34 1:31
35 1:32
36 48:58
37 50:60
38 51:61
39 52:62
40 53:63
41 54:64
42 55:65
43 56:66
44 57:67
45 58:68
46 61:93
47 61:94
48 61:95
49 61:98
50 61:100
51 61:120
52 61:121
53 61:122
54 61:123
55 61:124
56 61:125
57 63:97
58 63:101
59 63:102
60 63:103
61 63:104
62 63:105
63 64:107
64 64:108
65 64:109
66 64:110
67 64:111
68 64:112
69 64:113
70 64:114
71 64:115
72 64:117
73 64:118
74 64:119
75 67:127
76 67:128
77 67:129
78 67:138
79 67:183
80 67:184
81 67:185
82 67:186
83 67:187
84 67:188
85 68:134
86 69:135
87 72:131
88 72:132
89 72:140
90 72:141
91 72:142
92 72:143
93 72:144
94 72:151
95 72:152
96 72:153
97 72:154
98 72:155
99 72:157
100 72:158
101 72:159
102 72:161
103 72:162
104 72:163
105 72:164
106 72:171
107 72:172
108 72:173
109 72:174
110 72:175
111 72:177
112 72:178
113 74:180
114 75:181
115 79:190
116 79:191
117 79:196
118 79:215
119 79:216
120 79:217
121 79:218
122 79:219
123 79:220
124 79:221
125 80:193
126 80:197
127 80:198
128 80:199
129 81:194
130 81:200
131 81:201
132 81:202
133 81:203
134 81:204
135 81:205
136 81:206
137 81:207
138 81:208
139 81:209
140 81:210
141 81:211
142 81:213
143 81:214
144 *E
0 // $ANTLR 2.7.7 (20060906): "interface.g" -> "InterfaceParser.java"$
1
2 /*
3 [The "BSD licence"]
4 Copyright (c) 2003-2004 Terence Parr
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 package org.antlr.stringtemplate.language;
30 import org.antlr.stringtemplate.*;
31 import java.util.*;
32
33 public interface InterfaceParserTokenTypes {
34 int EOF = 1;
35 int NULL_TREE_LOOKAHEAD = 3;
36 int LITERAL_interface = 4;
37 int ID = 5;
38 int SEMI = 6;
39 int LITERAL_optional = 7;
40 int LPAREN = 8;
41 int RPAREN = 9;
42 int COMMA = 10;
43 int COLON = 11;
44 int SL_COMMENT = 12;
45 int ML_COMMENT = 13;
46 int WS = 14;
47 }
0 // $ANTLR 2.7.7 (20060906): interface.g -> InterfaceParserTokenTypes.txt$
1 InterfaceParser // output token vocab name
2 LITERAL_interface="interface"=4
3 ID=5
4 SEMI=6
5 LITERAL_optional="optional"=7
6 LPAREN=8
7 RPAREN=9
8 COMMA=10
9 COLON=11
10 SL_COMMENT=12
11 ML_COMMENT=13
12 WS=14
0 // $ANTLR 2.7.7 (20060906): "template.g" -> "TemplateParser.java"$
1
2 /*
3 [The "BSD licence"]
4 Copyright (c) 2003-2004 Terence Parr
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 package org.antlr.stringtemplate.language;
30 import org.antlr.stringtemplate.*;
31 import java.io.*;
32
33 import antlr.TokenBuffer;
34 import antlr.TokenStreamException;
35 import antlr.TokenStreamIOException;
36 import antlr.ANTLRException;
37 import antlr.LLkParser;
38 import antlr.Token;
39 import antlr.TokenStream;
40 import antlr.RecognitionException;
41 import antlr.NoViableAltException;
42 import antlr.MismatchedTokenException;
43 import antlr.SemanticException;
44 import antlr.ParserSharedInputState;
45 import antlr.collections.impl.BitSet;
46
47 /** A parser used to break up a single template into chunks, text literals
48 * and attribute expressions.
49 */
50 public class TemplateParser extends antlr.LLkParser implements TemplateParserTokenTypes
51 {
52
53 protected StringTemplate self;
54
55 public void reportError(RecognitionException e) {
56 StringTemplateGroup group = self.getGroup();
57 if ( group==StringTemplate.defaultGroup ) {
58 self.error("template parse error; template context is "+self.getEnclosingInstanceStackString(), e);
59 }
60 else {
61 self.error("template parse error in group "+self.getGroup().getName()+" line "+self.getGroupFileLine()+"; template context is "+self.getEnclosingInstanceStackString(), e);
62 }
63 }
64
65 protected TemplateParser(TokenBuffer tokenBuf, int k) {
66 super(tokenBuf,k);
67 tokenNames = _tokenNames;
68 }
69
70 public TemplateParser(TokenBuffer tokenBuf) {
71 this(tokenBuf,1);
72 }
73
74 protected TemplateParser(TokenStream lexer, int k) {
75 super(lexer,k);
76 tokenNames = _tokenNames;
77 }
78
79 public TemplateParser(TokenStream lexer) {
80 this(lexer,1);
81 }
82
83 public TemplateParser(ParserSharedInputState state) {
84 super(state,1);
85 tokenNames = _tokenNames;
86 }
87
88 public final void template(
89 StringTemplate self
90 ) throws RecognitionException, TokenStreamException {
91
92 Token s = null;
93 Token nl = null;
94
95 this.self = self;
96
97
98 try { // for error handling
99 {
100 _loop3:
101 do {
102 switch ( LA(1)) {
103 case LITERAL:
104 {
105 s = LT(1);
106 match(LITERAL);
107 self.addChunk(new StringRef(self,s.getText()));
108 break;
109 }
110 case NEWLINE:
111 {
112 nl = LT(1);
113 match(NEWLINE);
114
115 if ( LA(1)!=ELSE && LA(1)!=ENDIF ) {
116 self.addChunk(new NewlineRef(self,nl.getText()));
117 }
118
119 break;
120 }
121 case ACTION:
122 case IF:
123 case REGION_REF:
124 case REGION_DEF:
125 {
126 action(self);
127 break;
128 }
129 default:
130 {
131 break _loop3;
132 }
133 }
134 } while (true);
135 }
136 }
137 catch (RecognitionException ex) {
138 reportError(ex);
139 recover(ex,_tokenSet_0);
140 }
141 }
142
143 public final void action(
144 StringTemplate self
145 ) throws RecognitionException, TokenStreamException {
146
147 Token a = null;
148 Token i = null;
149 Token ei = null;
150 Token rr = null;
151 Token rd = null;
152
153 try { // for error handling
154 switch ( LA(1)) {
155 case ACTION:
156 {
157 a = LT(1);
158 match(ACTION);
159
160 String indent = ((ChunkToken)a).getIndentation();
161 ASTExpr c = self.parseAction(a.getText());
162 c.setIndentation(indent);
163 self.addChunk(c);
164
165 break;
166 }
167 case IF:
168 {
169 i = LT(1);
170 match(IF);
171
172 ConditionalExpr c = (ConditionalExpr)self.parseAction(i.getText());
173 // create and precompile the subtemplate
174 StringTemplate subtemplate =
175 new StringTemplate(self.getGroup(), null);
176 subtemplate.setEnclosingInstance(self);
177 subtemplate.setName(i.getText()+"_subtemplate");
178 self.addChunk(c);
179
180 template(subtemplate);
181 if ( c!=null ) c.setSubtemplate(subtemplate);
182 {
183 _loop6:
184 do {
185 if ((LA(1)==ELSEIF)) {
186 ei = LT(1);
187 match(ELSEIF);
188
189 ASTExpr ec = self.parseAction(ei.getText());
190 // create and precompile the subtemplate
191 StringTemplate elseIfSubtemplate =
192 new StringTemplate(self.getGroup(), null);
193 elseIfSubtemplate.setEnclosingInstance(self);
194 elseIfSubtemplate.setName(ei.getText()+"_subtemplate");
195
196 template(elseIfSubtemplate);
197 if ( c!=null ) c.addElseIfSubtemplate(ec, elseIfSubtemplate);
198 }
199 else {
200 break _loop6;
201 }
202
203 } while (true);
204 }
205 {
206 switch ( LA(1)) {
207 case ELSE:
208 {
209 match(ELSE);
210
211 // create and precompile the subtemplate
212 StringTemplate elseSubtemplate =
213 new StringTemplate(self.getGroup(), null);
214 elseSubtemplate.setEnclosingInstance(self);
215 elseSubtemplate.setName("else_subtemplate");
216
217 template(elseSubtemplate);
218 if ( c!=null ) c.setElseSubtemplate(elseSubtemplate);
219 break;
220 }
221 case ENDIF:
222 {
223 break;
224 }
225 default:
226 {
227 throw new NoViableAltException(LT(1), getFilename());
228 }
229 }
230 }
231 match(ENDIF);
232 break;
233 }
234 case REGION_REF:
235 {
236 rr = LT(1);
237 match(REGION_REF);
238
239 // define implicit template and
240 // convert <@r()> to <region__enclosingTemplate__r()>
241 String regionName = rr.getText();
242 String mangledRef = null;
243 boolean err = false;
244 // watch out for <@super.r()>; that does NOT def implicit region
245 // convert to <super.region__enclosingTemplate__r()>
246 if ( regionName.startsWith("super.") ) {
247 //System.out.println("super region ref "+regionName);
248 String regionRef =
249 regionName.substring("super.".length(),regionName.length());
250 String templateScope =
251 self.getGroup().getUnMangledTemplateName(self.getName());
252 StringTemplate scopeST = self.getGroup().lookupTemplate(templateScope);
253 if ( scopeST==null ) {
254 self.getGroup().error("reference to region within undefined template: "+
255 templateScope);
256 err=true;
257 }
258 if ( !scopeST.containsRegionName(regionRef) ) {
259 self.getGroup().error("template "+templateScope+" has no region called "+
260 regionRef);
261 err=true;
262 }
263 else {
264 mangledRef =
265 self.getGroup().getMangledRegionName(templateScope,regionRef);
266 mangledRef = "super."+mangledRef;
267 }
268 }
269 else {
270 //System.out.println("region ref "+regionName);
271 StringTemplate regionST =
272 self.getGroup().defineImplicitRegionTemplate(self,regionName);
273 mangledRef = regionST.getName();
274 }
275
276 if ( !err ) {
277 // treat as regular action: mangled template include
278 String indent = ((ChunkToken)rr).getIndentation();
279 ASTExpr c = self.parseAction(mangledRef+"()");
280 c.setIndentation(indent);
281 self.addChunk(c);
282 }
283
284 break;
285 }
286 case REGION_DEF:
287 {
288 rd = LT(1);
289 match(REGION_DEF);
290
291 String combinedNameTemplateStr = rd.getText();
292 int indexOfDefSymbol = combinedNameTemplateStr.indexOf("::=");
293 if ( indexOfDefSymbol>=1 ) {
294 String regionName = combinedNameTemplateStr.substring(0,indexOfDefSymbol);
295 String template =
296 combinedNameTemplateStr.substring(indexOfDefSymbol+3,
297 combinedNameTemplateStr.length());
298 StringTemplate regionST =
299 self.getGroup().defineRegionTemplate(self,
300 regionName,
301 template,
302 StringTemplate.REGION_EMBEDDED);
303 // treat as regular action: mangled template include
304 String indent = ((ChunkToken)rd).getIndentation();
305 ASTExpr c = self.parseAction(regionST.getName()+"()");
306 c.setIndentation(indent);
307 self.addChunk(c);
308 }
309 else {
310 self.error("embedded region definition screwed up");
311 }
312
313 break;
314 }
315 default:
316 {
317 throw new NoViableAltException(LT(1), getFilename());
318 }
319 }
320 }
321 catch (RecognitionException ex) {
322 reportError(ex);
323 recover(ex,_tokenSet_1);
324 }
325 }
326
327
328 public static final String[] _tokenNames = {
329 "<0>",
330 "EOF",
331 "<2>",
332 "NULL_TREE_LOOKAHEAD",
333 "LITERAL",
334 "NEWLINE",
335 "ACTION",
336 "IF",
337 "ELSEIF",
338 "ELSE",
339 "ENDIF",
340 "REGION_REF",
341 "REGION_DEF",
342 "EXPR",
343 "TEMPLATE",
344 "IF_EXPR",
345 "ESC_CHAR",
346 "ESC",
347 "HEX",
348 "SUBTEMPLATE",
349 "NESTED_PARENS",
350 "INDENT",
351 "COMMENT",
352 "LINE_BREAK"
353 };
354
355 private static final long[] mk_tokenSet_0() {
356 long[] data = { 1792L, 0L};
357 return data;
358 }
359 public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0());
360 private static final long[] mk_tokenSet_1() {
361 long[] data = { 8176L, 0L};
362 return data;
363 }
364 public static final BitSet _tokenSet_1 = new BitSet(mk_tokenSet_1());
365
366 }
0 SMAP
1 TemplateParser.java
2 G
3 *S G
4 *F
5 + 0 template.g
6 template.g
7 *L
8 1:3
9 1:4
10 1:5
11 1:6
12 1:8
13 1:9
14 1:10
15 1:11
16 1:12
17 1:13
18 1:14
19 1:15
20 1:16
21 1:17
22 1:19
23 1:20
24 1:21
25 1:22
26 1:23
27 1:24
28 1:25
29 1:26
30 1:27
31 1:28
32 1:29
33 1:30
34 1:31
35 1:32
36 40:54
37 42:56
38 43:57
39 44:58
40 45:59
41 46:60
42 47:61
43 48:62
44 49:63
45 50:64
46 53:89
47 53:90
48 53:91
49 53:99
50 53:137
51 53:138
52 53:139
53 53:140
54 53:141
55 53:142
56 54:96
57 57:93
58 57:100
59 57:101
60 57:102
61 57:103
62 57:104
63 57:105
64 57:106
65 57:107
66 57:108
67 57:130
68 57:131
69 57:132
70 57:133
71 57:134
72 57:135
73 57:136
74 58:94
75 58:111
76 58:112
77 58:113
78 58:114
79 60:116
80 61:117
81 62:118
82 64:122
83 64:123
84 64:124
85 64:125
86 64:126
87 64:127
88 68:144
89 68:145
90 68:146
91 68:154
92 68:155
93 68:316
94 68:317
95 68:318
96 68:319
97 68:320
98 68:321
99 68:322
100 68:323
101 68:324
102 68:325
103 68:326
104 69:148
105 69:156
106 69:157
107 69:158
108 69:159
109 71:161
110 72:162
111 73:163
112 74:164
113 77:149
114 77:168
115 77:169
116 77:170
117 77:171
118 79:173
119 80:174
120 81:175
121 82:176
122 83:177
123 84:178
124 85:179
125 88:181
126 88:182
127 90:150
128 90:183
129 90:184
130 90:185
131 90:186
132 90:187
133 90:188
134 90:199
135 90:200
136 90:201
137 90:202
138 90:204
139 90:205
140 92:190
141 93:191
142 94:192
143 95:193
144 96:194
145 97:195
146 100:197
147 102:198
148 105:207
149 105:208
150 105:209
151 105:210
152 105:226
153 105:227
154 105:228
155 105:229
156 105:230
157 107:212
158 108:213
159 109:214
160 110:215
161 111:216
162 114:218
163 115:219
164 118:232
165 120:151
166 120:235
167 120:236
168 120:237
169 120:238
170 122:240
171 123:241
172 124:242
173 125:243
174 126:244
175 127:245
176 128:246
177 129:247
178 130:248
179 131:249
180 132:250
181 133:251
182 134:252
183 135:253
184 136:254
185 137:255
186 138:256
187 139:257
188 140:258
189 141:259
190 142:260
191 143:261
192 144:262
193 145:263
194 146:264
195 147:265
196 148:266
197 149:267
198 150:268
199 151:269
200 152:270
201 153:271
202 154:272
203 155:273
204 156:274
205 157:275
206 159:277
207 160:278
208 161:279
209 162:280
210 163:281
211 164:282
212 165:283
213 168:152
214 168:287
215 168:288
216 168:289
217 168:290
218 170:292
219 171:293
220 172:294
221 173:295
222 174:296
223 175:297
224 176:298
225 177:299
226 178:300
227 179:301
228 180:302
229 181:303
230 182:304
231 183:305
232 184:306
233 185:307
234 186:308
235 187:309
236 188:310
237 189:311
238 190:312
239 *E
0 // $ANTLR 2.7.7 (20060906): "template.g" -> "TemplateParser.java"$
1
2 /*
3 [The "BSD licence"]
4 Copyright (c) 2003-2004 Terence Parr
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 package org.antlr.stringtemplate.language;
30 import org.antlr.stringtemplate.*;
31 import java.io.*;
32
33 public interface TemplateParserTokenTypes {
34 int EOF = 1;
35 int NULL_TREE_LOOKAHEAD = 3;
36 int LITERAL = 4;
37 int NEWLINE = 5;
38 int ACTION = 6;
39 int IF = 7;
40 int ELSEIF = 8;
41 int ELSE = 9;
42 int ENDIF = 10;
43 int REGION_REF = 11;
44 int REGION_DEF = 12;
45 int EXPR = 13;
46 int TEMPLATE = 14;
47 int IF_EXPR = 15;
48 int ESC_CHAR = 16;
49 int ESC = 17;
50 int HEX = 18;
51 int SUBTEMPLATE = 19;
52 int NESTED_PARENS = 20;
53 int INDENT = 21;
54 int COMMENT = 22;
55 int LINE_BREAK = 23;
56 }
0 // $ANTLR 2.7.7 (20060906): template.g -> TemplateParserTokenTypes.txt$
1 TemplateParser // output token vocab name
2 LITERAL=4
3 NEWLINE=5
4 ACTION=6
5 IF=7
6 ELSEIF=8
7 ELSE=9
8 ENDIF=10
9 REGION_REF=11
10 REGION_DEF=12
11 EXPR=13
12 TEMPLATE=14
13 IF_EXPR=15
14 ESC_CHAR=16
15 ESC=17
16 HEX=18
17 SUBTEMPLATE=19
18 NESTED_PARENS=20
19 INDENT=21
20 COMMENT=22
21 LINE_BREAK=23
0 #Generated by Maven
1 #Thu Nov 05 09:05:54 PST 2009
2 version=3.3-SNAPSHOT
3 groupId=org.antlr
4 artifactId=stringtemplate
0 <?xml version="1.0" encoding="UTF-8" ?>
1 <testsuite failures="0" time="0.625" errors="0" skipped="0" tests="315" name="org.antlr.stringtemplate.test.TestStringTemplate">
2 <properties>
3 <property name="java.runtime.name" value="Java(TM) SE Runtime Environment"/>
4 <property name="sun.boot.library.path" value="/usr/java/jdk1.6.0_11/jre/lib/amd64"/>
5 <property name="java.vm.version" value="11.0-b16"/>
6 <property name="java.vm.vendor" value="Sun Microsystems Inc."/>
7 <property name="java.vendor.url" value="http://java.sun.com/"/>
8 <property name="path.separator" value=":"/>
9 <property name="java.vm.name" value="Java HotSpot(TM) 64-Bit Server VM"/>
10 <property name="file.encoding.pkg" value="sun.io"/>
11 <property name="user.country" value="US"/>
12 <property name="sun.java.launcher" value="SUN_STANDARD"/>
13 <property name="sun.os.patch.level" value="unknown"/>
14 <property name="java.vm.specification.name" value="Java Virtual Machine Specification"/>
15 <property name="user.dir" value="/home/jim/stringtemplate-3.2.1"/>
16 <property name="java.runtime.version" value="1.6.0_11-b03"/>
17 <property name="java.awt.graphicsenv" value="sun.awt.X11GraphicsEnvironment"/>
18 <property name="basedir" value="/home/jim/stringtemplate-3.2.1"/>
19 <property name="java.endorsed.dirs" value="/usr/java/jdk1.6.0_11/jre/lib/endorsed"/>
20 <property name="os.arch" value="amd64"/>
21 <property name="surefire.real.class.path" value="/tmp/surefirebooter4751958194640846394.jar"/>
22 <property name="java.io.tmpdir" value="/tmp"/>
23 <property name="line.separator" value="
24 "/>
25 <property name="java.vm.specification.vendor" value="Sun Microsystems Inc."/>
26 <property name="os.name" value="Linux"/>
27 <property name="sun.jnu.encoding" value="UTF-8"/>
28 <property name="java.library.path" value="/usr/java/jdk1.6.0_11/jre/lib/amd64/server:/usr/java/jdk1.6.0_11/jre/lib/amd64:/usr/java/jdk1.6.0_11/jre/../lib/amd64:/usr/java/packages/lib/amd64:/lib:/usr/lib"/>
29 <property name="surefire.test.class.path" value="/home/jim/stringtemplate-3.2.1/target/test-classes:/home/jim/stringtemplate-3.2.1/target/classes:/home/jim/.m2/repository/junit/junit/4.5/junit-4.5.jar:/home/jim/.m2/repository/antlr/antlr/2.7.7/antlr-2.7.7.jar:/home/jim/stringtemplate-3.2.1/src:"/>
30 <property name="java.specification.name" value="Java Platform API Specification"/>
31 <property name="java.class.version" value="50.0"/>
32 <property name="sun.management.compiler" value="HotSpot 64-Bit Server Compiler"/>
33 <property name="os.version" value="2.6.18-164.2.1.el5"/>
34 <property name="user.home" value="/home/jim"/>
35 <property name="user.timezone" value="America/Los_Angeles"/>
36 <property name="java.awt.printerjob" value="sun.print.PSPrinterJob"/>
37 <property name="file.encoding" value="UTF-8"/>
38 <property name="java.specification.version" value="1.6"/>
39 <property name="user.name" value="jim"/>
40 <property name="java.class.path" value="/home/jim/stringtemplate-3.2.1/target/test-classes:/home/jim/stringtemplate-3.2.1/target/classes:/home/jim/.m2/repository/junit/junit/4.5/junit-4.5.jar:/home/jim/.m2/repository/antlr/antlr/2.7.7/antlr-2.7.7.jar:/home/jim/stringtemplate-3.2.1/src:"/>
41 <property name="java.vm.specification.version" value="1.0"/>
42 <property name="sun.arch.data.model" value="64"/>
43 <property name="java.home" value="/usr/java/jdk1.6.0_11/jre"/>
44 <property name="java.specification.vendor" value="Sun Microsystems Inc."/>
45 <property name="user.language" value="en"/>
46 <property name="java.vm.info" value="mixed mode"/>
47 <property name="java.version" value="1.6.0_11"/>
48 <property name="java.ext.dirs" value="/usr/java/jdk1.6.0_11/jre/lib/ext:/usr/java/packages/lib/ext"/>
49 <property name="sun.boot.class.path" value="/usr/java/jdk1.6.0_11/jre/lib/resources.jar:/usr/java/jdk1.6.0_11/jre/lib/rt.jar:/usr/java/jdk1.6.0_11/jre/lib/sunrsasign.jar:/usr/java/jdk1.6.0_11/jre/lib/jsse.jar:/usr/java/jdk1.6.0_11/jre/lib/jce.jar:/usr/java/jdk1.6.0_11/jre/lib/charsets.jar:/usr/java/jdk1.6.0_11/jre/classes"/>
50 <property name="java.vendor" value="Sun Microsystems Inc."/>
51 <property name="localRepository" value="/home/jim/.m2/repository"/>
52 <property name="file.separator" value="/"/>
53 <property name="java.vendor.url.bug" value="http://java.sun.com/cgi-bin/bugreport.cgi"/>
54 <property name="sun.cpu.endian" value="little"/>
55 <property name="sun.io.unicode.encoding" value="UnicodeLittle"/>
56 <property name="sun.cpu.isalist" value=""/>
57 </properties>
58 <testcase time="0.033" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testInterfaceFileFormat"/>
59 <testcase time="0.032" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNoGroupLoader"/>
60 <testcase time="0.003" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testCannotFindInterfaceFile"/>
61 <testcase time="0.027" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMultiDirGroupLoading"/>
62 <testcase time="0.003" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testGroupSatisfiesSingleInterface"/>
63 <testcase time="0.004" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testGroupExtendsSuperGroup"/>
64 <testcase time="0.003" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testGroupExtendsSuperGroupWithAngleBrackets"/>
65 <testcase time="0.004" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMissingInterfaceTemplate"/>
66 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMissingOptionalInterfaceTemplate"/>
67 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMismatchedInterfaceTemplate"/>
68 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testGroupFileFormat"/>
69 <testcase time="0.003" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testEscapedTemplateDelimiters"/>
70 <testcase time="0.005" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testTemplateParameterDecls"/>
71 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testTemplateRedef"/>
72 <testcase time="0.003" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMissingInheritedAttribute"/>
73 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testFormalArgumentAssignment"/>
74 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testUndefinedArgumentAssignment"/>
75 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testFormalArgumentAssignmentInApply"/>
76 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testUndefinedArgumentAssignmentInApply"/>
77 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testUndefinedAttributeReference"/>
78 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testUndefinedDefaultAttributeReference"/>
79 <testcase time="0.003" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testAngleBracketsWithGroupFile"/>
80 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testAngleBracketsNoGroup"/>
81 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRegionRef"/>
82 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testEmbeddedRegionRef"/>
83 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRegionRefAngleBrackets"/>
84 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testEmbeddedRegionRefAngleBrackets"/>
85 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testEmbeddedRegionRefWithNewlinesAngleBrackets"/>
86 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRegionRefWithDefAngleBrackets"/>
87 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRegionRefWithDefInConditional"/>
88 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRegionRefWithImplicitDefInConditional"/>
89 <testcase time="0.005" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRegionOverride"/>
90 <testcase time="0.003" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRegionOverrideRefSuperRegion"/>
91 <testcase time="0.003" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRegionOverrideRefSuperRegion3Levels"/>
92 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRegionOverrideRefSuperImplicitRegion"/>
93 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testEmbeddedRegionRedefError"/>
94 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testImplicitRegionRedefError"/>
95 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testImplicitOverriddenRegionRedefError"/>
96 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testUnknownRegionDefError"/>
97 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testSuperRegionRefError"/>
98 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMissingEndRegionError"/>
99 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMissingEndRegionErrorAngleBrackets"/>
100 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testSimpleInheritance"/>
101 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testOverrideInheritance"/>
102 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMultiLevelInheritance"/>
103 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testComplicatedInheritance"/>
104 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="test3LevelSuperRef"/>
105 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testExprInParens"/>
106 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMultipleAdditions"/>
107 <testcase time="0.004" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testCollectionAttributes"/>
108 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testParenthesizedExpression"/>
109 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testApplyTemplateNameExpression"/>
110 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testApplyTemplateNameTemplateEval"/>
111 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testTemplateNameExpression"/>
112 <testcase time="0.003" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMissingEndDelimiter"/>
113 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testSetButNotRefd"/>
114 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNullTemplateApplication"/>
115 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNullTemplateToMultiValuedApplication"/>
116 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testChangingAttrValueTemplateApplicationToVector"/>
117 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testChangingAttrValueRepeatedTemplateApplicationToVector"/>
118 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testAlternatingTemplateApplication"/>
119 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testExpressionAsRHSOfAssignment"/>
120 <testcase time="0.003" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testTemplateApplicationAsRHSOfAssignment"/>
121 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testParameterAndAttributeScoping"/>
122 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testComplicatedSeparatorExpr"/>
123 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testAttributeRefButtedUpAgainstEndifAndWhitespace"/>
124 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testStringCatenationOnSingleValuedAttributeViaTemplateLiteral"/>
125 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testStringCatenationOpOnArg"/>
126 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testStringCatenationOpOnArgWithEqualsInString"/>
127 <testcase time="0.005" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testApplyingTemplateFromDiskWithPrecompiledIF"/>
128 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMultiValuedAttributeWithAnonymousTemplateUsingIndexVariableI"/>
129 <testcase time="0.003" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testFindTemplateInCLASSPATH"/>
130 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testApplyTemplateToSingleValuedAttribute"/>
131 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testStringLiteralAsAttribute"/>
132 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testApplyTemplateToSingleValuedAttributeWithDefaultAttribute"/>
133 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testApplyAnonymousTemplateToSingleValuedAttribute"/>
134 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testApplyAnonymousTemplateToMultiValuedAttribute"/>
135 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testApplyAnonymousTemplateToAggregateAttribute"/>
136 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRepeatedApplicationOfTemplateToSingleValuedAttribute"/>
137 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRepeatedApplicationOfTemplateToMultiValuedAttributeWithSeparator"/>
138 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMultiValuedAttributeWithSeparator"/>
139 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testSingleValuedAttributes"/>
140 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIFTemplate"/>
141 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIFCondWithParensTemplate"/>
142 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIFCondWithParensDollarDelimsTemplate"/>
143 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIFBoolean"/>
144 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNestedIFTemplate"/>
145 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIFConditionWithTemplateApplication"/>
146 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testObjectPropertyReference"/>
147 <testcase time="0.004" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testApplyRepeatedAnonymousTemplateWithForeignTemplateRefToMultiValuedAttribute"/>
148 <testcase time="0.003" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRecursion"/>
149 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNestedAnonymousTemplates"/>
150 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testAnonymousTemplateAccessToEnclosingAttributes"/>
151 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNestedAnonymousTemplatesAgain"/>
152 <testcase time="0.003" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testEscapes"/>
153 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testEscapesOutsideExpressions"/>
154 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testElseClause"/>
155 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testElseIfClause"/>
156 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testElseIfClauseAngleBrackets"/>
157 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testElseIfClause2"/>
158 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testElseIfClauseAndElse"/>
159 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNestedIF"/>
160 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testEmbeddedMultiLineIF"/>
161 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testSimpleIndentOfAttributeList"/>
162 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIndentOfMultilineAttributes"/>
163 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIndentOfMultipleBlankLines"/>
164 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIndentBetweenLeftJustifiedLiterals"/>
165 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNestedIndent"/>
166 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testAlternativeWriter"/>
167 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testApplyAnonymousTemplateToMapAndSet"/>
168 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testDumpMapAndSet"/>
169 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testApplyAnonymousTemplateToArrayAndMapProperty"/>
170 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testSuperTemplateRef"/>
171 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testApplySuperTemplateRef"/>
172 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLazyEvalOfSuperInApplySuperTemplateRef"/>
173 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testTemplatePolymorphism"/>
174 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testListOfEmbeddedTemplateSeesEnclosingAttributes"/>
175 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testInheritArgumentFromRecursiveTemplateApplication"/>
176 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testDeliberateRecursiveTemplateApplication"/>
177 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testImmediateTemplateAsAttributeLoop"/>
178 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testTemplateAlias"/>
179 <testcase time="0.003" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testTemplateGetPropertyGetsAttribute"/>
180 <testcase time="0.003" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testComplicatedIndirectTemplateApplication"/>
181 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIndirectTemplateApplication"/>
182 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIndirectTemplateWithArgsApplication"/>
183 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNullIndirectTemplateApplication"/>
184 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNullIndirectTemplate"/>
185 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testHashMapPropertyFetch"/>
186 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testHashMapPropertyFetchEmbeddedStringTemplate"/>
187 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testEmbeddedComments"/>
188 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testEmbeddedCommentsAngleBracketed"/>
189 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLineBreak"/>
190 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLineBreak2"/>
191 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLineBreakNoWhiteSpace"/>
192 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLineBreakDollar"/>
193 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLineBreakDollar2"/>
194 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLineBreakNoWhiteSpaceDollar"/>
195 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testCharLiterals"/>
196 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNewlineNormalizationInTemplateString"/>
197 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNewlineNormalizationInTemplateStringPC"/>
198 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNewlineNormalizationInAttribute"/>
199 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testUnicodeLiterals"/>
200 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testEmptyIteratedValueGetsSeparator"/>
201 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMissingIteratedConditionalValueGetsNOSeparator"/>
202 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMissingIteratedConditionalValueGetsNOSeparator2"/>
203 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMissingIteratedDoubleConditionalValueGetsNOSeparator"/>
204 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIteratedConditionalWithEmptyElseValueGetsSeparator"/>
205 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testWhiteSpaceAtEndOfTemplate"/>
206 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testSizeZeroButNonNullListGetsNoOutput"/>
207 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNullListGetsNoOutput"/>
208 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testEmptyListGetsNoOutput"/>
209 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testEmptyListNoIteratorGetsNoOutput"/>
210 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testEmptyExprAsFirstLineGetsNoOutput"/>
211 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testSizeZeroOnLineByItselfGetsNoOutput"/>
212 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testSizeZeroOnLineWithIndentGetsNoOutput"/>
213 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testSimpleAutoIndent"/>
214 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testComputedPropertyName"/>
215 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNonNullButEmptyIteratorTestsFalse"/>
216 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testDoNotInheritAttributesThroughFormalArgs"/>
217 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testArgEvaluationContext"/>
218 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testPassThroughAttributes"/>
219 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testPassThroughAttributes2"/>
220 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testDefaultArgument"/>
221 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testDefaultArgument2"/>
222 <testcase time="0.003" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testDefaultArgumentManuallySet"/>
223 <testcase time="0.003" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testDefaultArgumentImplicitlySet"/>
224 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testDefaultArgumentAsTemplate"/>
225 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testDefaultArgumentAsTemplate2"/>
226 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testDoNotUseDefaultArgument"/>
227 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testDefaultArgumentInParensToEvalEarly"/>
228 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testArgumentsAsTemplates"/>
229 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testTemplateArgumentEvaluatedInSurroundingContext"/>
230 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testArgumentsAsTemplatesDefaultDelimiters"/>
231 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testDefaultArgsWhenNotInvoked"/>
232 <testcase time="0.009" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRendererForST"/>
233 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRendererWithFormat"/>
234 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRendererWithFormatAndList"/>
235 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRendererWithFormatAndSeparator"/>
236 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRendererWithFormatAndSeparatorAndNull"/>
237 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testEmbeddedRendererSeesEnclosing"/>
238 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRendererForGroup"/>
239 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testOverriddenRenderer"/>
240 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMap"/>
241 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMapValuesAreTemplates"/>
242 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMapKeyLookupViaTemplate"/>
243 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMapMissingDefaultValueIsEmpty"/>
244 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMapHiddenByFormalArg"/>
245 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMapEmptyValueAndAngleBracketStrings"/>
246 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMapDefaultValue"/>
247 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMapEmptyDefaultValue"/>
248 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMapDefaultValueIsKey"/>
249 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMapDefaultStringAsKey"/>
250 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMapDefaultIsDefaultString"/>
251 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMapViaEnclosingTemplates"/>
252 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMapViaEnclosingTemplates2"/>
253 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testEmptyGroupTemplate"/>
254 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testEmptyStringAndEmptyAnonTemplateAsParameterUsingAngleBracketLexer"/>
255 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testEmptyStringAndEmptyAnonTemplateAsParameterUsingDollarLexer"/>
256 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="test8BitEuroChars"/>
257 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="test16BitUnicodeChar"/>
258 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testFirstOp"/>
259 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testTruncOp"/>
260 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRestOp"/>
261 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRestOpEmptyList"/>
262 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testReUseOfRestResult"/>
263 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLastOp"/>
264 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testCombinedOp"/>
265 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testCatListAndSingleAttribute"/>
266 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testReUseOfCat"/>
267 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testCatListAndEmptyAttributes"/>
268 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNestedOp"/>
269 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testFirstWithOneAttributeOp"/>
270 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLastWithOneAttributeOp"/>
271 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLastWithLengthOneListAttributeOp"/>
272 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRestWithOneAttributeOp"/>
273 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRestWithLengthOneListAttributeOp"/>
274 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRepeatedRestOp"/>
275 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testRepeatedIteratedAttrFromArg"/>
276 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIncomingLists"/>
277 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIncomingListsAreNotModified"/>
278 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIncomingListsAreNotModified2"/>
279 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIncomingArraysAreOk"/>
280 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMultipleRefsToListAttribute"/>
281 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testApplyTemplateWithSingleFormalArgs"/>
282 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testApplyTemplateWithNoFormalArgs"/>
283 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testAnonTemplateArgs"/>
284 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testAnonTemplateWithArgHasNoITArg"/>
285 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testAnonTemplateArgs2"/>
286 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testFirstWithCatAttribute"/>
287 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testFirstWithListOfMaps"/>
288 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testJustCat"/>
289 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testCat2Attributes"/>
290 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testCat2AttributesWithApply"/>
291 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testCat3Attributes"/>
292 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testCatWithTemplateApplicationAsElement"/>
293 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testCatWithIFAsElement"/>
294 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testCatWithNullTemplateApplicationAsElement"/>
295 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testCatWithNestedTemplateApplicationAsElement"/>
296 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testListAsTemplateArgument"/>
297 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testSingleExprTemplateArgument"/>
298 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testSingleExprTemplateArgumentInApply"/>
299 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testSoleFormalTemplateArgumentInMultiApply"/>
300 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testSingleExprTemplateArgumentError"/>
301 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testInvokeIndirectTemplateWithSingleFormalArgs"/>
302 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testParallelAttributeIteration"/>
303 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testParallelAttributeIterationWithNullValue"/>
304 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testParallelAttributeIterationHasI"/>
305 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testParallelAttributeIterationWithDifferentSizes"/>
306 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testParallelAttributeIterationWithSingletons"/>
307 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testParallelAttributeIterationWithMismatchArgListSizes"/>
308 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testParallelAttributeIterationWithMissingArgs"/>
309 <testcase time="0.003" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testParallelAttributeIterationWithDifferentSizesTemplateRefInsideToo"/>
310 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testAnonTemplateOnLeftOfApply"/>
311 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testOverrideThroughConditional"/>
312 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNonPublicPropertyAccess"/>
313 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIndexVar"/>
314 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIndex0Var"/>
315 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIndexVarWithMultipleExprs"/>
316 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIndex0VarWithMultipleExprs"/>
317 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testArgumentContext"/>
318 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNoDotsInAttributeNames"/>
319 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNoDotsInTemplateNames"/>
320 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLineWrap"/>
321 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLineWrapWithNormalizedNewlines"/>
322 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLineWrapAnchored"/>
323 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testSubtemplatesAnchorToo"/>
324 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testFortranLineWrap"/>
325 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLineWrapWithDiffAnchor"/>
326 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLineWrapEdgeCase"/>
327 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLineWrapLastCharIsNewline"/>
328 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLineWrapCharAfterWrapIsNewline"/>
329 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLineWrapForAnonTemplate"/>
330 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLineWrapForAnonTemplateAnchored"/>
331 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLineWrapForAnonTemplateComplicatedWrap"/>
332 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIndentBeyondLineWidth"/>
333 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testIndentedExpr"/>
334 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNestedIndentedExpr"/>
335 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNestedWithIndentAndTrackStartOfExpr"/>
336 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLineDoesNotWrapDueToLiteral"/>
337 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testSingleValueWrap"/>
338 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLineWrapInNestedExpr"/>
339 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testBackslash"/>
340 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testBackslash2"/>
341 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testEscapeEscape"/>
342 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testEscapeEscapeNestedAngle"/>
343 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testListOfIntArrays"/>
344 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNullOptionSingleNullValue"/>
345 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNullOptionHasEmptyNullValue"/>
346 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNullOptionSingleNullValueInList"/>
347 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNullValueInList"/>
348 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNullValueInListNoNullOption"/>
349 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNullValueInListWithTemplateApply"/>
350 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNullValueInListWithTemplateApplyNullFirstValue"/>
351 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNullSingleValueInListWithTemplateApply"/>
352 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testNullSingleValueWithTemplateApply"/>
353 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLengthOp"/>
354 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLengthOpWithMap"/>
355 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLengthOpWithSet"/>
356 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLengthOpNull"/>
357 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLengthOpSingleValue"/>
358 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLengthOpPrimitive"/>
359 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLengthOpOfListWithNulls"/>
360 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testStripOpOfListWithNulls"/>
361 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testStripOpOfListOfListsWithNulls"/>
362 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testStripOpOfSingleAlt"/>
363 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testStripOpOfNull"/>
364 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testReUseOfStripResult"/>
365 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLengthOpOfStrippedListWithNulls"/>
366 <testcase time="0" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testLengthOpOfStrippedListWithNullsFrontAndBack"/>
367 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMapKeys"/>
368 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMapValues"/>
369 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testMapKeysWithIntegerType"/>
370 <testcase time="0.002" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testSuperReferenceInIfClause"/>
371 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testListLiteralWithEmptyElements"/>
372 <testcase time="0.001" classname="org.antlr.stringtemplate.test.TestStringTemplate" name="testTemplateApplicationAsOptionValue"/>
373 </testsuite>
0 -------------------------------------------------------------------------------
1 Test set: org.antlr.stringtemplate.test.TestStringTemplate
2 -------------------------------------------------------------------------------
3 Tests run: 315, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.656 sec
0 /*
1 [The "BSD licence"]
2 Copyright (c) 2003-2005 Terence Parr
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package org.antlr.stringtemplate.test;
28
29 import junit.framework.TestCase;
30 import org.antlr.stringtemplate.*;
31 import org.antlr.stringtemplate.language.AngleBracketTemplateLexer;
32 import org.antlr.stringtemplate.language.DefaultTemplateLexer;
33
34 import java.io.*;
35 import java.text.SimpleDateFormat;
36 import java.util.*;
37
38 public class TestStringTemplate extends TestCase {
39 static final String newline = System.getProperty("line.separator");
40
41 static class ErrorBuffer implements StringTemplateErrorListener {
42 StringBuffer errorOutput = new StringBuffer(500);
43 int n = 0;
44 public void error(String msg, Throwable e) {
45 n++;
46 if ( n>1 ) {
47 errorOutput.append('\n');
48 }
49 if ( e!=null ) {
50 StringWriter duh = new StringWriter();
51 e.printStackTrace(new PrintWriter(duh));
52 errorOutput.append(msg+": "+duh.toString());
53 }
54 else {
55 errorOutput.append(msg);
56 }
57 }
58 public void warning(String msg) {
59 n++;
60 errorOutput.append(msg);
61 }
62 public boolean equals(Object o) {
63 String me = toString();
64 String them = o.toString();
65 return me.equals(them);
66 }
67 public String toString() {
68 return errorOutput.toString();
69 }
70 }
71
72 public void testInterfaceFileFormat() throws Exception {
73 String groupI =
74 "interface test;" +newline+
75 "t();" +newline+
76 "bold(item);"+newline+
77 "optional duh(a,b,c);"+newline;
78 StringTemplateGroupInterface I =
79 new StringTemplateGroupInterface(new StringReader(groupI));
80
81 String expecting =
82 "interface test;\n" +
83 "t();\n" +
84 "bold(item);\n" +
85 "optional duh(a, b, c);\n";
86 assertEquals(expecting,I.toString());
87 }
88
89 public void testNoGroupLoader() throws Exception {
90 // this also tests the group loader
91 StringTemplateErrorListener errors = new ErrorBuffer();
92 String tmpdir = System.getProperty("java.io.tmpdir");
93
94 String templates =
95 "group testG implements blort;" +newline+
96 "t() ::= <<foo>>" +newline+
97 "bold(item) ::= <<foo>>"+newline+
98 "duh(a,b,c) ::= <<foo>>"+newline;
99
100 writeFile(tmpdir, "testG.stg", templates);
101
102 /*StringTemplateGroup group =*/
103 new StringTemplateGroup(new FileReader(tmpdir+"/testG.stg"), errors);
104
105 String expecting = "no group loader registered";
106 assertEquals(expecting,errors.toString());
107 }
108
109 public void testCannotFindInterfaceFile() throws Exception {
110 // this also tests the group loader
111 StringTemplateErrorListener errors = new ErrorBuffer();
112 String tmpdir = System.getProperty("java.io.tmpdir");
113 StringTemplateGroup.registerGroupLoader(new PathGroupLoader(tmpdir,errors));
114
115 String templates =
116 "group testG implements blort;" +newline+
117 "t() ::= <<foo>>" +newline+
118 "bold(item) ::= <<foo>>"+newline+
119 "duh(a,b,c) ::= <<foo>>"+newline;
120
121 writeFile(tmpdir, "testG.stg", templates);
122
123 /*StringTemplateGroup group =*/
124 new StringTemplateGroup(new FileReader(tmpdir+"/testG.stg"), errors);
125
126 String expecting = "no such interface file blort.sti";
127 assertEquals(expecting,errors.toString());
128 }
129
130 public void testMultiDirGroupLoading() throws Exception {
131 // this also tests the group loader
132 StringTemplateErrorListener errors = new ErrorBuffer();
133 String tmpdir = System.getProperty("java.io.tmpdir");
134 if ( !(new File(tmpdir+"/sub").exists()) ) {
135 if ( !(new File(tmpdir+"/sub").mkdir()) ) { // create a subdir
136 System.err.println("can't make subdir in test");
137 return;
138 }
139 }
140 StringTemplateGroup.registerGroupLoader(
141 new PathGroupLoader(tmpdir+":"+tmpdir+"/sub",errors)
142 );
143
144 String templates =
145 "group testG2;" +newline+
146 "t() ::= <<foo>>" +newline+
147 "bold(item) ::= <<foo>>"+newline+
148 "duh(a,b,c) ::= <<foo>>"+newline;
149
150 writeFile(tmpdir+"/sub", "testG2.stg", templates);
151
152 StringTemplateGroup group =
153 StringTemplateGroup.loadGroup("testG2");
154 String expecting = "group testG2;\n" +
155 "bold(item) ::= <<foo>>\n" +
156 "duh(a,b,c) ::= <<foo>>\n" +
157 "t() ::= <<foo>>\n";
158 assertEquals(expecting,group.toString());
159 }
160
161 public void testGroupSatisfiesSingleInterface() throws Exception {
162 // this also tests the group loader
163 StringTemplateErrorListener errors = new ErrorBuffer();
164 String tmpdir = System.getProperty("java.io.tmpdir");
165 StringTemplateGroup.registerGroupLoader(new PathGroupLoader(tmpdir,errors));
166 String groupI =
167 "interface testI;" +newline+
168 "t();" +newline+
169 "bold(item);"+newline+
170 "optional duh(a,b,c);"+newline;
171 writeFile(tmpdir, "testI.sti", groupI);
172
173 String templates =
174 "group testG implements testI;" +newline+
175 "t() ::= <<foo>>" +newline+
176 "bold(item) ::= <<foo>>"+newline+
177 "duh(a,b,c) ::= <<foo>>"+newline;
178
179 writeFile(tmpdir, "testG.stg", templates);
180
181 /*StringTemplateGroup group =*/
182 new StringTemplateGroup(new FileReader(tmpdir+"/testG.stg"), errors);
183
184 String expecting = ""; // should be no errors
185 assertEquals(expecting,errors.toString());
186 }
187
188 public void testGroupExtendsSuperGroup() throws Exception {
189 // this also tests the group loader
190 StringTemplateErrorListener errors = new ErrorBuffer();
191 String tmpdir = System.getProperty("java.io.tmpdir");
192 StringTemplateGroup.registerGroupLoader(
193 new PathGroupLoader(tmpdir,errors)
194 );
195 String superGroup =
196 "group superG;" +newline+
197 "bold(item) ::= <<*$item$*>>;\n"+newline;
198 writeFile(tmpdir, "superG.stg", superGroup);
199
200 String templates =
201 "group testG : superG;" +newline+
202 "main(x) ::= <<$bold(x)$>>"+newline;
203
204 writeFile(tmpdir, "testG.stg", templates);
205
206 StringTemplateGroup group =
207 new StringTemplateGroup(new FileReader(tmpdir+"/testG.stg"),
208 DefaultTemplateLexer.class,
209 errors);
210 StringTemplate st = group.getInstanceOf("main");
211 st.setAttribute("x", "foo");
212
213 String expecting = "*foo*";
214 assertEquals(expecting, st.toString());
215 }
216
217 public void testGroupExtendsSuperGroupWithAngleBrackets() throws Exception {
218 // this also tests the group loader
219 StringTemplateErrorListener errors = new ErrorBuffer();
220 String tmpdir = System.getProperty("java.io.tmpdir");
221 StringTemplateGroup.registerGroupLoader(
222 new PathGroupLoader(tmpdir,errors)
223 );
224 String superGroup =
225 "group superG;" +newline+
226 "bold(item) ::= <<*<item>*>>;\n"+newline;
227 writeFile(tmpdir, "superG.stg", superGroup);
228
229 String templates =
230 "group testG : superG;" +newline+
231 "main(x) ::= \"<bold(x)>\""+newline;
232
233 writeFile(tmpdir, "testG.stg", templates);
234
235 StringTemplateGroup group =
236 new StringTemplateGroup(new FileReader(tmpdir+"/testG.stg"),
237 errors);
238 StringTemplate st = group.getInstanceOf("main");
239 st.setAttribute("x", "foo");
240
241 String expecting = "*foo*";
242 assertEquals(expecting, st.toString());
243 }
244
245 public void testMissingInterfaceTemplate() throws Exception {
246 // this also tests the group loader
247 StringTemplateErrorListener errors = new ErrorBuffer();
248 String tmpdir = System.getProperty("java.io.tmpdir");
249 StringTemplateGroup.registerGroupLoader(new PathGroupLoader(tmpdir,errors));
250 String groupI =
251 "interface testI;" +newline+
252 "t();" +newline+
253 "bold(item);"+newline+
254 "optional duh(a,b,c);"+newline;
255 writeFile(tmpdir, "testI.sti", groupI);
256
257 String templates =
258 "group testG implements testI;" +newline+
259 "t() ::= <<foo>>" +newline+
260 "duh(a,b,c) ::= <<foo>>"+newline;
261
262 writeFile(tmpdir, "testG.stg", templates);
263
264 /*StringTemplateGroup group =*/
265 new StringTemplateGroup(new FileReader(tmpdir+"/testG.stg"), errors);
266
267 String expecting = "group testG does not satisfy interface testI: missing templates [bold]";
268 assertEquals(expecting, errors.toString());
269 }
270
271 public void testMissingOptionalInterfaceTemplate() throws Exception {
272 // this also tests the group loader
273 StringTemplateErrorListener errors = new ErrorBuffer();
274 String tmpdir = System.getProperty("java.io.tmpdir");
275 StringTemplateGroup.registerGroupLoader(new PathGroupLoader(tmpdir,errors));
276 String groupI =
277 "interface testI;" +newline+
278 "t();" +newline+
279 "bold(item);"+newline+
280 "optional duh(a,b,c);"+newline;
281 writeFile(tmpdir, "testI.sti", groupI);
282
283 String templates =
284 "group testG implements testI;" +newline+
285 "t() ::= <<foo>>" +newline+
286 "bold(item) ::= <<foo>>";
287
288 writeFile(tmpdir, "testG.stg", templates);
289
290 /*StringTemplateGroup group =*/
291 new StringTemplateGroup(new FileReader(tmpdir+"/testG.stg"), errors);
292
293 String expecting = ""; // should be NO errors
294 assertEquals(expecting, errors.toString());
295 }
296
297 public void testMismatchedInterfaceTemplate() throws Exception {
298 // this also tests the group loader
299 StringTemplateErrorListener errors = new ErrorBuffer();
300 String tmpdir = System.getProperty("java.io.tmpdir");
301 StringTemplateGroup.registerGroupLoader(new PathGroupLoader(tmpdir,errors));
302 String groupI =
303 "interface testI;" +newline+
304 "t();" +newline+
305 "bold(item);"+newline+
306 "optional duh(a,b,c);"+newline;
307 writeFile(tmpdir, "testI.sti", groupI);
308
309 String templates =
310 "group testG implements testI;" +newline+
311 "t() ::= <<foo>>" +newline+
312 "bold(item) ::= <<foo>>"+newline+
313 "duh(a,c) ::= <<foo>>"+newline;
314
315 writeFile(tmpdir, "testG.stg", templates);
316
317 /*StringTemplateGroup group =*/
318 new StringTemplateGroup(new FileReader(tmpdir+"/testG.stg"), errors);
319
320 String expecting = "group testG does not satisfy interface testI: mismatched arguments on these templates [optional duh(a, b, c)]";
321 assertEquals(expecting,errors.toString());
322 }
323
324 public void testGroupFileFormat() throws Exception {
325 String templates =
326 "group test;" +newline+
327 "t() ::= \"literal template\"" +newline+
328 "bold(item) ::= \"<b>$item$</b>\""+newline+
329 "duh() ::= <<"+newline+"xx"+newline+">>"+newline;
330 StringTemplateGroup group =
331 new StringTemplateGroup(new StringReader(templates),
332 DefaultTemplateLexer.class);
333
334 String expecting = "group test;" +newline+
335 "bold(item) ::= <<<b>$item$</b>>>" +newline+
336 "duh() ::= <<xx>>" +newline+
337 "t() ::= <<literal template>>"+newline;
338 assertEquals(expecting,group.toString());
339
340 StringTemplate a = group.getInstanceOf("t");
341 expecting = "literal template";
342 assertEquals(expecting,a.toString());
343
344 StringTemplate b = group.getInstanceOf("bold");
345 b.setAttribute("item", "dork");
346 expecting = "<b>dork</b>";
347 assertEquals(expecting,b.toString());
348 }
349
350 public void testEscapedTemplateDelimiters() throws Exception {
351 String templates =
352 "group test;" +newline+
353 "t() ::= <<$\"literal\":{a|$a$\\}}$ template\n>>" +newline+
354 "bold(item) ::= <<<b>$item$</b\\>>>"+newline+
355 "duh() ::= <<"+newline+"xx"+newline+">>"+newline;
356 StringTemplateGroup group =
357 new StringTemplateGroup(new StringReader(templates),
358 DefaultTemplateLexer.class);
359
360 String expecting = "group test;" +newline+
361 "bold(item) ::= <<<b>$item$</b>>>" +newline+
362 "duh() ::= <<xx>>" +newline+
363 "t() ::= <<$\"literal\":{a|$a$\\}}$ template>>"+newline;
364 assertEquals(expecting,group.toString());
365
366 StringTemplate b = group.getInstanceOf("bold");
367 b.setAttribute("item", "dork");
368 expecting = "<b>dork</b>";
369 assertEquals(expecting,b.toString());
370
371 StringTemplate a = group.getInstanceOf("t");
372 expecting = "literal} template";
373 assertEquals(expecting,a.toString());
374 }
375
376 /** Check syntax and setAttribute-time errors */
377 public void testTemplateParameterDecls() throws Exception {
378 String templates =
379 "group test;" +newline+
380 "t() ::= \"no args but ref $foo$\"" +newline+
381 "t2(item) ::= \"decl but not used is ok\""+newline +
382 "t3(a,b,c,d) ::= <<$a$ $d$>>"+newline+
383 "t4(a,b,c,d) ::= <<$a$ $b$ $c$ $d$>>"+newline
384 ;
385 StringTemplateGroup group =
386 new StringTemplateGroup(new StringReader(templates),
387 DefaultTemplateLexer.class);
388
389 // check setting unknown arg in empty formal list
390 StringTemplate a = group.getInstanceOf("t");
391 String error = null;
392 try {
393 a.setAttribute("foo", "x"); // want NoSuchElementException
394 }
395 catch (NoSuchElementException e) {
396 error = e.getMessage();
397 }
398 String expecting = "no such attribute: foo in template context [t]";
399 assertEquals(expecting,error);
400
401 // check setting known arg
402 a = group.getInstanceOf("t2");
403 a.setAttribute("item", "x"); // shouldn't get exception
404
405 // check setting unknown arg in nonempty list of formal args
406 a = group.getInstanceOf("t3");
407 a.setAttribute("b", "x");
408 }
409
410 public void testTemplateRedef() throws Exception {
411 String templates =
412 "group test;" +newline+
413 "a() ::= \"x\"" +newline+
414 "b() ::= \"y\"" +newline+
415 "a() ::= \"z\"" +newline;
416 StringTemplateErrorListener errors = new ErrorBuffer();
417 /*StringTemplateGroup group =*/
418 new StringTemplateGroup(new StringReader(templates), errors);
419 String expecting = "redefinition of template: a";
420 assertEquals(expecting,errors.toString());
421 }
422
423 public void testMissingInheritedAttribute() throws Exception {
424 String templates =
425 "group test;" +newline+
426 "page(title,font) ::= <<"+newline +
427 "<html>"+newline +
428 "<body>"+newline +
429 "$title$<br>"+newline +
430 "$body()$"+newline +
431 "</body>"+newline +
432 "</html>"+newline +
433 ">>"+newline +
434 "body() ::= \"<font face=$font$>my body</font>\"" +newline;
435 StringTemplateGroup group =
436 new StringTemplateGroup(new StringReader(templates),
437 DefaultTemplateLexer.class);
438 StringTemplate t = group.getInstanceOf("page");
439 t.setAttribute("title","my title");
440 t.setAttribute("font","Helvetica"); // body() will see it
441 t.toString(); // should be no problem
442 }
443
444 public void testFormalArgumentAssignment() throws Exception {
445 String templates =
446 "group test;" +newline+
447 "page() ::= <<$body(font=\"Times\")$>>"+newline +
448 "body(font) ::= \"<font face=$font$>my body</font>\"" +newline;
449 StringTemplateGroup group =
450 new StringTemplateGroup(new StringReader(templates),
451 DefaultTemplateLexer.class);
452 StringTemplate t = group.getInstanceOf("page");
453 String expecting = "<font face=Times>my body</font>";
454 assertEquals(expecting, t.toString());
455 }
456
457 public void testUndefinedArgumentAssignment() throws Exception {
458 String templates =
459 "group test;" +newline+
460 "page(x) ::= <<$body(font=x)$>>"+newline +
461 "body() ::= \"<font face=$font$>my body</font>\"" +newline;
462 StringTemplateGroup group =
463 new StringTemplateGroup(new StringReader(templates),
464 DefaultTemplateLexer.class);
465 StringTemplate t = group.getInstanceOf("page");
466 t.setAttribute("x","Times");
467 String error = "";
468 try {
469 t.toString();
470 }
471 catch (NoSuchElementException iae) {
472 error = iae.getMessage();
473 }
474 String expecting = "template body has no such attribute: font in template context [page <invoke body arg context>]";
475 assertEquals(expecting, error);
476 }
477
478 public void testFormalArgumentAssignmentInApply() throws Exception {
479 String templates =
480 "group test;" +newline+
481 "page(name) ::= <<$name:bold(font=\"Times\")$>>"+newline +
482 "bold(font) ::= \"<font face=$font$><b>$it$</b></font>\"" +newline;
483 StringTemplateGroup group =
484 new StringTemplateGroup(new StringReader(templates),
485 DefaultTemplateLexer.class);
486 StringTemplate t = group.getInstanceOf("page");
487 t.setAttribute("name", "Ter");
488 String expecting = "<font face=Times><b>Ter</b></font>";
489 assertEquals(expecting, t.toString());
490 }
491
492 public void testUndefinedArgumentAssignmentInApply() throws Exception {
493 String templates =
494 "group test;" +newline+
495 "page(name,x) ::= <<$name:bold(font=x)$>>"+newline +
496 "bold() ::= \"<font face=$font$><b>$it$</b></font>\"" +newline;
497 StringTemplateGroup group =
498 new StringTemplateGroup(new StringReader(templates),
499 DefaultTemplateLexer.class);
500 StringTemplate t = group.getInstanceOf("page");
501 t.setAttribute("x","Times");
502 t.setAttribute("name", "Ter");
503 String error = "";
504 try {
505 t.toString();
506 }
507 catch (NoSuchElementException iae) {
508 error = iae.getMessage();
509 }
510 String expecting = "template bold has no such attribute: font in template context [page <invoke bold arg context>]";
511 assertEquals(expecting,error);
512 }
513
514 public void testUndefinedAttributeReference() throws Exception {
515 String templates =
516 "group test;" +newline+
517 "page() ::= <<$bold()$>>"+newline +
518 "bold() ::= \"$name$\"" +newline;
519 StringTemplateGroup group =
520 new StringTemplateGroup(new StringReader(templates),
521 DefaultTemplateLexer.class);
522 StringTemplate t = group.getInstanceOf("page");
523 String error = "";
524 try {
525 t.toString();
526 }
527 catch (NoSuchElementException iae) {
528 error = iae.getMessage();
529 }
530 String expecting = "no such attribute: name in template context [page bold]";
531 assertEquals(expecting,error);
532 }
533
534 public void testUndefinedDefaultAttributeReference() throws Exception {
535 String templates =
536 "group test;" +newline+
537 "page() ::= <<$bold()$>>"+newline +
538 "bold() ::= \"$it$\"" +newline;
539 StringTemplateGroup group =
540 new StringTemplateGroup(new StringReader(templates),
541 DefaultTemplateLexer.class);
542 StringTemplate t = group.getInstanceOf("page");
543 String error = "";
544 try {
545 t.toString();
546 }
547 catch (NoSuchElementException nse) {
548 error = nse.getMessage();
549 }
550 String expecting = "no such attribute: it in template context [page bold]";
551 assertEquals(expecting,error);
552 }
553
554 public void testAngleBracketsWithGroupFile() throws Exception {
555 String templates =
556 "group test;" +newline+
557 "a(s) ::= \"<s:{case <i> : <it> break;}>\""+newline +
558 "b(t) ::= \"<t; separator=\\\",\\\">\"" +newline+
559 "c(t) ::= << <t; separator=\",\"> >>" +newline;
560 // mainly testing to ensure we don't get parse errors of above
561 StringTemplateGroup group =
562 new StringTemplateGroup(
563 new StringReader(templates));
564 StringTemplate t = group.getInstanceOf("a");
565 t.setAttribute("s","Test");
566 String expecting = "case 1 : Test break;";
567 assertEquals(expecting, t.toString());
568 }
569
570 public void testAngleBracketsNoGroup() throws Exception {
571 StringTemplate st =new StringTemplate(
572 "Tokens : <rules; separator=\"|\"> ;",
573 AngleBracketTemplateLexer.class);
574 st.setAttribute("rules", "A");
575 st.setAttribute("rules", "B");
576 String expecting = "Tokens : A|B ;";
577 assertEquals(expecting, st.toString());
578 }
579
580 public void testRegionRef() throws Exception {
581 String templates =
582 "group test;" +newline+
583 "a() ::= \"X$@r()$Y\"" +newline;
584 StringTemplateGroup group =
585 new StringTemplateGroup(new StringReader(templates),
586 DefaultTemplateLexer.class);
587 StringTemplate st = group.getInstanceOf("a");
588 String result = st.toString();
589 String expecting = "XY";
590 assertEquals(expecting, result);
591 }
592
593 public void testEmbeddedRegionRef() throws Exception {
594 String templates =
595 "group test;" +newline+
596 "a() ::= \"X$@r$blort$@end$Y\"" +newline;
597 StringTemplateGroup group =
598 new StringTemplateGroup(new StringReader(templates),
599 DefaultTemplateLexer.class);
600 StringTemplate st = group.getInstanceOf("a");
601 String result = st.toString();
602 String expecting = "XblortY";
603 assertEquals(expecting, result);
604 }
605
606 public void testRegionRefAngleBrackets() throws Exception {
607 String templates =
608 "group test;" +newline+
609 "a() ::= \"X<@r()>Y\"" +newline;
610 StringTemplateGroup group =
611 new StringTemplateGroup(new StringReader(templates));
612 StringTemplate st = group.getInstanceOf("a");
613 String result = st.toString();
614 String expecting = "XY";
615 assertEquals(expecting, result);
616 }
617
618 public void testEmbeddedRegionRefAngleBrackets() throws Exception {
619 String templates =
620 "group test;" +newline+
621 "a() ::= \"X<@r>blort<@end>Y\"" +newline;
622 StringTemplateGroup group =
623 new StringTemplateGroup(new StringReader(templates));
624 StringTemplate st = group.getInstanceOf("a");
625 String result = st.toString();
626 String expecting = "XblortY";
627 assertEquals(expecting, result);
628 }
629
630 // FIXME: This test fails due to inserted white space...
631 public void testEmbeddedRegionRefWithNewlinesAngleBrackets() throws Exception {
632 String templates =
633 "group test;" +newline+
634 "a() ::= \"X<@r>" +newline+
635 "blort" +newline+
636 "<@end>" +newline+
637 "Y\"" +newline;
638 StringTemplateGroup group =
639 new StringTemplateGroup(new StringReader(templates));
640 StringTemplate st = group.getInstanceOf("a");
641 String result = st.toString();
642 String expecting = "XblortY";
643 assertEquals(expecting, result);
644 }
645
646 public void testRegionRefWithDefAngleBrackets() throws Exception {
647 String templates =
648 "group test;" +newline+
649 "a() ::= \"X<@r()>Y\"" +newline+
650 "@a.r() ::= \"foo\"" +newline;
651 StringTemplateGroup group =
652 new StringTemplateGroup(new StringReader(templates));
653 StringTemplate st = group.getInstanceOf("a");
654 String result = st.toString();
655 String expecting = "XfooY";
656 assertEquals(expecting, result);
657 }
658
659 public void testRegionRefWithDefInConditional() throws Exception {
660 String templates =
661 "group test;" +newline+
662 "a(v) ::= \"X<if(v)>A<@r()>B<endif>Y\"" +newline+
663 "@a.r() ::= \"foo\"" +newline;
664 StringTemplateGroup group =
665 new StringTemplateGroup(new StringReader(templates));
666 StringTemplate st = group.getInstanceOf("a");
667 st.setAttribute("v", "true");
668 String result = st.toString();
669 String expecting = "XAfooBY";
670 assertEquals(expecting, result);
671 }
672
673 public void testRegionRefWithImplicitDefInConditional() throws Exception {
674 String templates =
675 "group test;" +newline+
676 "a(v) ::= \"X<if(v)>A<@r>yo<@end>B<endif>Y\"" +newline+
677 "@a.r() ::= \"foo\"" +newline;
678 StringTemplateErrorListener errors = new ErrorBuffer();
679 StringTemplateGroup group =
680 new StringTemplateGroup(new StringReader(templates),
681 errors);
682 StringTemplate st = group.getInstanceOf("a");
683 st.setAttribute("v", "true");
684 String result = st.toString();
685 String expecting = "XAyoBY";
686 assertEquals(expecting, result);
687
688 String err_result = errors.toString();
689 String err_expecting = "group test line 3: redefinition of template region: @a.r";
690 assertEquals(err_expecting,err_result);
691 }
692
693 public void testRegionOverride() throws Exception {
694 String templates1 =
695 "group super;" +newline+
696 "a() ::= \"X<@r()>Y\"" +
697 "@a.r() ::= \"foo\"" +newline;
698 StringTemplateGroup group =
699 new StringTemplateGroup(new StringReader(templates1));
700
701 String templates2 =
702 "group sub;" +newline+
703 "@a.r() ::= \"foo\"" +newline;
704 StringTemplateGroup subGroup =
705 new StringTemplateGroup(new StringReader(templates2),
706 AngleBracketTemplateLexer.class,
707 null,
708 group);
709
710 StringTemplate st = subGroup.getInstanceOf("a");
711 String result = st.toString();
712 String expecting = "XfooY";
713 assertEquals(expecting, result);
714 }
715
716 public void testRegionOverrideRefSuperRegion() throws Exception {
717 String templates1 =
718 "group super;" +newline+
719 "a() ::= \"X<@r()>Y\"" +
720 "@a.r() ::= \"foo\"" +newline;
721 StringTemplateGroup group =
722 new StringTemplateGroup(new StringReader(templates1));
723
724 String templates2 =
725 "group sub;" +newline+
726 "@a.r() ::= \"A<@super.r()>B\"" +newline;
727 StringTemplateGroup subGroup =
728 new StringTemplateGroup(new StringReader(templates2),
729 AngleBracketTemplateLexer.class,
730 null,
731 group);
732
733 StringTemplate st = subGroup.getInstanceOf("a");
734 String result = st.toString();
735 String expecting = "XAfooBY";
736 assertEquals(expecting, result);
737 }
738
739 public void testRegionOverrideRefSuperRegion3Levels() throws Exception {
740 // Bug: This was causing infinite recursion:
741 // getInstanceOf(super::a)
742 // getInstanceOf(sub::a)
743 // getInstanceOf(subsub::a)
744 // getInstanceOf(subsub::region__a__r)
745 // getInstanceOf(subsub::super.region__a__r)
746 // getInstanceOf(subsub::super.region__a__r)
747 // getInstanceOf(subsub::super.region__a__r)
748 // ...
749 // Somehow, the ref to super in subsub is not moving up the chain
750 // to the @super.r(); oh, i introduced a bug when i put setGroup
751 // into STG.getInstanceOf()!
752
753 String templates1 =
754 "group super;" +newline+
755 "a() ::= \"X<@r()>Y\"" +
756 "@a.r() ::= \"foo\"" +newline;
757 StringTemplateGroup group =
758 new StringTemplateGroup(new StringReader(templates1));
759
760 String templates2 =
761 "group sub;" +newline+
762 "@a.r() ::= \"<@super.r()>2\"" +newline;
763 StringTemplateGroup subGroup =
764 new StringTemplateGroup(new StringReader(templates2),
765 AngleBracketTemplateLexer.class,
766 null,
767 group);
768
769 String templates3 =
770 "group subsub;" +newline+
771 "@a.r() ::= \"<@super.r()>3\"" +newline;
772 StringTemplateGroup subSubGroup =
773 new StringTemplateGroup(new StringReader(templates3),
774 AngleBracketTemplateLexer.class,
775 null,
776 subGroup);
777
778 StringTemplate st = subSubGroup.getInstanceOf("a");
779 String result = st.toString();
780 String expecting = "Xfoo23Y";
781 assertEquals(expecting, result);
782 }
783
784 public void testRegionOverrideRefSuperImplicitRegion() throws Exception {
785 String templates1 =
786 "group super;" +newline+
787 "a() ::= \"X<@r>foo<@end>Y\""+newline;
788 StringTemplateGroup group =
789 new StringTemplateGroup(new StringReader(templates1));
790
791 String templates2 =
792 "group sub;" +newline+
793 "@a.r() ::= \"A<@super.r()>\"" +newline;
794 StringTemplateGroup subGroup =
795 new StringTemplateGroup(new StringReader(templates2),
796 AngleBracketTemplateLexer.class,
797 null,
798 group);
799
800 StringTemplate st = subGroup.getInstanceOf("a");
801 String result = st.toString();
802 String expecting = "XAfooY";
803 assertEquals(expecting, result);
804 }
805
806 public void testEmbeddedRegionRedefError() throws Exception {
807 // cannot define an embedded template within group
808 String templates =
809 "group test;" +newline+
810 "a() ::= \"X<@r>dork<@end>Y\"" +
811 "@a.r() ::= \"foo\"" +newline;
812 StringTemplateErrorListener errors = new ErrorBuffer();
813 StringTemplateGroup group =
814 new StringTemplateGroup(new StringReader(templates),
815 errors);
816 StringTemplate st = group.getInstanceOf("a");
817 st.toString();
818 String result = errors.toString();
819 String expecting = "group test line 2: redefinition of template region: @a.r";
820 assertEquals(expecting, result);
821 }
822
823 public void testImplicitRegionRedefError() throws Exception {
824 // cannot define an implicitly-defined template more than once
825 String templates =
826 "group test;" +newline+
827 "a() ::= \"X<@r()>Y\"" +newline+
828 "@a.r() ::= \"foo\"" +newline+
829 "@a.r() ::= \"bar\"" +newline;
830 StringTemplateErrorListener errors = new ErrorBuffer();
831 StringTemplateGroup group =
832 new StringTemplateGroup(new StringReader(templates),
833 errors);
834 StringTemplate st = group.getInstanceOf("a");
835 st.toString();
836 String result = errors.toString();
837 String expecting = "group test line 4: redefinition of template region: @a.r";
838 assertEquals(expecting, result);
839 }
840
841 public void testImplicitOverriddenRegionRedefError() throws Exception {
842 String templates1 =
843 "group super;" +newline+
844 "a() ::= \"X<@r()>Y\"" +
845 "@a.r() ::= \"foo\"" +newline;
846 StringTemplateGroup group =
847 new StringTemplateGroup(new StringReader(templates1));
848
849 String templates2 =
850 "group sub;" +newline+
851 "@a.r() ::= \"foo\"" +newline+
852 "@a.r() ::= \"bar\"" +newline;
853 StringTemplateErrorListener errors = new ErrorBuffer();
854 StringTemplateGroup subGroup =
855 new StringTemplateGroup(new StringReader(templates2),
856 AngleBracketTemplateLexer.class,
857 errors,
858 group);
859
860 /*StringTemplate st =*/ subGroup.getInstanceOf("a");
861 String result = errors.toString();
862 String expecting = "group sub line 3: redefinition of template region: @a.r";
863 assertEquals(expecting, result);
864 }
865
866 public void testUnknownRegionDefError() throws Exception {
867 // cannot define an implicitly-defined template more than once
868 String templates =
869 "group test;" +newline+
870 "a() ::= \"X<@r()>Y\"" +newline+
871 "@a.q() ::= \"foo\"" +newline;
872 StringTemplateErrorListener errors = new ErrorBuffer();
873 StringTemplateGroup group =
874 new StringTemplateGroup(new StringReader(templates),
875 errors);
876 StringTemplate st = group.getInstanceOf("a");
877 st.toString();
878 String result = errors.toString();
879 String expecting = "group test line 3: template a has no region called q";
880 assertEquals(expecting, result);
881 }
882
883 public void testSuperRegionRefError() throws Exception {
884 String templates1 =
885 "group super;" +newline+
886 "a() ::= \"X<@r()>Y\"" +
887 "@a.r() ::= \"foo\"" +newline;
888 StringTemplateGroup group =
889 new StringTemplateGroup(new StringReader(templates1));
890
891 String templates2 =
892 "group sub;" +newline+
893 "@a.r() ::= \"A<@super.q()>B\"" +newline;
894 StringTemplateErrorListener errors = new ErrorBuffer();
895 StringTemplateGroup subGroup =
896 new StringTemplateGroup(new StringReader(templates2),
897 AngleBracketTemplateLexer.class,
898 errors,
899 group);
900
901 /*StringTemplate st =*/ subGroup.getInstanceOf("a");
902 String result = errors.toString();
903 String expecting = "template a has no region called q";
904 assertEquals(expecting, result);
905 }
906
907 public void testMissingEndRegionError() throws Exception {
908 // cannot define an implicitly-defined template more than once
909 String templates =
910 "group test;" +newline+
911 "a() ::= \"X$@r$foo\"" +newline;
912 StringTemplateErrorListener errors = new ErrorBuffer();
913 StringTemplateGroup group =
914 new StringTemplateGroup(new StringReader(templates),
915 DefaultTemplateLexer.class,
916 errors,
917 null);
918 StringTemplate st = group.getInstanceOf("a");
919 st.toString();
920 String result = errors.toString();
921 String expecting = "missing region r $@end$ tag";
922 assertEquals(expecting, result);
923 }
924
925 public void testMissingEndRegionErrorAngleBrackets() throws Exception {
926 // cannot define an implicitly-defined template more than once
927 String templates =
928 "group test;" +newline+
929 "a() ::= \"X<@r>foo\"" +newline;
930 StringTemplateErrorListener errors = new ErrorBuffer();
931 StringTemplateGroup group =
932 new StringTemplateGroup(new StringReader(templates),
933 errors);
934 StringTemplate st = group.getInstanceOf("a");
935 st.toString();
936 String result = errors.toString();
937 String expecting = "missing region r <@end> tag";
938 assertEquals(expecting, result);
939 }
940
941 public void testSimpleInheritance() throws Exception {
942 // make a bold template in the super group that you can inherit from sub
943 StringTemplateGroup supergroup = new StringTemplateGroup("super");
944 StringTemplateGroup subgroup = new StringTemplateGroup("sub");
945 /*StringTemplate bold =*/ supergroup.defineTemplate("bold", "<b>$it$</b>");
946 subgroup.setSuperGroup(supergroup);
947 StringTemplateErrorListener errors = new ErrorBuffer();
948 subgroup.setErrorListener(errors);
949 supergroup.setErrorListener(errors);
950 StringTemplate duh = new StringTemplate(subgroup, "$name:bold()$");
951 duh.setAttribute("name", "Terence");
952 String expecting = "<b>Terence</b>";
953 assertEquals(expecting,duh.toString());
954 }
955
956 public void testOverrideInheritance() throws Exception {
957 // make a bold template in the super group and one in sub group
958 StringTemplateGroup supergroup = new StringTemplateGroup("super");
959 StringTemplateGroup subgroup = new StringTemplateGroup("sub");
960 supergroup.defineTemplate("bold", "<b>$it$</b>");
961 subgroup.defineTemplate("bold", "<strong>$it$</strong>");
962 subgroup.setSuperGroup(supergroup);
963 StringTemplateErrorListener errors = new ErrorBuffer();
964 subgroup.setErrorListener(errors);
965 supergroup.setErrorListener(errors);
966 StringTemplate duh = new StringTemplate(subgroup, "$name:bold()$");
967 duh.setAttribute("name", "Terence");
968 String expecting = "<strong>Terence</strong>";
969 assertEquals(expecting,duh.toString());
970 }
971
972 public void testMultiLevelInheritance() throws Exception {
973 // must loop up two levels to find bold()
974 StringTemplateGroup rootgroup = new StringTemplateGroup("root");
975 StringTemplateGroup level1 = new StringTemplateGroup("level1");
976 StringTemplateGroup level2 = new StringTemplateGroup("level2");
977 rootgroup.defineTemplate("bold", "<b>$it$</b>");
978 level1.setSuperGroup(rootgroup);
979 level2.setSuperGroup(level1);
980 StringTemplateErrorListener errors = new ErrorBuffer();
981 rootgroup.setErrorListener(errors);
982 level1.setErrorListener(errors);
983 level2.setErrorListener(errors);
984 StringTemplate duh = new StringTemplate(level2, "$name:bold()$");
985 duh.setAttribute("name", "Terence");
986 String expecting = "<b>Terence</b>";
987 assertEquals(expecting,duh.toString());
988 }
989
990 public void testComplicatedInheritance() throws Exception {
991 // in super: decls invokes labels
992 // in sub: overridden decls which calls super.decls
993 // overridden labels
994 // Bug: didn't see the overridden labels. In other words,
995 // the overridden decls called super which called labels, but
996 // didn't get the subgroup overridden labels--it calls the
997 // one in the superclass. Ouput was "DL" not "DSL"; didn't
998 // invoke sub's labels().
999 String basetemplates =
1000 "group base;" +newline+
1001 "decls() ::= \"D<labels()>\""+newline+
1002 "labels() ::= \"L\"" +newline
1003 ;
1004 StringTemplateGroup base =
1005 new StringTemplateGroup(new StringReader(basetemplates));
1006 String subtemplates =
1007 "group sub;" +newline+
1008 "decls() ::= \"<super.decls()>\""+newline+
1009 "labels() ::= \"SL\"" +newline
1010 ;
1011 StringTemplateGroup sub =
1012 new StringTemplateGroup(new StringReader(subtemplates));
1013 sub.setSuperGroup(base);
1014 StringTemplate st = sub.getInstanceOf("decls");
1015 String expecting = "DSL";
1016 String result = st.toString();
1017 assertEquals(expecting, result);
1018 }
1019
1020 public void test3LevelSuperRef() throws Exception {
1021 String templates1 =
1022 "group super;" +newline+
1023 "r() ::= \"foo\"" +newline;
1024 StringTemplateGroup group =
1025 new StringTemplateGroup(new StringReader(templates1));
1026
1027 String templates2 =
1028 "group sub;" +newline+
1029 "r() ::= \"<super.r()>2\"" +newline;
1030 StringTemplateGroup subGroup =
1031 new StringTemplateGroup(new StringReader(templates2),
1032 AngleBracketTemplateLexer.class,
1033 null,
1034 group);
1035
1036 String templates3 =
1037 "group subsub;" +newline+
1038 "r() ::= \"<super.r()>3\"" +newline;
1039 StringTemplateGroup subSubGroup =
1040 new StringTemplateGroup(new StringReader(templates3),
1041 AngleBracketTemplateLexer.class,
1042 null,
1043 subGroup);
1044
1045 StringTemplate st = subSubGroup.getInstanceOf("r");
1046 String result = st.toString();
1047 String expecting = "foo23";
1048 assertEquals(expecting, result);
1049 }
1050
1051 public void testExprInParens() throws Exception {
1052 // specify a template to apply to an attribute
1053 // Use a template group so we can specify the start/stop chars
1054 StringTemplateGroup group =
1055 new StringTemplateGroup("dummy", ".");
1056 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$it$</b>");
1057 StringTemplate duh = new StringTemplate(group, "$(\"blort: \"+(list)):bold()$");
1058 duh.setAttribute("list", "a");
1059 duh.setAttribute("list", "b");
1060 duh.setAttribute("list", "c");
1061 // System.out.println(duh);
1062 String expecting = "<b>blort: abc</b>";
1063 assertEquals(expecting, duh.toString());
1064 }
1065
1066 public void testMultipleAdditions() throws Exception {
1067 // specify a template to apply to an attribute
1068 // Use a template group so we can specify the start/stop chars
1069 StringTemplateGroup group =
1070 new StringTemplateGroup("dummy", ".");
1071 group.defineTemplate("link", "<a href=\"$url$\"><b>$title$</b></a>");
1072 StringTemplate duh =
1073 new StringTemplate(group,
1074 "$link(url=\"/member/view?ID=\"+ID+\"&x=y\"+foo, title=\"the title\")$");
1075 duh.setAttribute("ID", "3321");
1076 duh.setAttribute("foo", "fubar");
1077 String expecting = "<a href=\"/member/view?ID=3321&x=yfubar\"><b>the title</b></a>";
1078 assertEquals(expecting, duh.toString());
1079 }
1080
1081 public void testCollectionAttributes() throws Exception {
1082 StringTemplateGroup group =
1083 new StringTemplateGroup("test");
1084 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$it$</b>");
1085 StringTemplate t =
1086 new StringTemplate(group, "$data$, $data:bold()$, "+
1087 "$list:bold():bold()$, $array$, $a2$, $a3$, $a4$");
1088 Vector v = new Vector();
1089 v.addElement("1");
1090 v.addElement("2");
1091 v.addElement("3");
1092 List list = new ArrayList();
1093 list.add("a");
1094 list.add("b");
1095 list.add("c");
1096 t.setAttribute("data", v);
1097 t.setAttribute("list", list);
1098 t.setAttribute("array", new String[] {"x","y"});
1099 t.setAttribute("a2", new int[] {10,20});
1100 t.setAttribute("a3", new float[] {1.2f,1.3f});
1101 t.setAttribute("a4", new double[] {8.7,9.2});
1102 //System.out.println(t);
1103 String expecting="123, <b>1</b><b>2</b><b>3</b>, "+
1104 "<b><b>a</b></b><b><b>b</b></b><b><b>c</b></b>, xy, 1020, 1.21.3, 8.79.2";
1105 assertEquals(expecting, t.toString());
1106 }
1107
1108 public void testParenthesizedExpression() throws Exception {
1109 StringTemplateGroup group =
1110 new StringTemplateGroup("test");
1111 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$it$</b>");
1112 StringTemplate t = new StringTemplate(group, "$(f+l):bold()$");
1113 t.setAttribute("f", "Joe");
1114 t.setAttribute("l", "Schmoe");
1115 //System.out.println(t);
1116 String expecting="<b>JoeSchmoe</b>";
1117 assertEquals(expecting, t.toString());
1118 }
1119
1120 public void testApplyTemplateNameExpression() throws Exception {
1121 StringTemplateGroup group =
1122 new StringTemplateGroup("test");
1123 /* StringTemplate bold =*/ group.defineTemplate("foobar", "foo$attr$bar");
1124 StringTemplate t = new StringTemplate(group, "$data:(name+\"bar\")()$");
1125 t.setAttribute("data", "Ter");
1126 t.setAttribute("data", "Tom");
1127 t.setAttribute("name", "foo");
1128 //System.out.println(t);
1129 String expecting="fooTerbarfooTombar";
1130 assertEquals(expecting, t.toString());
1131 }
1132
1133 public void testApplyTemplateNameTemplateEval() throws Exception {
1134 StringTemplateGroup group =
1135 new StringTemplateGroup("test");
1136 /*StringTemplate foobar =*/ group.defineTemplate("foobar", "foo$it$bar");
1137 /*StringTemplate a =*/ group.defineTemplate("a", "$it$bar");
1138 StringTemplate t = new StringTemplate(group, "$data:(\"foo\":a())()$");
1139 t.setAttribute("data", "Ter");
1140 t.setAttribute("data", "Tom");
1141 //System.out.println(t);
1142 String expecting="fooTerbarfooTombar";
1143 assertEquals(expecting, t.toString());
1144 }
1145
1146 public void testTemplateNameExpression() throws Exception {
1147 StringTemplateGroup group =
1148 new StringTemplateGroup("test");
1149 /*StringTemplate foo =*/ group.defineTemplate("foo", "hi there!");
1150 StringTemplate t = new StringTemplate(group, "$(name)()$");
1151 t.setAttribute("name", "foo");
1152 //System.out.println(t);
1153 String expecting="hi there!";
1154 assertEquals(expecting, t.toString());
1155 }
1156
1157 public void testMissingEndDelimiter() throws Exception {
1158 StringTemplateGroup group =
1159 new StringTemplateGroup("test");
1160 StringTemplateErrorListener errors = new ErrorBuffer();
1161 group.setErrorListener(errors);
1162 /*StringTemplate t =*/ new StringTemplate(group, "stuff $a then more junk etc...");
1163 String expectingError="problem parsing template 'anonymous': line 1:31: expecting '$', found '<EOF>'";
1164 //System.out.println("error: '"+errors+"'");
1165 //System.out.println("expecting: '"+expectingError+"'");
1166 assertTrue(errors.toString().startsWith(expectingError));
1167 }
1168
1169 public void testSetButNotRefd() throws Exception {
1170 StringTemplate.setLintMode(true);
1171 StringTemplateGroup group =
1172 new StringTemplateGroup("test");
1173 StringTemplate t = new StringTemplate(group, "$a$ then $b$ and $c$ refs.");
1174 t.setAttribute("a", "Terence");
1175 t.setAttribute("b", "Terence");
1176 t.setAttribute("cc", "Terence"); // oops...should be 'c'
1177 StringTemplateErrorListener errors = new ErrorBuffer();
1178 group.setErrorListener(errors);
1179 String expectingError="anonymous: set but not used: cc";
1180 /*String result =*/ t.toString(); // result is irrelevant
1181 //System.out.println("result error: '"+errors+"'");
1182 //System.out.println("expecting: '"+expectingError+"'");
1183 StringTemplate.setLintMode(false);
1184 assertEquals(expectingError,errors.toString());
1185 }
1186
1187 public void testNullTemplateApplication() throws Exception {
1188 StringTemplateGroup group =
1189 new StringTemplateGroup("test");
1190 StringTemplateErrorListener errors = new ErrorBuffer();
1191 group.setErrorListener(errors);
1192 StringTemplate t = new StringTemplate(group, "$names:bold(x=it)$");
1193 t.setAttribute("names", "Terence");
1194
1195 String error = null;
1196 try {
1197 t.toString();
1198 }
1199 catch (IllegalArgumentException iae) {
1200 error = iae.getMessage();
1201 }
1202 String expecting = "Can't find template bold.st; context is [anonymous]; group hierarchy is [test]" ;
1203 assertEquals(expecting,error);
1204 }
1205
1206 public void testNullTemplateToMultiValuedApplication() throws Exception {
1207 StringTemplateGroup group =
1208 new StringTemplateGroup("test");
1209 StringTemplateErrorListener errors = new ErrorBuffer();
1210 group.setErrorListener(errors);
1211 StringTemplate t = new StringTemplate(group, "$names:bold(x=it)$");
1212 t.setAttribute("names", "Terence");
1213 t.setAttribute("names", "Tom");
1214 //System.out.println(t);
1215 String error = null;
1216 try {
1217 t.toString();
1218 }
1219 catch (IllegalArgumentException iae) {
1220 error = iae.getMessage();
1221 }
1222 String expecting = "Can't find template bold.st; context is [anonymous]; group hierarchy is [test]"; // bold not found...empty string
1223 assertEquals(expecting,error);
1224 }
1225
1226 public void testChangingAttrValueTemplateApplicationToVector() throws Exception {
1227 StringTemplateGroup group =
1228 new StringTemplateGroup("test");
1229 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$x$</b>");
1230 StringTemplate t = new StringTemplate(group, "$names:bold(x=it)$");
1231 t.setAttribute("names", "Terence");
1232 t.setAttribute("names", "Tom");
1233 //System.out.println("'"+t.toString()+"'");
1234 String expecting="<b>Terence</b><b>Tom</b>";
1235 assertEquals(expecting, t.toString());
1236 }
1237
1238 public void testChangingAttrValueRepeatedTemplateApplicationToVector() throws Exception {
1239 StringTemplateGroup group =
1240 new StringTemplateGroup("dummy", ".");
1241 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$item$</b>");
1242 /*StringTemplate italics =*/ group.defineTemplate("italics", "<i>$it$</i>");
1243 StringTemplate members =
1244 new StringTemplate(group, "$members:bold(item=it):italics(it=it)$");
1245 members.setAttribute("members", "Jim");
1246 members.setAttribute("members", "Mike");
1247 members.setAttribute("members", "Ashar");
1248 //System.out.println("members="+members);
1249 String expecting = "<i><b>Jim</b></i><i><b>Mike</b></i><i><b>Ashar</b></i>";
1250 assertEquals(expecting,members.toString());
1251 }
1252
1253 public void testAlternatingTemplateApplication() throws Exception {
1254 StringTemplateGroup group =
1255 new StringTemplateGroup("dummy", ".");
1256 /*StringTemplate listItem =*/ group.defineTemplate("listItem", "<li>$it$</li>");
1257 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$it$</b>");
1258 /*StringTemplate italics =*/ group.defineTemplate("italics", "<i>$it$</i>");
1259 StringTemplate item =
1260 new StringTemplate(group, "$item:bold(),italics():listItem()$");
1261 item.setAttribute("item", "Jim");
1262 item.setAttribute("item", "Mike");
1263 item.setAttribute("item", "Ashar");
1264 //System.out.println("ITEM="+item);
1265 String expecting = "<li><b>Jim</b></li><li><i>Mike</i></li><li><b>Ashar</b></li>";
1266 assertEquals(item.toString(), expecting);
1267 }
1268
1269 public void testExpressionAsRHSOfAssignment() throws Exception {
1270 StringTemplateGroup group =
1271 new StringTemplateGroup("test");
1272 /*StringTemplate hostname =*/ group.defineTemplate("hostname", "$machine$.jguru.com");
1273 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$x$</b>");
1274 StringTemplate t = new StringTemplate(group, "$bold(x=hostname(machine=\"www\"))$");
1275 String expecting="<b>www.jguru.com</b>";
1276 assertEquals(expecting, t.toString());
1277 }
1278
1279 public void testTemplateApplicationAsRHSOfAssignment() throws Exception {
1280 StringTemplateGroup group =
1281 new StringTemplateGroup("test");
1282 /*StringTemplate hostname =*/ group.defineTemplate("hostname", "$machine$.jguru.com");
1283 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$x$</b>");
1284 /*StringTemplate italics =*/ group.defineTemplate("italics", "<i>$it$</i>");
1285 StringTemplate t = new StringTemplate(group, "$bold(x=hostname(machine=\"www\"):italics())$");
1286 String expecting="<b><i>www.jguru.com</i></b>";
1287 assertEquals(expecting, t.toString());
1288 }
1289
1290 public void testParameterAndAttributeScoping() throws Exception {
1291 StringTemplateGroup group =
1292 new StringTemplateGroup("test");
1293 /*StringTemplate italics =*/ group.defineTemplate("italics", "<i>$x$</i>");
1294 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$x$</b>");
1295 StringTemplate t = new StringTemplate(group, "$bold(x=italics(x=name))$");
1296 t.setAttribute("name", "Terence");
1297 //System.out.println(t);
1298 String expecting="<b><i>Terence</i></b>";
1299 assertEquals(expecting, t.toString());
1300 }
1301
1302 public void testComplicatedSeparatorExpr() throws Exception {
1303 StringTemplateGroup group =
1304 new StringTemplateGroup("test");
1305 /*StringTemplate bold =*/ group.defineTemplate("bulletSeparator", "</li>$foo$<li>");
1306 // make separator a complicated expression with args passed to included template
1307 StringTemplate t =
1308 new StringTemplate(group,
1309 "<ul>$name; separator=bulletSeparator(foo=\" \")+\"&nbsp;\"$</ul>");
1310 t.setAttribute("name", "Ter");
1311 t.setAttribute("name", "Tom");
1312 t.setAttribute("name", "Mel");
1313 //System.out.println(t);
1314 String expecting = "<ul>Ter</li> <li>&nbsp;Tom</li> <li>&nbsp;Mel</ul>";
1315 assertEquals(expecting, t.toString());
1316 }
1317
1318 public void testAttributeRefButtedUpAgainstEndifAndWhitespace() throws Exception {
1319 StringTemplateGroup group =
1320 new StringTemplateGroup("test");
1321 StringTemplate a = new StringTemplate(group,
1322 "$if (!firstName)$$email$$endif$");
1323 a.setAttribute("email", "parrt@jguru.com");
1324 String expecting = "parrt@jguru.com";
1325 assertEquals(a.toString(), expecting);
1326 }
1327
1328 public void testStringCatenationOnSingleValuedAttributeViaTemplateLiteral() throws Exception {
1329 StringTemplateGroup group =
1330 new StringTemplateGroup("test");
1331 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$it$</b>");
1332 //StringTemplate a = new StringTemplate(group, "$\" Parr\":bold()$");
1333 StringTemplate b = new StringTemplate(group, "$bold(it={$name$ Parr})$");
1334 //a.setAttribute("name", "Terence");
1335 b.setAttribute("name", "Terence");
1336 String expecting = "<b>Terence Parr</b>";
1337 //assertEquals(a.toString(), expecting);
1338 assertEquals(b.toString(), expecting);
1339 }
1340
1341 public void testStringCatenationOpOnArg() throws Exception {
1342 StringTemplateGroup group =
1343 new StringTemplateGroup("test");
1344 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$it$</b>");
1345 StringTemplate b = new StringTemplate(group, "$bold(it=name+\" Parr\")$");
1346 //a.setAttribute("name", "Terence");
1347 b.setAttribute("name", "Terence");
1348 String expecting = "<b>Terence Parr</b>";
1349 //assertEquals(expecting, a.toString());
1350 assertEquals(expecting, b.toString());
1351 }
1352
1353 public void testStringCatenationOpOnArgWithEqualsInString() throws Exception {
1354 StringTemplateGroup group =
1355 new StringTemplateGroup("test");
1356 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$it$</b>");
1357 StringTemplate b = new StringTemplate(group, "$bold(it=name+\" Parr=\")$");
1358 //a.setAttribute("name", "Terence");
1359 b.setAttribute("name", "Terence");
1360 String expecting = "<b>Terence Parr=</b>";
1361 //assertEquals(expecting, a.toString());
1362 assertEquals(expecting, b.toString());
1363 }
1364
1365 public void testApplyingTemplateFromDiskWithPrecompiledIF()
1366 throws Exception
1367 {
1368 // Create a temporary working directory
1369 File tmpDir = new File(System.getProperty("java.io.tmpdir"));
1370 File tmpWorkDir;
1371 int counter = (new Random()).nextInt() & 65535;;
1372 do {
1373 counter++;
1374 StringBuffer name = new StringBuffer("st-junit-");
1375 name.append(counter);
1376 tmpWorkDir = new File(tmpDir, name.toString());
1377 } while (tmpWorkDir.exists());
1378 tmpWorkDir.mkdirs();
1379
1380 // write the template files first to /tmp
1381 File pageFile = new File(tmpWorkDir,"page.st");
1382 FileWriter fw = new FileWriter(pageFile);
1383 fw.write("<html><head>"+newline);
1384 //fw.write(" <title>PeerScope: $title$</title>"+newline);
1385 fw.write("</head>"+newline);
1386 fw.write("<body>"+newline);
1387 fw.write("$if(member)$User: $member:terse()$$endif$"+newline);
1388 fw.write("</body>"+newline);
1389 fw.write("</head>"+newline);
1390 fw.close();
1391
1392 File terseFile = new File(tmpWorkDir,"terse.st");
1393 fw = new FileWriter(terseFile);
1394 fw.write("$it.firstName$ $it.lastName$ (<tt>$it.email$</tt>)"+newline);
1395 fw.close();
1396
1397 // specify a template to apply to an attribute
1398 // Use a template group so we can specify the start/stop chars
1399 StringTemplateGroup group =
1400 new StringTemplateGroup("dummy", tmpWorkDir.toString());
1401
1402 StringTemplate a = group.getInstanceOf("page");
1403 a.setAttribute("member", new Connector());
1404 String expecting = "<html><head>"+newline+
1405 "</head>"+newline+
1406 "<body>"+newline+
1407 "User: Terence Parr (<tt>parrt@jguru.com</tt>)"+newline+
1408 "</body>"+newline+
1409 "</head>";
1410 //System.out.println("'"+a+"'");
1411 assertEquals(expecting, a.toString());
1412
1413 // Cleanup the temp folder.
1414 pageFile.delete();
1415 terseFile.delete();
1416 tmpWorkDir.delete();
1417 }
1418
1419 public void testMultiValuedAttributeWithAnonymousTemplateUsingIndexVariableI()
1420 throws Exception
1421 {
1422 StringTemplateGroup tgroup =
1423 new StringTemplateGroup("dummy", ".");
1424 StringTemplate t =
1425 new StringTemplate(tgroup,
1426 " List:"+newline+" "+newline+"foo"+newline+newline+
1427 "$names:{<br>$i$. $it$"+newline+
1428 "}$");
1429 t.setAttribute("names", "Terence");
1430 t.setAttribute("names", "Jim");
1431 t.setAttribute("names", "Sriram");
1432 //System.out.println(t);
1433 String expecting =
1434 " List:"+newline+
1435 " "+newline+
1436 "foo"+newline+newline+
1437 "<br>1. Terence"+newline+
1438 "<br>2. Jim"+newline+
1439 "<br>3. Sriram"+newline;
1440 assertEquals(expecting, t.toString());
1441 }
1442
1443 public void testFindTemplateInCLASSPATH() throws Exception {
1444 // Look for templates in CLASSPATH as resources
1445 StringTemplateGroup mgroup =
1446 new StringTemplateGroup("method stuff",
1447 AngleBracketTemplateLexer.class);
1448 StringTemplate m = mgroup.getInstanceOf("org/antlr/stringtemplate/test/method");
1449 // "method.st" references body() so "body.st" will be loaded too
1450 m.setAttribute("visibility", "public");
1451 m.setAttribute("name", "foobar");
1452 m.setAttribute("returnType", "void");
1453 m.setAttribute("statements", "i=1;"); // body inherits these from method
1454 m.setAttribute("statements", "x=i;");
1455 String expecting =
1456 "public void foobar() {"+newline+
1457 "\t// start of a body"+newline+
1458 "\ti=1;"+newline+
1459 "\tx=i;"+newline+
1460 "\t// end of a body"+newline+
1461 "}";
1462 //System.out.println(m);
1463 assertEquals(expecting, m.toString());
1464 }
1465
1466 public void testApplyTemplateToSingleValuedAttribute() throws Exception {
1467 StringTemplateGroup group =
1468 new StringTemplateGroup("test");
1469 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$x$</b>");
1470 StringTemplate name = new StringTemplate(group, "$name:bold(x=name)$");
1471 name.setAttribute("name", "Terence");
1472 assertEquals("<b>Terence</b>",name.toString());
1473 }
1474
1475 public void testStringLiteralAsAttribute() throws Exception {
1476 StringTemplateGroup group =
1477 new StringTemplateGroup("test");
1478 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$it$</b>");
1479 StringTemplate name = new StringTemplate(group, "$\"Terence\":bold()$");
1480 assertEquals("<b>Terence</b>",name.toString());
1481 }
1482
1483 public void testApplyTemplateToSingleValuedAttributeWithDefaultAttribute() throws Exception {
1484 StringTemplateGroup group =
1485 new StringTemplateGroup("test");
1486 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$it$</b>");
1487 StringTemplate name = new StringTemplate(group, "$name:bold()$");
1488 name.setAttribute("name", "Terence");
1489 assertEquals("<b>Terence</b>",name.toString());
1490 }
1491
1492 public void testApplyAnonymousTemplateToSingleValuedAttribute() throws Exception {
1493 // specify a template to apply to an attribute
1494 // Use a template group so we can specify the start/stop chars
1495 StringTemplateGroup group =
1496 new StringTemplateGroup("dummy", ".");
1497 StringTemplate item =
1498 new StringTemplate(group, "$item:{<li>$it$</li>}$");
1499 item.setAttribute("item", "Terence");
1500 assertEquals("<li>Terence</li>",item.toString());
1501 }
1502
1503 public void testApplyAnonymousTemplateToMultiValuedAttribute() throws Exception {
1504 // specify a template to apply to an attribute
1505 // Use a template group so we can specify the start/stop chars
1506 StringTemplateGroup group =
1507 new StringTemplateGroup("dummy", ".");
1508 StringTemplate list =
1509 new StringTemplate(group, "<ul>$items$</ul>");
1510 // demonstrate setting arg to anonymous subtemplate
1511 StringTemplate item =
1512 new StringTemplate(group, "$item:{<li>$it$</li>}; separator=\",\"$");
1513 item.setAttribute("item", "Terence");
1514 item.setAttribute("item", "Jim");
1515 item.setAttribute("item", "John");
1516 list.setAttribute("items", item); // nested template
1517 String expecting = "<ul><li>Terence</li>,<li>Jim</li>,<li>John</li></ul>";
1518 assertEquals(expecting,list.toString());
1519 }
1520
1521 public void testApplyAnonymousTemplateToAggregateAttribute() throws Exception {
1522 StringTemplate st =
1523 new StringTemplate("$items:{$it.lastName$, $it.firstName$\n}$");
1524 // also testing wacky spaces in aggregate spec
1525 st.setAttribute("items.{ firstName ,lastName}", "Ter", "Parr");
1526 st.setAttribute("items.{firstName, lastName }", "Tom", "Burns");
1527 String expecting =
1528 "Parr, Ter"+newline +
1529 "Burns, Tom"+newline;
1530 assertEquals(expecting, st.toString());
1531 }
1532
1533 public void testRepeatedApplicationOfTemplateToSingleValuedAttribute() throws Exception {
1534 StringTemplateGroup group =
1535 new StringTemplateGroup("dummy", ".");
1536 /*StringTemplate search =*/ group.defineTemplate("bold", "<b>$it$</b>");
1537 StringTemplate item =
1538 new StringTemplate(group, "$item:bold():bold()$");
1539 item.setAttribute("item", "Jim");
1540 assertEquals("<b><b>Jim</b></b>", item.toString());
1541 }
1542
1543 public void testRepeatedApplicationOfTemplateToMultiValuedAttributeWithSeparator() throws Exception {
1544 StringTemplateGroup group =
1545 new StringTemplateGroup("dummy", ".");
1546 /*StringTemplate search =*/ group.defineTemplate("bold", "<b>$it$</b>");
1547 StringTemplate item =
1548 new StringTemplate(group, "$item:bold():bold(); separator=\",\"$");
1549 item.setAttribute("item", "Jim");
1550 item.setAttribute("item", "Mike");
1551 item.setAttribute("item", "Ashar");
1552 // first application of template must yield another vector!
1553 //System.out.println("ITEM="+item);
1554 String expecting = "<b><b>Jim</b></b>,<b><b>Mike</b></b>,<b><b>Ashar</b></b>";
1555 assertEquals(item.toString(), expecting);
1556 }
1557
1558 // ### NEED A TEST OF obj ASSIGNED TO ARG?
1559
1560 public void testMultiValuedAttributeWithSeparator() throws Exception {
1561 StringTemplate query;
1562
1563 // if column can be multi-valued, specify a separator
1564 StringTemplateGroup group =
1565 new StringTemplateGroup("dummy", ".", AngleBracketTemplateLexer.class);
1566 query = new StringTemplate(group, "SELECT <distinct> <column; separator=\", \"> FROM <table>;");
1567 query.setAttribute("column", "name");
1568 query.setAttribute("column", "email");
1569 query.setAttribute("table", "User");
1570 // uncomment next line to make "DISTINCT" appear in output
1571 // query.setAttribute("distince", "DISTINCT");
1572 // System.out.println(query);
1573 assertEquals("SELECT name, email FROM User;",query.toString());
1574 }
1575
1576 public void testSingleValuedAttributes() throws Exception {
1577 // all attributes are single-valued:
1578 StringTemplate query =
1579 new StringTemplate("SELECT $column$ FROM $table$;");
1580 query.setAttribute("column", "name");
1581 query.setAttribute("table", "User");
1582 // System.out.println(query);
1583 assertEquals("SELECT name FROM User;",query.toString());
1584 }
1585
1586 public void testIFTemplate() throws Exception {
1587 StringTemplateGroup group =
1588 new StringTemplateGroup("dummy", ".", AngleBracketTemplateLexer.class);
1589 StringTemplate t =
1590 new StringTemplate(group,
1591 "SELECT <column> FROM PERSON "+
1592 "<if(cond)>WHERE ID=<id><endif>;");
1593 t.setAttribute("column", "name");
1594 t.setAttribute("cond", "true");
1595 t.setAttribute("id", "231");
1596 assertEquals("SELECT name FROM PERSON WHERE ID=231;",t.toString());
1597 }
1598
1599 public void testIFCondWithParensTemplate() throws Exception {
1600 StringTemplateGroup group =
1601 new StringTemplateGroup("dummy", ".", AngleBracketTemplateLexer.class);
1602 StringTemplate t =
1603 new StringTemplate(group,
1604 "<if(map.(type))><type> <prop>=<map.(type)>;<endif>");
1605 HashMap map = new HashMap();
1606 map.put("int","0");
1607 t.setAttribute("map", map);
1608 t.setAttribute("prop", "x");
1609 t.setAttribute("type", "int");
1610 assertEquals("int x=0;",t.toString());
1611 }
1612
1613 public void testIFCondWithParensDollarDelimsTemplate() throws Exception {
1614 StringTemplateGroup group =
1615 new StringTemplateGroup("dummy", ".");
1616 StringTemplate t =
1617 new StringTemplate(group,
1618 "$if(map.(type))$$type$ $prop$=$map.(type)$;$endif$");
1619 HashMap map = new HashMap();
1620 map.put("int","0");
1621 t.setAttribute("map", map);
1622 t.setAttribute("prop", "x");
1623 t.setAttribute("type", "int");
1624 assertEquals("int x=0;",t.toString());
1625 }
1626
1627 /** As of 2.0, you can test a boolean value */
1628 public void testIFBoolean() throws Exception {
1629 StringTemplateGroup group =
1630 new StringTemplateGroup("dummy", ".");
1631 StringTemplate t =
1632 new StringTemplate(group,
1633 "$if(b)$x$endif$ $if(!b)$y$endif$");
1634 t.setAttribute("b", new Boolean(true));
1635 assertEquals(t.toString(), "x ");
1636
1637 t = t.getInstanceOf();
1638 t.setAttribute("b", new Boolean(false));
1639 assertEquals(" y", t.toString());
1640 }
1641
1642 public void testNestedIFTemplate() throws Exception {
1643 StringTemplateGroup group =
1644 new StringTemplateGroup("dummy", ".", AngleBracketTemplateLexer.class);
1645 StringTemplate t =
1646 new StringTemplate(group,
1647 "ack<if(a)>"+newline+
1648 "foo"+newline+
1649 "<if(!b)>stuff<endif>"+newline+
1650 "<if(b)>no<endif>"+newline+
1651 "junk"+newline+
1652 "<endif>"
1653 );
1654 t.setAttribute("a", "blort");
1655 // leave b as null
1656 //System.out.println("t="+t);
1657 String expecting =
1658 "ackfoo"+newline+
1659 "stuff"+newline+
1660 "junk";
1661 assertEquals(expecting, t.toString());
1662 }
1663
1664 public void testIFConditionWithTemplateApplication() throws Exception {
1665 StringTemplateGroup group =
1666 new StringTemplateGroup("dummy", ".");
1667 StringTemplate t =
1668 new StringTemplate(group,
1669 "$if(names:{$it$})$Fail!$endif$ $if(!names:{$it$})$Works!$endif$");
1670 t.setAttribute("b", new Boolean(true));
1671 assertEquals(t.toString(), " Works!");
1672 }
1673
1674 public class Connector {
1675 public int getID() { return 1; }
1676 public String getFirstName() { return "Terence"; }
1677 public String getLastName() { return "Parr"; }
1678 public String getEmail() { return "parrt@jguru.com"; }
1679 public String getBio() { return "Superhero by night..."; }
1680 /** As of 2.0, booleans work as you expect. In 1.x,
1681 * a missing value simulated a boolean.
1682 */
1683 public boolean getCanEdit() { return false; }
1684 }
1685
1686 public class Connector2 {
1687 public int getID() { return 2; }
1688 public String getFirstName() { return "Tom"; }
1689 public String getLastName() { return "Burns"; }
1690 public String getEmail() { return "tombu@jguru.com"; }
1691 public String getBio() { return "Superhero by day..."; }
1692 public Boolean getCanEdit() { return new Boolean(true); }
1693 }
1694
1695 public void testObjectPropertyReference() throws Exception {
1696 StringTemplateGroup group =
1697 new StringTemplateGroup("dummy", ".");
1698 StringTemplate t =
1699 new StringTemplate(
1700 group,
1701 "<b>Name: $p.firstName$ $p.lastName$</b><br>"+newline+
1702 "<b>Email: $p.email$</b><br>"+newline+
1703 "$p.bio$"
1704 );
1705 t.setAttribute("p", new Connector());
1706 //System.out.println("t is "+t.toString());
1707 String expecting =
1708 "<b>Name: Terence Parr</b><br>"+newline+
1709 "<b>Email: parrt@jguru.com</b><br>"+newline+
1710 "Superhero by night...";
1711 assertEquals(expecting, t.toString());
1712 }
1713
1714 public void testApplyRepeatedAnonymousTemplateWithForeignTemplateRefToMultiValuedAttribute() throws Exception {
1715 // specify a template to apply to an attribute
1716 // Use a template group so we can specify the start/stop chars
1717 StringTemplateGroup group =
1718 new StringTemplateGroup("dummy", ".");
1719 group.defineTemplate("link", "<a href=\"$url$\"><b>$title$</b></a>");
1720 StringTemplate duh =
1721 new StringTemplate(group,
1722 "start|$p:{$link(url=\"/member/view?ID=\"+it.ID, title=it.firstName)$ $if(it.canEdit)$canEdit$endif$}:"+
1723 "{$it$<br>\n}$|end");
1724 duh.setAttribute("p", new Connector());
1725 duh.setAttribute("p", new Connector2());
1726 //System.out.println(duh);
1727 String expecting = "start|<a href=\"/member/view?ID=1\"><b>Terence</b></a> <br>"+newline+
1728 "<a href=\"/member/view?ID=2\"><b>Tom</b></a> canEdit<br>"+newline+
1729 "|end";
1730 assertEquals(expecting,duh.toString());
1731 }
1732
1733 public static class Tree {
1734 protected List children = new LinkedList();
1735 protected String text;
1736 public Tree(String t) {
1737 text = t;
1738 }
1739 public String getText() {
1740 return text;
1741 }
1742 public void addChild(Tree c) {
1743 children.add(c);
1744 }
1745 public Tree getFirstChild() {
1746 if ( children.size()==0 ) {
1747 return null;
1748 }
1749 return (Tree)children.get(0);
1750 }
1751 public List getChildren() {
1752 return children;
1753 }
1754 }
1755
1756 public void testRecursion() throws Exception {
1757 StringTemplateGroup group =
1758 new StringTemplateGroup("dummy", ".", AngleBracketTemplateLexer.class);
1759 group.defineTemplate("tree",
1760 "<if(it.firstChild)>"+
1761 "( <it.text> <it.children:tree(); separator=\" \"> )" +
1762 "<else>" +
1763 "<it.text>" +
1764 "<endif>");
1765 StringTemplate tree = group.getInstanceOf("tree");
1766 // build ( a b (c d) e )
1767 Tree root = new Tree("a");
1768 root.addChild(new Tree("b"));
1769 Tree subtree = new Tree("c");
1770 subtree.addChild(new Tree("d"));
1771 root.addChild(subtree);
1772 root.addChild(new Tree("e"));
1773 tree.setAttribute("it", root);
1774 String expecting = "( a b ( c d ) e )";
1775 assertEquals(expecting, tree.toString());
1776 }
1777
1778 public void testNestedAnonymousTemplates() throws Exception {
1779 StringTemplateGroup group =
1780 new StringTemplateGroup("dummy", ".");
1781 StringTemplate t =
1782 new StringTemplate(
1783 group,
1784 "$A:{" + newline +
1785 "<i>$it:{" + newline +
1786 "<b>$it$</b>" + newline +
1787 "}$</i>" + newline +
1788 "}$"
1789 );
1790 t.setAttribute("A", "parrt");
1791 String expecting = newline +
1792 "<i>" + newline +
1793 "<b>parrt</b>" + newline +
1794 "</i>" + newline;
1795 assertEquals(expecting, t.toString());
1796 }
1797
1798 public void testAnonymousTemplateAccessToEnclosingAttributes() throws Exception {
1799 StringTemplateGroup group =
1800 new StringTemplateGroup("dummy", ".");
1801 StringTemplate t =
1802 new StringTemplate(
1803 group,
1804 "$A:{" + newline +
1805 "<i>$it:{" + newline +
1806 "<b>$it$, $B$</b>" + newline +
1807 "}$</i>" + newline +
1808 "}$"
1809 );
1810 t.setAttribute("A", "parrt");
1811 t.setAttribute("B", "tombu");
1812 String expecting = newline +
1813 "<i>" + newline +
1814 "<b>parrt, tombu</b>" + newline +
1815 "</i>" + newline;
1816 assertEquals(expecting, t.toString());
1817 }
1818
1819 public void testNestedAnonymousTemplatesAgain() throws Exception {
1820
1821 StringTemplateGroup group =
1822 new StringTemplateGroup("dummy", ".");
1823 StringTemplate t =
1824 new StringTemplate(
1825 group,
1826 "<table>"+newline +
1827 "$names:{<tr>$it:{<td>$it:{<b>$it$</b>}$</td>}$</tr>}$"+newline +
1828 "</table>"+newline
1829 );
1830 t.setAttribute("names", "parrt");
1831 t.setAttribute("names", "tombu");
1832 String expecting =
1833 "<table>" + newline +
1834 "<tr><td><b>parrt</b></td></tr><tr><td><b>tombu</b></td></tr>" + newline +
1835 "</table>" + newline;
1836 assertEquals(expecting, t.toString());
1837 }
1838
1839 public void testEscapes() throws Exception {
1840 StringTemplateGroup group =
1841 new StringTemplateGroup("dummy", ".");
1842 group.defineTemplate("foo", "$x$ && $it$");
1843 StringTemplate t =
1844 new StringTemplate(
1845 group,
1846 "$A:foo(x=\"dog\\\"\\\"\")$" // $A:foo("dog\"\"")$
1847 );
1848 StringTemplate u =
1849 new StringTemplate(
1850 group,
1851 "$A:foo(x=\"dog\\\"g\")$" // $A:foo(x="dog\"g")$
1852 );
1853 StringTemplate v =
1854 new StringTemplate(
1855 group,
1856 // $A:{$attr:foo(x="\{dog\}\"")$ is cool}$
1857 "$A:{$it:foo(x=\"\\{dog\\}\\\"\")$ is cool}$"
1858 );
1859 t.setAttribute("A", "ick");
1860 u.setAttribute("A", "ick");
1861 v.setAttribute("A", "ick");
1862 //System.out.println("t is '"+t.toString()+"'");
1863 //System.out.println("u is '"+u.toString()+"'");
1864 //System.out.println("v is '"+v.toString()+"'");
1865 String expecting = "dog\"\" && ick";
1866 assertEquals(expecting, t.toString());
1867 expecting = "dog\"g && ick";
1868 assertEquals(expecting,u.toString());
1869 expecting = "{dog}\" && ick is cool";
1870 assertEquals(expecting,v.toString());
1871 }
1872
1873 public void testEscapesOutsideExpressions() throws Exception {
1874 StringTemplate b = new StringTemplate("It\\'s ok...\\$; $a:{\\'hi\\', $it$}$");
1875 b.setAttribute("a", "Ter");
1876 String expecting ="It\\'s ok...$; \\'hi\\', Ter";
1877 String result = b.toString();
1878 assertEquals(expecting, result);
1879 }
1880
1881 public void testElseClause() throws Exception {
1882 StringTemplate e = new StringTemplate(
1883 "$if(title)$"+newline +
1884 "foo"+newline +
1885 "$else$"+newline +
1886 "bar"+newline +
1887 "$endif$"
1888 );
1889 e.setAttribute("title", "sample");
1890 String expecting = "foo";
1891 assertEquals(expecting, e.toString());
1892
1893 e = e.getInstanceOf();
1894 expecting = "bar";
1895 assertEquals(expecting, e.toString());
1896 }
1897
1898 public void testElseIfClause() throws Exception {
1899 StringTemplate e = new StringTemplate(
1900 "$if(x)$"+newline +
1901 "foo"+newline +
1902 "$elseif(y)$"+newline +
1903 "bar"+newline +
1904 "$endif$"
1905 );
1906 e.setAttribute("y", "yep");
1907 String expecting = "bar";
1908 assertEquals(expecting, e.toString());
1909 }
1910
1911 public void testElseIfClauseAngleBrackets() throws Exception {
1912 StringTemplate e = new StringTemplate(
1913 "<if(x)>"+newline +
1914 "foo"+newline +
1915 "<elseif(y)>"+newline +
1916 "bar"+newline +
1917 "<endif>",
1918 AngleBracketTemplateLexer.class
1919 );
1920 e.setAttribute("y", "yep");
1921 String expecting = "bar";
1922 assertEquals(expecting, e.toString());
1923 }
1924
1925 public void testElseIfClause2() throws Exception {
1926 StringTemplate e = new StringTemplate(
1927 "$if(x)$"+newline +
1928 "foo"+newline +
1929 "$elseif(y)$"+newline +
1930 "bar"+newline +
1931 "$elseif(z)$"+newline +
1932 "blort"+newline +
1933 "$endif$"
1934 );
1935 e.setAttribute("z", "yep");
1936 String expecting = "blort";
1937 assertEquals(expecting, e.toString());
1938 }
1939
1940 public void testElseIfClauseAndElse() throws Exception {
1941 StringTemplate e = new StringTemplate(
1942 "$if(x)$"+newline +
1943 "foo"+newline +
1944 "$elseif(y)$"+newline +
1945 "bar"+newline +
1946 "$elseif(z)$"+newline +
1947 "z"+newline +
1948 "$else$"+newline +
1949 "blort"+newline +
1950 "$endif$"
1951 );
1952 String expecting = "blort";
1953 assertEquals(expecting, e.toString());
1954 }
1955
1956 public void testNestedIF() throws Exception {
1957 StringTemplate e = new StringTemplate(
1958 "$if(title)$"+newline +
1959 "foo"+newline +
1960 "$else$"+newline +
1961 "$if(header)$"+newline +
1962 "bar"+newline +
1963 "$else$"+newline +
1964 "blort"+newline +
1965 "$endif$"+newline +
1966 "$endif$"
1967 );
1968 e.setAttribute("title", "sample");
1969 String expecting = "foo";
1970 assertEquals(expecting, e.toString());
1971
1972 e = e.getInstanceOf();
1973 e.setAttribute("header", "more");
1974 expecting = "bar";
1975 assertEquals(expecting, e.toString());
1976
1977 e = e.getInstanceOf();
1978 expecting = "blort";
1979 assertEquals(expecting, e.toString());
1980 }
1981
1982 public void testEmbeddedMultiLineIF() throws Exception {
1983 StringTemplateGroup group =
1984 new StringTemplateGroup("test");
1985 StringTemplate main = new StringTemplate(group, "$sub$");
1986 StringTemplate sub = new StringTemplate(group,
1987 "begin" + newline +
1988 "$if(foo)$" + newline +
1989 "$foo$" + newline +
1990 "$else$" +newline +
1991 "blort" + newline +
1992 "$endif$" + newline
1993 );
1994 sub.setAttribute("foo", "stuff");
1995 main.setAttribute("sub", sub);
1996 String expecting =
1997 "begin"+newline+
1998 "stuff";
1999 assertEquals(expecting, main.toString());
2000
2001 main = new StringTemplate(group, "$sub$");
2002 sub = sub.getInstanceOf();
2003 main.setAttribute("sub", sub);
2004 expecting =
2005 "begin"+newline+
2006 "blort";
2007 assertEquals(expecting, main.toString());
2008 }
2009
2010 public void testSimpleIndentOfAttributeList()
2011 throws Exception
2012 {
2013 String templates =
2014 "group test;" +newline+
2015 "list(names) ::= <<" +
2016 " $names; separator=\"\n\"$"+newline+
2017 ">>"+newline;
2018 StringTemplateErrorListener errors = new ErrorBuffer();
2019 StringTemplateGroup group =
2020 new StringTemplateGroup(new StringReader(templates),
2021 DefaultTemplateLexer.class,
2022 errors);
2023 StringTemplate t = group.getInstanceOf("list");
2024 t.setAttribute("names", "Terence");
2025 t.setAttribute("names", "Jim");
2026 t.setAttribute("names", "Sriram");
2027 String expecting =
2028 " Terence"+newline+
2029 " Jim"+newline+
2030 " Sriram";
2031 assertEquals(expecting, t.toString());
2032 }
2033
2034 public void testIndentOfMultilineAttributes()
2035 throws Exception
2036 {
2037 String templates =
2038 "group test;" +newline+
2039 "list(names) ::= <<" +
2040 " $names; separator=\"\n\"$"+newline+
2041 ">>"+newline;
2042 StringTemplateErrorListener errors = new ErrorBuffer();
2043 StringTemplateGroup group =
2044 new StringTemplateGroup(new StringReader(templates),
2045 DefaultTemplateLexer.class,
2046 errors);
2047 StringTemplate t = group.getInstanceOf("list");
2048 t.setAttribute("names", "Terence\nis\na\nmaniac");
2049 t.setAttribute("names", "Jim");
2050 t.setAttribute("names", "Sriram\nis\ncool");
2051 String expecting =
2052 " Terence"+newline+
2053 " is"+newline+
2054 " a"+newline+
2055 " maniac"+newline+
2056 " Jim"+newline+
2057 " Sriram"+newline+
2058 " is"+newline+
2059 " cool";
2060 assertEquals(expecting, t.toString());
2061 }
2062
2063 public void testIndentOfMultipleBlankLines()
2064 throws Exception
2065 {
2066 String templates =
2067 "group test;" +newline+
2068 "list(names) ::= <<" +
2069 " $names$"+newline+
2070 ">>"+newline;
2071 StringTemplateErrorListener errors = new ErrorBuffer();
2072 StringTemplateGroup group =
2073 new StringTemplateGroup(new StringReader(templates),
2074 DefaultTemplateLexer.class,
2075 errors);
2076 StringTemplate t = group.getInstanceOf("list");
2077 t.setAttribute("names", "Terence\n\nis a maniac");
2078 String expecting =
2079 " Terence"+newline+
2080 ""+newline+ // no indent on blank line
2081 " is a maniac";
2082 assertEquals(expecting, t.toString());
2083 }
2084
2085 public void testIndentBetweenLeftJustifiedLiterals()
2086 throws Exception
2087 {
2088 String templates =
2089 "group test;" +newline+
2090 "list(names) ::= <<" +
2091 "Before:"+newline +
2092 " $names; separator=\"\\n\"$"+newline+
2093 "after" +newline+
2094 ">>"+newline;
2095 StringTemplateErrorListener errors = new ErrorBuffer();
2096 StringTemplateGroup group =
2097 new StringTemplateGroup(new StringReader(templates),
2098 DefaultTemplateLexer.class,
2099 errors);
2100 StringTemplate t = group.getInstanceOf("list");
2101 t.setAttribute("names", "Terence");
2102 t.setAttribute("names", "Jim");
2103 t.setAttribute("names", "Sriram");
2104 String expecting =
2105 "Before:" +newline+
2106 " Terence"+newline+
2107 " Jim"+newline+
2108 " Sriram"+newline+
2109 "after";
2110 assertEquals(expecting, t.toString());
2111 }
2112
2113 public void testNestedIndent()
2114 throws Exception
2115 {
2116 String templates =
2117 "group test;" +newline+
2118 "method(name,stats) ::= <<" +
2119 "void $name$() {"+newline +
2120 "\t$stats; separator=\"\\n\"$"+newline+
2121 "}" +newline+
2122 ">>"+newline+
2123 "ifstat(expr,stats) ::= <<"+newline +
2124 "if ($expr$) {"+newline +
2125 " $stats; separator=\"\\n\"$"+newline +
2126 "}" +
2127 ">>"+newline +
2128 "assign(lhs,expr) ::= <<$lhs$=$expr$;>>"+newline
2129 ;
2130 StringTemplateErrorListener errors = new ErrorBuffer();
2131 StringTemplateGroup group =
2132 new StringTemplateGroup(new StringReader(templates),
2133 DefaultTemplateLexer.class,
2134 errors);
2135 StringTemplate t = group.getInstanceOf("method");
2136 t.setAttribute("name", "foo");
2137 StringTemplate s1 = group.getInstanceOf("assign");
2138 s1.setAttribute("lhs", "x");
2139 s1.setAttribute("expr", "0");
2140 StringTemplate s2 = group.getInstanceOf("ifstat");
2141 s2.setAttribute("expr", "x>0");
2142 StringTemplate s2a = group.getInstanceOf("assign");
2143 s2a.setAttribute("lhs", "y");
2144 s2a.setAttribute("expr", "x+y");
2145 StringTemplate s2b = group.getInstanceOf("assign");
2146 s2b.setAttribute("lhs", "z");
2147 s2b.setAttribute("expr", "4");
2148 s2.setAttribute("stats", s2a);
2149 s2.setAttribute("stats", s2b);
2150 t.setAttribute("stats", s1);
2151 t.setAttribute("stats", s2);
2152 String expecting =
2153 "void foo() {"+newline+
2154 "\tx=0;"+newline+
2155 "\tif (x>0) {"+newline+
2156 "\t y=x+y;"+newline+
2157 "\t z=4;"+newline+
2158 "\t}"+newline+
2159 "}";
2160 assertEquals(expecting, t.toString());
2161 }
2162
2163 public void testAlternativeWriter() throws Exception {
2164 final StringBuffer buf = new StringBuffer();
2165 StringTemplateWriter w = new StringTemplateWriter() {
2166 public void pushIndentation(String indent) {
2167 }
2168 public String popIndentation() {
2169 return null;
2170 }
2171 public void pushAnchorPoint() {
2172 }
2173 public void popAnchorPoint() {
2174 }
2175 public void setLineWidth(int lineWidth) { }
2176 public int write(String str, String wrap) throws IOException {
2177 return 0;
2178 }
2179 public int write(String str) throws IOException {
2180 buf.append(str); // just pass thru
2181 return str.length();
2182 }
2183 public int writeWrapSeparator(String wrap) throws IOException {
2184 return 0;
2185 }
2186 public int writeSeparator(String str) throws IOException {
2187 return write(str);
2188 }
2189 };
2190 StringTemplateGroup group =
2191 new StringTemplateGroup("test");
2192 group.defineTemplate("bold", "<b>$x$</b>");
2193 StringTemplate name = new StringTemplate(group, "$name:bold(x=name)$");
2194 name.setAttribute("name", "Terence");
2195 name.write(w);
2196 assertEquals("<b>Terence</b>", buf.toString());
2197 }
2198
2199 public void testApplyAnonymousTemplateToMapAndSet() throws Exception {
2200 StringTemplate st =
2201 new StringTemplate("$items:{<li>$it$</li>}$");
2202 Map m = new LinkedHashMap();
2203 m.put("a", "1");
2204 m.put("b", "2");
2205 m.put("c", "3");
2206 st.setAttribute("items", m);
2207 String expecting = "<li>1</li><li>2</li><li>3</li>";
2208 assertEquals(expecting, st.toString());
2209
2210 st = st.getInstanceOf();
2211 Set s = new HashSet();
2212 s.add("1");
2213 s.add("2");
2214 s.add("3");
2215 st.setAttribute("items", s);
2216 expecting = "<li>3</li><li>2</li><li>1</li>";
2217 assertEquals(expecting, st.toString());
2218 }
2219
2220 public void testDumpMapAndSet() throws Exception {
2221 StringTemplate st =
2222 new StringTemplate("$items; separator=\",\"$");
2223 Map m = new LinkedHashMap();
2224 m.put("a", "1");
2225 m.put("b", "2");
2226 m.put("c", "3");
2227 st.setAttribute("items", m);
2228 String expecting = "1,2,3";
2229 assertEquals(expecting, st.toString());
2230
2231 st = st.getInstanceOf();
2232 Set s = new HashSet();
2233 s.add("1");
2234 s.add("2");
2235 s.add("3");
2236 st.setAttribute("items", s);
2237 expecting = "3,2,1";
2238 assertEquals(expecting, st.toString());
2239 }
2240
2241 public class Connector3 {
2242 public int[] getValues() { return new int[] {1,2,3}; }
2243 public Map getStuff() {
2244 Map m = new LinkedHashMap(); m.put("a","1"); m.put("b","2"); return m;
2245 }
2246 }
2247
2248 public void testApplyAnonymousTemplateToArrayAndMapProperty() throws Exception {
2249 StringTemplate st =
2250 new StringTemplate("$x.values:{<li>$it$</li>}$");
2251 st.setAttribute("x", new Connector3());
2252 String expecting = "<li>1</li><li>2</li><li>3</li>";
2253 assertEquals(expecting, st.toString());
2254
2255 st = new StringTemplate("$x.stuff:{<li>$it$</li>}$");
2256 st.setAttribute("x", new Connector3());
2257 expecting = "<li>1</li><li>2</li>";
2258 assertEquals(expecting, st.toString());
2259 }
2260
2261 public void testSuperTemplateRef()
2262 throws Exception
2263 {
2264 // you can refer to a template defined in a super group via super.t()
2265 StringTemplateGroup group = new StringTemplateGroup("super");
2266 StringTemplateGroup subGroup = new StringTemplateGroup("sub");
2267 subGroup.setSuperGroup(group);
2268 group.defineTemplate("page", "$font()$:text");
2269 group.defineTemplate("font", "Helvetica");
2270 subGroup.defineTemplate("font", "$super.font()$ and Times");
2271 StringTemplate st = subGroup.getInstanceOf("page");
2272 String expecting =
2273 "Helvetica and Times:text";
2274 assertEquals(expecting, st.toString());
2275 }
2276
2277 public void testApplySuperTemplateRef()
2278 throws Exception
2279 {
2280 StringTemplateGroup group = new StringTemplateGroup("super");
2281 StringTemplateGroup subGroup = new StringTemplateGroup("sub");
2282 subGroup.setSuperGroup(group);
2283 group.defineTemplate("bold", "<b>$it$</b>");
2284 subGroup.defineTemplate("bold", "<strong>$it$</strong>");
2285 subGroup.defineTemplate("page", "$name:super.bold()$");
2286 StringTemplate st = subGroup.getInstanceOf("page");
2287 st.setAttribute("name", "Ter");
2288 String expecting =
2289 "<b>Ter</b>";
2290 assertEquals(expecting, st.toString());
2291 }
2292
2293 public void testLazyEvalOfSuperInApplySuperTemplateRef()
2294 throws Exception
2295 {
2296 StringTemplateGroup group = new StringTemplateGroup("base");
2297 StringTemplateGroup subGroup = new StringTemplateGroup("sub");
2298 subGroup.setSuperGroup(group);
2299 group.defineTemplate("bold", "<b>$it$</b>");
2300 subGroup.defineTemplate("bold", "<strong>$it$</strong>");
2301 // this is the same as testApplySuperTemplateRef() test
2302 // 'cept notice that here the supergroup defines page
2303 // As long as you create the instance via the subgroup,
2304 // "super." will evaluate lazily (i.e., not statically
2305 // during template compilation) to the templates
2306 // getGroup().superGroup value. If I create instance
2307 // of page in group not subGroup, however, I will get
2308 // an error as superGroup is null for group "group".
2309 group.defineTemplate("page", "$name:super.bold()$");
2310 StringTemplate st = subGroup.getInstanceOf("page");
2311 st.setAttribute("name", "Ter");
2312 String error = null;
2313 try {
2314 st.toString();
2315 }
2316 catch (IllegalArgumentException iae) {
2317 error = iae.getMessage();
2318 }
2319 String expectingError = "base has no super group; invalid template: super.bold";
2320 assertEquals(expectingError, error);
2321 }
2322
2323 public void testTemplatePolymorphism()
2324 throws Exception
2325 {
2326 StringTemplateGroup group = new StringTemplateGroup("super");
2327 StringTemplateGroup subGroup = new StringTemplateGroup("sub");
2328 subGroup.setSuperGroup(group);
2329 // bold is defined in both super and sub
2330 // if you create an instance of page via the subgroup,
2331 // then bold() should evaluate to the subgroup not the super
2332 // even though page is defined in the super. Just like polymorphism.
2333 group.defineTemplate("bold", "<b>$it$</b>");
2334 group.defineTemplate("page", "$name:bold()$");
2335 subGroup.defineTemplate("bold", "<strong>$it$</strong>");
2336 StringTemplate st = subGroup.getInstanceOf("page");
2337 st.setAttribute("name", "Ter");
2338 String expecting =
2339 "<strong>Ter</strong>";
2340 assertEquals(expecting, st.toString());
2341 }
2342
2343 public void testListOfEmbeddedTemplateSeesEnclosingAttributes() throws Exception {
2344 String templates =
2345 "group test;" +newline+
2346 "output(cond,items) ::= <<page: $items$>>" +newline+
2347 "mybody() ::= <<$font()$stuff>>" +newline+
2348 "font() ::= <<$if(cond)$this$else$that$endif$>>"
2349 ;
2350 StringTemplateErrorListener errors = new ErrorBuffer();
2351 StringTemplateGroup group =
2352 new StringTemplateGroup(new StringReader(templates),
2353 DefaultTemplateLexer.class,
2354 errors);
2355 StringTemplate outputST = group.getInstanceOf("output");
2356 StringTemplate bodyST1 = group.getInstanceOf("mybody");
2357 StringTemplate bodyST2 = group.getInstanceOf("mybody");
2358 StringTemplate bodyST3 = group.getInstanceOf("mybody");
2359 outputST.setAttribute("items", bodyST1);
2360 outputST.setAttribute("items", bodyST2);
2361 outputST.setAttribute("items", bodyST3);
2362 String expecting = "page: thatstuffthatstuffthatstuff";
2363 assertEquals(expecting, outputST.toString());
2364 }
2365
2366 public void testInheritArgumentFromRecursiveTemplateApplication() throws Exception {
2367 // do not inherit attributes through formal args
2368 String templates =
2369 "group test;" +newline+
2370 "block(stats) ::= \"<stats>\"" +
2371 "ifstat(stats) ::= \"IF true then <stats>\""+newline
2372 ;
2373 StringTemplateGroup group =
2374 new StringTemplateGroup(new StringReader(templates));
2375 StringTemplate b = group.getInstanceOf("block");
2376 b.setAttribute("stats", group.getInstanceOf("ifstat"));
2377 b.setAttribute("stats", group.getInstanceOf("ifstat"));
2378 String expecting = "IF true then IF true then ";
2379 String result = b.toString();
2380 //System.err.println("result='"+result+"'");
2381 assertEquals(expecting, result);
2382 }
2383
2384
2385 public void testDeliberateRecursiveTemplateApplication() throws Exception {
2386 // This test will cause infinite loop. block contains a stat which
2387 // contains the same block. Must be in lintMode to detect
2388 String templates =
2389 "group test;" +newline+
2390 "block(stats) ::= \"<stats>\"" +
2391 "ifstat(stats) ::= \"IF true then <stats>\""+newline
2392 ;
2393 StringTemplate.setLintMode(true);
2394 StringTemplate.resetTemplateCounter();
2395 StringTemplateGroup group =
2396 new StringTemplateGroup(new StringReader(templates));
2397 StringTemplate b = group.getInstanceOf("block");
2398 StringTemplate ifstat = group.getInstanceOf("ifstat");
2399 b.setAttribute("stats", ifstat); // block has if stat
2400 ifstat.setAttribute("stats", b); // but make "if" contain block
2401 String expectingError =
2402 "infinite recursion to <ifstat([stats])@4> referenced in <block([stats])@3>; stack trace:"+newline +
2403 "<ifstat([stats])@4>, attributes=[stats=<block()@3>]>"+newline +
2404 "<block([stats])@3>, attributes=[stats=<ifstat()@4>], references=[stats]>"+newline +
2405 "<ifstat([stats])@4> (start of recursive cycle)"+newline +
2406 "...";
2407 // note that attributes attribute doesn't show up in ifstat() because
2408 // recursion detection traps the problem before it writes out the
2409 // infinitely-recursive template; I set the attributes attribute right
2410 // before I render.
2411 String errors = "";
2412 try {
2413 /*String result =*/ b.toString();
2414 }
2415 catch (IllegalStateException ise) {
2416 errors = ise.getMessage();
2417 }
2418 //System.err.println("errors="+errors+"'");
2419 //System.err.println("expecting="+expectingError+"'");
2420 StringTemplate.setLintMode(false);
2421 assertEquals(expectingError, errors);
2422 }
2423
2424
2425 public void testImmediateTemplateAsAttributeLoop() throws Exception {
2426 // even though block has a stats value that refers to itself,
2427 // there is no recursion because each instance of block hides
2428 // the stats value from above since it's a formal arg.
2429 String templates =
2430 "group test;" +newline+
2431 "block(stats) ::= \"{<stats>}\""
2432 ;
2433 StringTemplateGroup group =
2434 new StringTemplateGroup(new StringReader(templates));
2435 StringTemplate b = group.getInstanceOf("block");
2436 b.setAttribute("stats", group.getInstanceOf("block"));
2437 String expecting ="{{}}";
2438 String result = b.toString();
2439 //System.err.println(result);
2440 assertEquals(expecting, result);
2441 }
2442
2443
2444 public void testTemplateAlias() throws Exception {
2445 String templates =
2446 "group test;" +newline+
2447 "page(name) ::= \"name is <name>\"" +
2448 "other ::= page"+newline
2449 ;
2450 StringTemplateGroup group =
2451 new StringTemplateGroup(new StringReader(templates));
2452 StringTemplate b = group.getInstanceOf("other"); // alias for page
2453 b.setAttribute("name", "Ter");
2454 String expecting ="name is Ter";
2455 String result = b.toString();
2456 assertEquals(expecting, result);
2457 }
2458
2459 public void testTemplateGetPropertyGetsAttribute() throws Exception {
2460 // This test will cause infinite loop if missing attribute no
2461 // properly caught in getAttribute
2462 String templates =
2463 "group test;"+newline+
2464 "Cfile(funcs) ::= <<"+newline +
2465 "#include \\<stdio.h>"+newline+
2466 "<funcs:{public void <it.name>(<it.args>);}; separator=\"\\n\">"+newline+
2467 "<funcs; separator=\"\\n\">"+newline+
2468 ">>"+newline +
2469 "func(name,args,body) ::= <<"+newline+
2470 "public void <name>(<args>) {<body>}"+newline +
2471 ">>"+newline
2472 ;
2473 StringTemplateGroup group =
2474 new StringTemplateGroup(new StringReader(templates));
2475 StringTemplate b = group.getInstanceOf("Cfile");
2476 StringTemplate f1 = group.getInstanceOf("func");
2477 StringTemplate f2 = group.getInstanceOf("func");
2478 f1.setAttribute("name", "f");
2479 f1.setAttribute("args", "");
2480 f1.setAttribute("body", "i=1;");
2481 f2.setAttribute("name", "g");
2482 f2.setAttribute("args", "int arg");
2483 f2.setAttribute("body", "y=1;");
2484 b.setAttribute("funcs",f1);
2485 b.setAttribute("funcs",f2);
2486 String expecting = "#include <stdio.h>" +newline+
2487 "public void f();"+newline+
2488 "public void g(int arg);" +newline+
2489 "public void f() {i=1;}"+newline+
2490 "public void g(int arg) {y=1;}";
2491 assertEquals(expecting,b.toString());
2492 }
2493
2494 public static class Decl {
2495 String name;
2496 String type;
2497 public Decl(String name, String type) {this.name=name; this.type=type;}
2498 public String getName() {return name;}
2499 public String getType() {return type;}
2500 }
2501
2502 public void testComplicatedIndirectTemplateApplication() throws Exception {
2503 String templates =
2504 "group Java;"+newline +
2505 ""+newline +
2506 "file(variables) ::= <<" +
2507 "<variables:{ v | <v.decl:(v.format)()>}; separator=\"\\n\">"+newline +
2508 ">>"+newline+
2509 "intdecl(decl) ::= \"int <decl.name> = 0;\""+newline +
2510 "intarray(decl) ::= \"int[] <decl.name> = null;\""+newline
2511 ;
2512 StringTemplateGroup group =
2513 new StringTemplateGroup(new StringReader(templates));
2514 StringTemplate f = group.getInstanceOf("file");
2515 f.setAttribute("variables.{decl,format}", new Decl("i","int"), "intdecl");
2516 f.setAttribute("variables.{decl,format}", new Decl("a","int-array"), "intarray");
2517 //System.out.println("f='"+f+"'");
2518 String expecting = "int i = 0;" +newline+
2519 "int[] a = null;";
2520 assertEquals(expecting, f.toString());
2521 }
2522
2523 public void testIndirectTemplateApplication() throws Exception {
2524 String templates =
2525 "group dork;"+newline +
2526 ""+newline +
2527 "test(name) ::= <<" +
2528 "<(name)()>"+newline +
2529 ">>"+newline+
2530 "first() ::= \"the first\""+newline +
2531 "second() ::= \"the second\""+newline
2532 ;
2533 StringTemplateGroup group =
2534 new StringTemplateGroup(new StringReader(templates));
2535 StringTemplate f = group.getInstanceOf("test");
2536 f.setAttribute("name", "first");
2537 String expecting = "the first";
2538 assertEquals(expecting, f.toString());
2539 }
2540
2541 public void testIndirectTemplateWithArgsApplication() throws Exception {
2542 String templates =
2543 "group dork;"+newline +
2544 ""+newline +
2545 "test(name) ::= <<" +
2546 "<(name)(a=\"foo\")>"+newline +
2547 ">>"+newline+
2548 "first(a) ::= \"the first: <a>\""+newline +
2549 "second(a) ::= \"the second <a>\""+newline
2550 ;
2551 StringTemplateGroup group =
2552 new StringTemplateGroup(new StringReader(templates));
2553 StringTemplate f = group.getInstanceOf("test");
2554 f.setAttribute("name", "first");
2555 String expecting = "the first: foo";
2556 assertEquals(f.toString(), expecting);
2557 }
2558
2559 public void testNullIndirectTemplateApplication() throws Exception {
2560 String templates =
2561 "group dork;"+newline +
2562 ""+newline +
2563 "test(names,t) ::= <<" +
2564 "<names:(t)()>"+newline + // t null be must be defined else error: null attr w/o formal def
2565 ">>"+newline+
2566 "ind() ::= \"[<it>]\""+newline;
2567 ;
2568 StringTemplateGroup group =
2569 new StringTemplateGroup(new StringReader(templates));
2570 StringTemplate f = group.getInstanceOf("test");
2571 f.setAttribute("names", "me");
2572 f.setAttribute("names", "you");
2573 String expecting = "";
2574 assertEquals(expecting, f.toString());
2575 }
2576
2577 public void testNullIndirectTemplate() throws Exception {
2578 String templates =
2579 "group dork;"+newline +
2580 ""+newline +
2581 "test(name) ::= <<" +
2582 "<(name)()>"+newline +
2583 ">>"+newline+
2584 "first() ::= \"the first\""+newline +
2585 "second() ::= \"the second\""+newline
2586 ;
2587 StringTemplateGroup group =
2588 new StringTemplateGroup(new StringReader(templates));
2589 StringTemplate f = group.getInstanceOf("test");
2590 //f.setAttribute("name", "first");
2591 String expecting = "";
2592 assertEquals(expecting, f.toString());
2593 }
2594
2595 public void testHashMapPropertyFetch() throws Exception {
2596 StringTemplate a = new StringTemplate("$stuff.prop$");
2597 HashMap map = new HashMap();
2598 a.setAttribute("stuff", map);
2599 map.put("prop", "Terence");
2600 String results = a.toString();
2601 //System.out.println(results);
2602 String expecting = "Terence";
2603 assertEquals(expecting, results);
2604 }
2605
2606 public void testHashMapPropertyFetchEmbeddedStringTemplate() throws Exception {
2607 StringTemplate a = new StringTemplate("$stuff.prop$");
2608 HashMap map = new HashMap();
2609 a.setAttribute("stuff", map);
2610 a.setAttribute("title", "ST rocks");
2611 map.put("prop", new StringTemplate("embedded refers to $title$"));
2612 String results = a.toString();
2613 //System.out.println(results);
2614 String expecting = "embedded refers to ST rocks";
2615 assertEquals(expecting, results);
2616 }
2617
2618 public void testEmbeddedComments() throws Exception {
2619 StringTemplate st = new StringTemplate(
2620 "Foo $! ignore !$bar" +newline
2621 );
2622 String expecting ="Foo bar"+newline;
2623 String result = st.toString();
2624 assertEquals(expecting, result);
2625
2626 st = new StringTemplate(
2627 "Foo $! ignore" +newline+
2628 " and a line break!$" +newline+
2629 "bar" +newline
2630 );
2631 expecting ="Foo "+newline+"bar"+newline;
2632 result = st.toString();
2633 assertEquals(expecting, result);
2634
2635 st = new StringTemplate(
2636 "$! start of line $ and $! ick" +newline+
2637 "!$boo"+newline
2638 );
2639 expecting ="boo"+newline;
2640 result = st.toString();
2641 assertEquals(expecting, result);
2642
2643 st = new StringTemplate(
2644 "$! start of line !$" +newline+
2645 "$! another to ignore !$" +newline+
2646 "$! ick" +newline+
2647 "!$boo"+newline
2648 );
2649 expecting ="boo"+newline;
2650 result = st.toString();
2651 assertEquals(expecting, result);
2652
2653 st = new StringTemplate(
2654 "$! back !$$! to back !$" +newline+ // can't detect; leaves \n
2655 "$! ick" +newline+
2656 "!$boo"+newline
2657 );
2658 expecting =newline+"boo"+newline;
2659 result = st.toString();
2660 assertEquals(expecting, result);
2661 }
2662
2663 public void testEmbeddedCommentsAngleBracketed() throws Exception {
2664 StringTemplate st = new StringTemplate(
2665 "Foo <! ignore !>bar" +newline,
2666 AngleBracketTemplateLexer.class
2667 );
2668 String expecting ="Foo bar"+newline;
2669 String result = st.toString();
2670 assertEquals(expecting, result);
2671
2672 st = new StringTemplate(
2673 "Foo <! ignore" +newline+
2674 " and a line break!>" +newline+
2675 "bar" +newline,
2676 AngleBracketTemplateLexer.class
2677 );
2678 expecting ="Foo "+newline+"bar"+newline;
2679 result = st.toString();
2680 assertEquals(expecting, result);
2681
2682 st = new StringTemplate(
2683 "<! start of line $ and <! ick" +newline+
2684 "!>boo"+newline,
2685 AngleBracketTemplateLexer.class
2686 );
2687 expecting ="boo"+newline;
2688 result = st.toString();
2689 assertEquals(expecting, result);
2690
2691 st = new StringTemplate(
2692 "<! start of line !>" +
2693 "<! another to ignore !>" +
2694 "<! ick" +newline+
2695 "!>boo"+newline,
2696 AngleBracketTemplateLexer.class
2697 );
2698 expecting ="boo"+newline;
2699 result = st.toString();
2700 //System.out.println(result);
2701 assertEquals(expecting, result);
2702
2703 st = new StringTemplate(
2704 "<! back !><! to back !>" +newline+ // can't detect; leaves \n
2705 "<! ick" +newline+
2706 "!>boo"+newline,
2707 AngleBracketTemplateLexer.class
2708 );
2709 expecting =newline+"boo"+newline;
2710 result = st.toString();
2711 assertEquals(expecting, result);
2712 }
2713
2714 public void testLineBreak() throws Exception {
2715 StringTemplate st = new StringTemplate(
2716 "Foo <\\\\>"+newline+
2717 " \t bar" +newline,
2718 AngleBracketTemplateLexer.class
2719 );
2720 StringWriter sw = new StringWriter();
2721 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2722 String result = sw.toString();
2723 String expecting ="Foo bar"+newline; // expect \n in output
2724 assertEquals(expecting, result);
2725 }
2726
2727 public void testLineBreak2() throws Exception {
2728 StringTemplate st = new StringTemplate(
2729 "Foo <\\\\> "+newline+
2730 " \t bar" +newline,
2731 AngleBracketTemplateLexer.class
2732 );
2733 StringWriter sw = new StringWriter();
2734 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2735 String result = sw.toString();
2736 String expecting ="Foo bar"+newline; // expect \n in output
2737 assertEquals(expecting, result);
2738 }
2739
2740 public void testLineBreakNoWhiteSpace() throws Exception {
2741 StringTemplate st = new StringTemplate(
2742 "Foo <\\\\>"+newline+
2743 "bar" +newline,
2744 AngleBracketTemplateLexer.class
2745 );
2746 StringWriter sw = new StringWriter();
2747 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2748 String result = sw.toString();
2749 String expecting ="Foo bar"+newline; // expect \n in output
2750 assertEquals(expecting, result);
2751 }
2752
2753 public void testLineBreakDollar() throws Exception {
2754 StringTemplate st = new StringTemplate(
2755 "Foo $\\\\$"+newline+
2756 " \t bar" +newline,
2757 DefaultTemplateLexer.class
2758 );
2759 StringWriter sw = new StringWriter();
2760 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2761 String result = sw.toString();
2762 String expecting ="Foo bar"+newline; // expect \n in output
2763 assertEquals(expecting, result);
2764 }
2765
2766 public void testLineBreakDollar2() throws Exception {
2767 StringTemplate st = new StringTemplate(
2768 "Foo $\\\\$ "+newline+
2769 " \t bar" +newline,
2770 DefaultTemplateLexer.class
2771 );
2772 StringWriter sw = new StringWriter();
2773 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2774 String result = sw.toString();
2775 String expecting ="Foo bar"+newline; // expect \n in output
2776 assertEquals(expecting, result);
2777 }
2778
2779 public void testLineBreakNoWhiteSpaceDollar() throws Exception {
2780 StringTemplate st = new StringTemplate(
2781 "Foo $\\\\$"+newline+
2782 "bar" +newline,
2783 DefaultTemplateLexer.class
2784 );
2785 StringWriter sw = new StringWriter();
2786 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2787 String result = sw.toString();
2788 String expecting ="Foo bar"+newline; // expect \n in output
2789 assertEquals(expecting, result);
2790 }
2791
2792 public void testCharLiterals() throws Exception {
2793 StringTemplate st = new StringTemplate(
2794 "Foo <\\r\\n><\\n><\\t> bar" +newline,
2795 AngleBracketTemplateLexer.class
2796 );
2797 StringWriter sw = new StringWriter();
2798 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2799 String result = sw.toString();
2800 String expecting ="Foo \n\n\t bar"+newline; // expect \n in output
2801 assertEquals(expecting, result);
2802
2803 st = new StringTemplate(
2804 "Foo $\\n$$\\t$ bar" +newline);
2805 sw = new StringWriter();
2806 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2807 expecting ="Foo \n\t bar"+newline; // expect \n in output
2808 result = sw.toString();
2809 assertEquals(expecting, result);
2810
2811 st = new StringTemplate(
2812 "Foo$\\ $bar$\\n$");
2813 sw = new StringWriter();
2814 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2815 result = sw.toString();
2816 expecting ="Foo bar\n"; // force \n
2817 assertEquals(expecting, result);
2818 }
2819
2820 public void testNewlineNormalizationInTemplateString() throws Exception {
2821 StringTemplate st = new StringTemplate(
2822 "Foo\r\n"+
2823 "Bar\n",
2824 AngleBracketTemplateLexer.class
2825 );
2826 StringWriter sw = new StringWriter();
2827 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2828 String result = sw.toString();
2829 String expecting ="Foo\nBar\n"; // expect \n in output
2830 assertEquals(expecting, result);
2831 }
2832
2833 public void testNewlineNormalizationInTemplateStringPC() throws Exception {
2834 StringTemplate st = new StringTemplate(
2835 "Foo\r\n"+
2836 "Bar\n",
2837 AngleBracketTemplateLexer.class
2838 );
2839 StringWriter sw = new StringWriter();
2840 st.write(new AutoIndentWriter(sw,"\r\n")); // force \r\n as newline
2841 String result = sw.toString();
2842 String expecting ="Foo\r\nBar\r\n"; // expect \r\n in output
2843 assertEquals(expecting, result);
2844 }
2845
2846 public void testNewlineNormalizationInAttribute() throws Exception {
2847 StringTemplate st = new StringTemplate(
2848 "Foo\r\n"+
2849 "<name>\n",
2850 AngleBracketTemplateLexer.class
2851 );
2852 st.setAttribute("name", "a\nb\r\nc");
2853 StringWriter sw = new StringWriter();
2854 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2855 String result = sw.toString();
2856 String expecting ="Foo\na\nb\nc\n"; // expect \n in output
2857 assertEquals(expecting, result);
2858 }
2859
2860 public void testUnicodeLiterals() throws Exception {
2861 StringTemplate st = new StringTemplate(
2862 "Foo <\\uFEA5\\n\\u00C2> bar" +newline,
2863 AngleBracketTemplateLexer.class
2864 );
2865 String expecting ="Foo \ufea5"+newline+"\u00C2 bar"+newline;
2866 String result = st.toString();
2867 assertEquals(expecting, result);
2868
2869 st = new StringTemplate(
2870 "Foo $\\uFEA5\\n\\u00C2$ bar" +newline);
2871 expecting ="Foo \ufea5"+newline+"\u00C2 bar"+newline;
2872 result = st.toString();
2873 assertEquals(expecting, result);
2874
2875 st = new StringTemplate(
2876 "Foo$\\ $bar$\\n$");
2877 expecting ="Foo bar"+newline;
2878 result = st.toString();
2879 assertEquals(expecting, result);
2880 }
2881
2882
2883 public void testEmptyIteratedValueGetsSeparator() throws Exception {
2884 StringTemplateGroup group =
2885 new StringTemplateGroup("test");
2886 StringTemplateErrorListener errors = new ErrorBuffer();
2887 group.setErrorListener(errors);
2888 StringTemplate t = new StringTemplate(group, "$names; separator=\",\"$");
2889 t.setAttribute("names", "Terence");
2890 t.setAttribute("names", "");
2891 t.setAttribute("names", "");
2892 t.setAttribute("names", "Tom");
2893 t.setAttribute("names", "Frank");
2894 t.setAttribute("names", "");
2895 // empty values get separator still
2896 String expecting="Terence,,,Tom,Frank,";
2897 String result = t.toString();
2898 assertEquals(expecting, result);
2899 }
2900
2901 public void testMissingIteratedConditionalValueGetsNOSeparator() throws Exception {
2902 StringTemplateGroup group =
2903 new StringTemplateGroup("test");
2904 StringTemplateErrorListener errors = new ErrorBuffer();
2905 group.setErrorListener(errors);
2906 StringTemplate t = new StringTemplate(group,
2907 "$users:{$if(it.ok)$$it.name$$endif$}; separator=\",\"$");
2908 t.setAttribute("users.{name,ok}", "Terence", new Boolean(true));
2909 t.setAttribute("users.{name,ok}", "Tom", new Boolean(false));
2910 t.setAttribute("users.{name,ok}", "Frank", new Boolean(true));
2911 t.setAttribute("users.{name,ok}", "Johnny", new Boolean(false));
2912 // empty conditional values get no separator
2913 String expecting="Terence,Frank";
2914 String result = t.toString();
2915 assertEquals(expecting, result);
2916 }
2917
2918 public void testMissingIteratedConditionalValueGetsNOSeparator2() throws Exception {
2919 StringTemplateGroup group =
2920 new StringTemplateGroup("test");
2921 StringTemplateErrorListener errors = new ErrorBuffer();
2922 group.setErrorListener(errors);
2923 StringTemplate t = new StringTemplate(group,
2924 "$users:{$if(it.ok)$$it.name$$endif$}; separator=\",\"$");
2925 t.setAttribute("users.{name,ok}", "Terence", new Boolean(true));
2926 t.setAttribute("users.{name,ok}", "Tom", new Boolean(false));
2927 t.setAttribute("users.{name,ok}", "Frank", new Boolean(false));
2928 t.setAttribute("users.{name,ok}", "Johnny", new Boolean(false));
2929 // empty conditional values get no separator
2930 String expecting="Terence";
2931 String result = t.toString();
2932 assertEquals(expecting, result);
2933 }
2934
2935 public void testMissingIteratedDoubleConditionalValueGetsNOSeparator() throws Exception {
2936 StringTemplateGroup group =
2937 new StringTemplateGroup("test");
2938 StringTemplateErrorListener errors = new ErrorBuffer();
2939 group.setErrorListener(errors);
2940 StringTemplate t = new StringTemplate(group,
2941 "$users:{$if(it.ok)$$it.name$$endif$$if(it.ok)$$it.name$$endif$}; separator=\",\"$");
2942 t.setAttribute("users.{name,ok}", "Terence", new Boolean(false));
2943 t.setAttribute("users.{name,ok}", "Tom", new Boolean(true));
2944 t.setAttribute("users.{name,ok}", "Frank", new Boolean(true));
2945 t.setAttribute("users.{name,ok}", "Johnny", new Boolean(true));
2946 // empty conditional values get no separator
2947 String expecting="TomTom,FrankFrank,JohnnyJohnny";
2948 String result = t.toString();
2949 assertEquals(expecting, result);
2950 }
2951
2952 public void testIteratedConditionalWithEmptyElseValueGetsSeparator() throws Exception {
2953 StringTemplateGroup group =
2954 new StringTemplateGroup("test");
2955 StringTemplateErrorListener errors = new ErrorBuffer();
2956 group.setErrorListener(errors);
2957 StringTemplate t = new StringTemplate(group,
2958 "$users:{$if(it.ok)$$it.name$$else$$endif$}; separator=\",\"$");
2959 t.setAttribute("users.{name,ok}", "Terence", new Boolean(true));
2960 t.setAttribute("users.{name,ok}", "Tom", new Boolean(false));
2961 t.setAttribute("users.{name,ok}", "Frank", new Boolean(true));
2962 t.setAttribute("users.{name,ok}", "Johnny", new Boolean(false));
2963 // empty conditional values get no separator
2964 String expecting="Terence,,Frank,";
2965 String result = t.toString();
2966 assertEquals(expecting, result);
2967 }
2968
2969 public void testWhiteSpaceAtEndOfTemplate() throws Exception {
2970 StringTemplateGroup group = new StringTemplateGroup("group");
2971 StringTemplate pageST = group.getInstanceOf("org/antlr/stringtemplate/test/page");
2972 StringTemplate listST = group.getInstanceOf("org/antlr/stringtemplate/test/users_list");
2973 // users.list references row.st which has a single blank line at the end.
2974 // I.e., there are 2 \n in a row at the end
2975 // ST should eat all whitespace at end
2976 listST.setAttribute("users", new Connector());
2977 listST.setAttribute("users", new Connector2());
2978 pageST.setAttribute("title", "some title");
2979 pageST.setAttribute("body", listST);
2980 String expecting ="some title" +newline+
2981 "Terence parrt@jguru.comTom tombu@jguru.com";
2982 String result = pageST.toString();
2983 //System.out.println("'"+result+"'");
2984 assertEquals(expecting, result);
2985 }
2986
2987 static class Duh {
2988 public List users = new ArrayList();
2989 }
2990
2991 public void testSizeZeroButNonNullListGetsNoOutput() throws Exception {
2992 StringTemplateGroup group =
2993 new StringTemplateGroup("test");
2994 StringTemplateErrorListener errors = new ErrorBuffer();
2995 group.setErrorListener(errors);
2996 StringTemplate t = new StringTemplate(group,
2997 "begin\n" +
2998 "$duh.users:{name: $it$}; separator=\", \"$\n" +
2999 "end\n");
3000 t.setAttribute("duh", new Duh());
3001 String expecting="begin\nend\n";
3002 String result = t.toString();
3003 assertEquals(expecting, result);
3004 }
3005
3006 public void testNullListGetsNoOutput() throws Exception {
3007 StringTemplateGroup group =
3008 new StringTemplateGroup("test");
3009 StringTemplateErrorListener errors = new ErrorBuffer();
3010 group.setErrorListener(errors);
3011 StringTemplate t = new StringTemplate(group,
3012 "begin\n" +
3013 "$users:{name: $it$}; separator=\", \"$\n" +
3014 "end\n");
3015 //t.setAttribute("users", new Duh());
3016 String expecting="begin\nend\n";
3017 String result = t.toString();
3018 assertEquals(expecting, result);
3019 }
3020
3021 public void testEmptyListGetsNoOutput() throws Exception {
3022 StringTemplateGroup group =
3023 new StringTemplateGroup("test");
3024 StringTemplateErrorListener errors = new ErrorBuffer();
3025 group.setErrorListener(errors);
3026 StringTemplate t = new StringTemplate(group,
3027 "begin\n" +
3028 "$users:{name: $it$}; separator=\", \"$\n" +
3029 "end\n");
3030 t.setAttribute("users", new ArrayList());
3031 String expecting="begin\nend\n";
3032 String result = t.toString();
3033 assertEquals(expecting, result);
3034 }
3035
3036 public void testEmptyListNoIteratorGetsNoOutput() throws Exception {
3037 StringTemplateGroup group =
3038 new StringTemplateGroup("test");
3039 StringTemplateErrorListener errors = new ErrorBuffer();
3040 group.setErrorListener(errors);
3041 StringTemplate t = new StringTemplate(group,
3042 "begin\n" +
3043 "$users; separator=\", \"$\n" +
3044 "end\n");
3045 t.setAttribute("users", new ArrayList());
3046 String expecting="begin\nend\n";
3047 String result = t.toString();
3048 assertEquals(expecting, result);
3049 }
3050
3051 public void testEmptyExprAsFirstLineGetsNoOutput() throws Exception {
3052 StringTemplateGroup group =
3053 new StringTemplateGroup("test");
3054 StringTemplateErrorListener errors = new ErrorBuffer();
3055 group.setErrorListener(errors);
3056 group.defineTemplate("bold", "<b>$it$</b>");
3057 StringTemplate t = new StringTemplate(group,
3058 "$users$\n" +
3059 "end\n");
3060 String expecting="end\n";
3061 String result = t.toString();
3062 assertEquals(expecting, result);
3063 }
3064
3065 public void testSizeZeroOnLineByItselfGetsNoOutput() throws Exception {
3066 StringTemplateGroup group =
3067 new StringTemplateGroup("test");
3068 StringTemplateErrorListener errors = new ErrorBuffer();
3069 group.setErrorListener(errors);
3070 StringTemplate t = new StringTemplate(group,
3071 "begin\n"+
3072 "$name$\n"+
3073 "$users:{name: $it$}$\n"+
3074 "$users:{name: $it$}; separator=\", \"$\n"+
3075 "end\n");
3076 String expecting="begin\nend\n";
3077 String result = t.toString();
3078 assertEquals(expecting, result);
3079 }
3080
3081 public void testSizeZeroOnLineWithIndentGetsNoOutput() throws Exception {
3082 StringTemplateGroup group =
3083 new StringTemplateGroup("test");
3084 StringTemplateErrorListener errors = new ErrorBuffer();
3085 group.setErrorListener(errors);
3086 StringTemplate t = new StringTemplate(group,
3087 "begin\n"+
3088 " $name$\n"+
3089 " $users:{name: $it$}$\n"+
3090 " $users:{name: $it$$\\n$}$\n"+
3091 "end\n");
3092 String expecting="begin\nend\n";
3093 String result = t.toString();
3094 assertEquals(expecting, result);
3095 }
3096
3097 public void testSimpleAutoIndent() throws Exception {
3098 StringTemplate a = new StringTemplate(
3099 "$title$: {\n" +
3100 " $name; separator=\"\n\"$\n" +
3101 "}");
3102 a.setAttribute("title", "foo");
3103 a.setAttribute("name", "Terence");
3104 a.setAttribute("name", "Frank");
3105 String results = a.toString();
3106 //System.out.println(results);
3107 String expecting =
3108 "foo: {\n" +
3109 " Terence\n" +
3110 " Frank\n" +
3111 "}";
3112 assertEquals(results, expecting);
3113 }
3114
3115 public void testComputedPropertyName() throws Exception {
3116 StringTemplateGroup group =
3117 new StringTemplateGroup("test");
3118 StringTemplateErrorListener errors = new ErrorBuffer();
3119 group.setErrorListener(errors);
3120 StringTemplate t = new StringTemplate(group,
3121 "variable property $propName$=$v.(propName)$");
3122 t.setAttribute("v", new Decl("i","int"));
3123 t.setAttribute("propName", "type");
3124 String expecting="variable property type=int";
3125 String result = t.toString();
3126 assertEquals("", errors.toString());
3127 assertEquals(expecting, result);
3128 }
3129
3130 public void testNonNullButEmptyIteratorTestsFalse() throws Exception {
3131 StringTemplateGroup group =
3132 new StringTemplateGroup("test");
3133 StringTemplate t = new StringTemplate(group,
3134 "$if(users)$\n" +
3135 "Users: $users:{$it.name$ }$\n" +
3136 "$endif$");
3137 t.setAttribute("users", new LinkedList());
3138 String expecting="";
3139 String result = t.toString();
3140 assertEquals(expecting, result);
3141 }
3142
3143 public void testDoNotInheritAttributesThroughFormalArgs() throws Exception {
3144 String templates =
3145 "group test;" +newline+
3146 "method(name) ::= \"<stat()>\"" +newline+
3147 "stat(name) ::= \"x=y; // <name>\""+newline
3148 ;
3149 // name is not visible in stat because of the formal arg called name.
3150 // somehow, it must be set.
3151 StringTemplateGroup group =
3152 new StringTemplateGroup(new StringReader(templates));
3153 StringTemplate b = group.getInstanceOf("method");
3154 b.setAttribute("name", "foo");
3155 String expecting = "x=y; // ";
3156 String result = b.toString();
3157 //System.err.println("result='"+result+"'");
3158 assertEquals(expecting, result);
3159 }
3160
3161 public void testArgEvaluationContext() throws Exception {
3162 String templates =
3163 "group test;" +newline+
3164 "method(name) ::= \"<stat(name=name)>\"" +newline+
3165 "stat(name) ::= \"x=y; // <name>\""+newline
3166 ;
3167 // attribute name is not visible in stat because of the formal
3168 // arg called name in template stat. However, we can set it's value
3169 // with an explicit name=name. This looks weird, but makes total
3170 // sense as the rhs is evaluated in the context of method and the lhs
3171 // is evaluated in the context of stat's arg list.
3172 StringTemplateGroup group =
3173 new StringTemplateGroup(new StringReader(templates));
3174 StringTemplate b = group.getInstanceOf("method");
3175 b.setAttribute("name", "foo");
3176 String expecting = "x=y; // foo";
3177 String result = b.toString();
3178 //System.err.println("result='"+result+"'");
3179 assertEquals(expecting, result);
3180 }
3181
3182 public void testPassThroughAttributes() throws Exception {
3183 String templates =
3184 "group test;" +newline+
3185 "method(name) ::= \"<stat(...)>\"" +newline+
3186 "stat(name) ::= \"x=y; // <name>\""+newline
3187 ;
3188 StringTemplateGroup group =
3189 new StringTemplateGroup(new StringReader(templates));
3190 StringTemplate b = group.getInstanceOf("method");
3191 b.setAttribute("name", "foo");
3192 String expecting = "x=y; // foo";
3193 String result = b.toString();
3194 //System.err.println("result='"+result+"'");
3195 assertEquals(expecting, result);
3196 }
3197
3198 public void testPassThroughAttributes2() throws Exception {
3199 String templates =
3200 "group test;" +newline+
3201 "method(name) ::= <<"+newline+
3202 "<stat(value=\"34\",...)>" +newline+
3203 ">>"+newline+
3204 "stat(name,value) ::= \"x=<value>; // <name>\""+newline
3205 ;
3206 StringTemplateGroup group =
3207 new StringTemplateGroup(new StringReader(templates));
3208 StringTemplate b = group.getInstanceOf("method");
3209 b.setAttribute("name", "foo");
3210 String expecting = "x=34; // foo";
3211 String result = b.toString();
3212 //System.err.println("result='"+result+"'");
3213 assertEquals(expecting, result);
3214 }
3215
3216 public void testDefaultArgument() throws Exception {
3217 String templates =
3218 "group test;" +newline+
3219 "method(name) ::= <<"+newline+
3220 "<stat(...)>" +newline+
3221 ">>"+newline+
3222 "stat(name,value=\"99\") ::= \"x=<value>; // <name>\""+newline
3223 ;
3224 StringTemplateGroup group =
3225 new StringTemplateGroup(new StringReader(templates));
3226 StringTemplate b = group.getInstanceOf("method");
3227 b.setAttribute("name", "foo");
3228 String expecting = "x=99; // foo";
3229 String result = b.toString();
3230 //System.err.println("result='"+result+"'");
3231 assertEquals(expecting, result);
3232 }
3233
3234 public void testDefaultArgument2() throws Exception {
3235 String templates =
3236 "group test;" +newline+
3237 "stat(name,value=\"99\") ::= \"x=<value>; // <name>\""+newline
3238 ;
3239 StringTemplateGroup group =
3240 new StringTemplateGroup(new StringReader(templates));
3241 StringTemplate b = group.getInstanceOf("stat");
3242 b.setAttribute("name", "foo");
3243 String expecting = "x=99; // foo";
3244 String result = b.toString();
3245 //System.err.println("result='"+result+"'");
3246 assertEquals(expecting, result);
3247 }
3248
3249 public void testDefaultArgumentManuallySet() throws Exception {
3250 class Field {
3251 public String name = "parrt";
3252 public int n = 0;
3253 public String toString() {
3254 return "Field";
3255 }
3256 }
3257 String templates =
3258 "group test;" +newline+
3259 "method(fields) ::= <<"+newline+
3260 "<fields:{f | <stat(f=f)>}>" +newline+
3261 ">>"+newline+
3262 "stat(f,value={<f.name>}) ::= \"x=<value>; // <f.name>\""+newline
3263 ;
3264 StringTemplateGroup group =
3265 new StringTemplateGroup(new StringReader(templates));
3266 StringTemplate m = group.getInstanceOf("method");
3267 m.setAttribute("fields", new Field());
3268 String expecting = "x=parrt; // parrt";
3269 String result = m.toString();
3270 assertEquals(expecting, result);
3271 }
3272
3273 /** This fails because checkNullAttributeAgainstFormalArguments looks
3274 * for a formal argument at the current level not of the original embedded
3275 * template. We have defined it all the way in the embedded, but there is
3276 * no value so we try to look upwards ala dynamic scoping. When it reaches
3277 * the top, it doesn't find a value but it will miss the
3278 * formal argument down in the embedded.
3279 *
3280 * By definition, though, the formal parameter exists if we have
3281 * a default value. look up the value to see if it's null without
3282 * checking checkNullAttributeAgainstFormalArguments.
3283 */
3284 public void testDefaultArgumentImplicitlySet() throws Exception {
3285 class Field {
3286 public String name = "parrt";
3287 public int n = 0;
3288 public String toString() {
3289 return "Field";
3290 }
3291 }
3292 String templates =
3293 "group test;" +newline+
3294 "method(fields) ::= <<"+newline+
3295 "<fields:{f | <stat(...)>}>" +newline+
3296 ">>"+newline+
3297 "stat(f,value={<f.name>}) ::= \"x=<value>; // <f.name>\""+newline
3298 ;
3299 StringTemplateGroup group =
3300 new StringTemplateGroup(new StringReader(templates));
3301 StringTemplate m = group.getInstanceOf("method");
3302 m.setAttribute("fields", new Field());
3303 String expecting = "x=parrt; // parrt";
3304 String result = m.toString();
3305 assertEquals(expecting, result);
3306 }
3307
3308 /* FIX THIS
3309 public void testDefaultArgumentImplicitlySet2() throws Exception {
3310 class Field {
3311 public String name = "parrt";
3312 public int n = 0;
3313 public String toString() {
3314 return "Field";
3315 }
3316 }
3317 String templates =
3318 "group test;" +newline+
3319 "method(fields) ::= <<"+newline+
3320 "<fields:{f | <f:stat()>}>" +newline+ // THIS SHOULD BE ERROR; >1 arg?
3321 ">>"+newline+
3322 "stat(f,value={<f.name>}) ::= \"x=<value>; // <f.name>\""+newline
3323 ;
3324 StringTemplateGroup group =
3325 new StringTemplateGroup(new StringReader(templates));
3326 StringTemplate m = group.getInstanceOf("method");
3327 m.setAttribute("fields", new Field());
3328 String expecting = "x=parrt; // parrt";
3329 String result = m.toString();
3330 assertEquals(expecting, result);
3331 }
3332 */
3333
3334 public void testDefaultArgumentAsTemplate() throws Exception {
3335 String templates =
3336 "group test;" +newline+
3337 "method(name,size) ::= <<"+newline+
3338 "<stat(...)>" +newline+
3339 ">>"+newline+
3340 "stat(name,value={<name>}) ::= \"x=<value>; // <name>\""+newline
3341 ;
3342 StringTemplateGroup group =
3343 new StringTemplateGroup(new StringReader(templates));
3344 StringTemplate b = group.getInstanceOf("method");
3345 b.setAttribute("name", "foo");
3346 b.setAttribute("size", "2");
3347 String expecting = "x=foo; // foo";
3348 String result = b.toString();
3349 //System.err.println("result='"+result+"'");
3350 assertEquals(expecting, result);
3351 }
3352
3353 public void testDefaultArgumentAsTemplate2() throws Exception {
3354 String templates =
3355 "group test;" +newline+
3356 "method(name,size) ::= <<"+newline+
3357 "<stat(...)>" +newline+
3358 ">>"+newline+
3359 "stat(name,value={ [<name>] }) ::= \"x=<value>; // <name>\""+newline
3360 ;
3361 StringTemplateGroup group =
3362 new StringTemplateGroup(new StringReader(templates));
3363 StringTemplate b = group.getInstanceOf("method");
3364 b.setAttribute("name", "foo");
3365 b.setAttribute("size", "2");
3366 String expecting = "x= [foo] ; // foo";
3367 String result = b.toString();
3368 //System.err.println("result='"+result+"'");
3369 assertEquals(expecting, result);
3370 }
3371
3372 public void testDoNotUseDefaultArgument() throws Exception {
3373 String templates =
3374 "group test;" +newline+
3375 "method(name) ::= <<"+newline+
3376 "<stat(value=\"34\",...)>" +newline+
3377 ">>"+newline+
3378 "stat(name,value=\"99\") ::= \"x=<value>; // <name>\""+newline
3379 ;
3380 StringTemplateGroup group =
3381 new StringTemplateGroup(new StringReader(templates));
3382 StringTemplate b = group.getInstanceOf("method");
3383 b.setAttribute("name", "foo");
3384 String expecting = "x=34; // foo";
3385 String result = b.toString();
3386 assertEquals(expecting, result);
3387 }
3388
3389 public void testDefaultArgumentInParensToEvalEarly() throws Exception {
3390 class Counter {
3391 int n = 0;
3392 public String toString() { return String.valueOf(n++); }
3393 }
3394 String templates =
3395 "group test;" +newline+
3396 "A(x) ::= \"<B()>\""+newline+
3397 "B(y={<(x)>}) ::= \"<y> <x> <x> <y>\""+newline
3398 ;
3399 StringTemplateGroup group =
3400 new StringTemplateGroup(new StringReader(templates));
3401 StringTemplate b = group.getInstanceOf("A");
3402 b.setAttribute("x", new Counter());
3403 String expecting = "0 1 2 0";
3404 String result = b.toString();
3405 //System.err.println("result='"+result+"'");
3406 assertEquals(expecting, result);
3407 }
3408
3409 public void testArgumentsAsTemplates() throws Exception {
3410 String templates =
3411 "group test;" +newline+
3412 "method(name,size) ::= <<"+newline+
3413 "<stat(value={<size>})>" +newline+
3414 ">>"+newline+
3415 "stat(value) ::= \"x=<value>;\""+newline
3416 ;
3417 StringTemplateGroup group =
3418 new StringTemplateGroup(new StringReader(templates));
3419 StringTemplate b = group.getInstanceOf("method");
3420 b.setAttribute("name", "foo");
3421 b.setAttribute("size", "34");
3422 String expecting = "x=34;";
3423 String result = b.toString();
3424 assertEquals(expecting, result);
3425 }
3426
3427 public void testTemplateArgumentEvaluatedInSurroundingContext() throws Exception {
3428 String templates =
3429 "group test;" +newline+
3430 "file(m,size) ::= \"<m>\""+newline+
3431 "method(name) ::= <<"+newline+
3432 "<stat(value={<size>.0})>" +newline+
3433 ">>"+newline+
3434 "stat(value) ::= \"x=<value>;\""+newline
3435 ;
3436 StringTemplateGroup group =
3437 new StringTemplateGroup(new StringReader(templates));
3438 StringTemplate f = group.getInstanceOf("file");
3439 f.setAttribute("size", "34");
3440 StringTemplate m = group.getInstanceOf("method");
3441 m.setAttribute("name", "foo");
3442 f.setAttribute("m", m);
3443 String expecting = "x=34.0;";
3444 String result = m.toString();
3445 assertEquals(expecting, result);
3446 }
3447
3448 public void testArgumentsAsTemplatesDefaultDelimiters() throws Exception {
3449 String templates =
3450 "group test;" +newline+
3451 "method(name,size) ::= <<"+newline+
3452 "$stat(value={$size$})$" +newline+
3453 ">>"+newline+
3454 "stat(value) ::= \"x=$value$;\""+newline
3455 ;
3456 StringTemplateGroup group =
3457 new StringTemplateGroup(new StringReader(templates),
3458 DefaultTemplateLexer.class);
3459 StringTemplate b = group.getInstanceOf("method");
3460 b.setAttribute("name", "foo");
3461 b.setAttribute("size", "34");
3462 String expecting = "x=34;";
3463 String result = b.toString();
3464 assertEquals(expecting, result);
3465 }
3466
3467 public void testDefaultArgsWhenNotInvoked() throws Exception {
3468 String templates =
3469 "group test;" +newline+
3470 "b(name=\"foo\") ::= \".<name>.\""+newline
3471 ;
3472 StringTemplateGroup group =
3473 new StringTemplateGroup(new StringReader(templates));
3474 StringTemplate b = group.getInstanceOf("b");
3475 String expecting = ".foo.";
3476 String result = b.toString();
3477 assertEquals(expecting, result);
3478 }
3479
3480 public class DateRenderer implements AttributeRenderer {
3481 public String toString(Object o) {
3482 SimpleDateFormat f = new SimpleDateFormat ("yyyy.MM.dd");
3483 return f.format(((Calendar)o).getTime());
3484 }
3485 public String toString(Object o, String formatString) {
3486 return toString(o);
3487 }
3488 }
3489
3490 public class DateRenderer2 implements AttributeRenderer {
3491 public String toString(Object o) {
3492 SimpleDateFormat f = new SimpleDateFormat ("MM/dd/yyyy");
3493 return f.format(((Calendar)o).getTime());
3494 }
3495 public String toString(Object o, String formatString) {
3496 return toString(o);
3497 }
3498 }
3499
3500 public class DateRenderer3 implements AttributeRenderer {
3501 public String toString(Object o) {
3502 SimpleDateFormat f = new SimpleDateFormat ("MM/dd/yyyy");
3503 return f.format(((Calendar)o).getTime());
3504 }
3505 public String toString(Object o, String formatString) {
3506 SimpleDateFormat f = new SimpleDateFormat (formatString);
3507 return f.format(((Calendar)o).getTime());
3508 }
3509 }
3510
3511 public class StringRenderer implements AttributeRenderer {
3512 public String toString(Object o) {
3513 return (String)o;
3514 }
3515 public String toString(Object o, String formatString) {
3516 if ( formatString.equals("upper") ) {
3517 return ((String)o).toUpperCase();
3518 }
3519 return toString(o);
3520 }
3521 }
3522
3523 public void testRendererForST() throws Exception {
3524 StringTemplate st =new StringTemplate(
3525 "date: <created>",
3526 AngleBracketTemplateLexer.class);
3527 st.setAttribute("created",
3528 new GregorianCalendar(2005, 07-1, 05));
3529 st.registerRenderer(GregorianCalendar.class, new DateRenderer());
3530 String expecting = "date: 2005.07.05";
3531 String result = st.toString();
3532 assertEquals(expecting, result);
3533 }
3534
3535 public void testRendererWithFormat() throws Exception {
3536 StringTemplate st =new StringTemplate(
3537 "date: <created; format=\"yyyy.MM.dd\">",
3538 AngleBracketTemplateLexer.class);
3539 st.setAttribute("created",
3540 new GregorianCalendar(2005, 07-1, 05));
3541 st.registerRenderer(GregorianCalendar.class, new DateRenderer3());
3542 String expecting = "date: 2005.07.05";
3543 String result = st.toString();
3544 assertEquals(expecting, result);
3545 }
3546
3547 public void testRendererWithFormatAndList() throws Exception {
3548 StringTemplate st =new StringTemplate(
3549 "The names: <names; format=\"upper\">",
3550 AngleBracketTemplateLexer.class);
3551 st.setAttribute("names", "ter");
3552 st.setAttribute("names", "tom");
3553 st.setAttribute("names", "sriram");
3554 st.registerRenderer(String.class, new StringRenderer());
3555 String expecting = "The names: TERTOMSRIRAM";
3556 String result = st.toString();
3557 assertEquals(expecting, result);
3558 }
3559
3560 public void testRendererWithFormatAndSeparator() throws Exception {
3561 StringTemplate st =new StringTemplate(
3562 "The names: <names; separator=\" and \", format=\"upper\">",
3563 AngleBracketTemplateLexer.class);
3564 st.setAttribute("names", "ter");
3565 st.setAttribute("names", "tom");
3566 st.setAttribute("names", "sriram");
3567 st.registerRenderer(String.class, new StringRenderer());
3568 String expecting = "The names: TER and TOM and SRIRAM";
3569 String result = st.toString();
3570 assertEquals(expecting, result);
3571 }
3572
3573 public void testRendererWithFormatAndSeparatorAndNull() throws Exception {
3574 StringTemplate st =new StringTemplate(
3575 "The names: <names; separator=\" and \", null=\"n/a\", format=\"upper\">",
3576 AngleBracketTemplateLexer.class);
3577 List names = new ArrayList();
3578 names.add("ter");
3579 names.add(null);
3580 names.add("sriram");
3581 st.setAttribute("names", names);
3582 st.registerRenderer(String.class, new StringRenderer());
3583 String expecting = "The names: TER and N/A and SRIRAM";
3584 String result = st.toString();
3585 assertEquals(expecting, result);
3586 }
3587
3588 public void testEmbeddedRendererSeesEnclosing() throws Exception {
3589 // st is embedded in outer; set renderer on outer, st should
3590 // still see it.
3591 StringTemplate outer =new StringTemplate(
3592 "X: <x>",
3593 AngleBracketTemplateLexer.class);
3594 StringTemplate st =new StringTemplate(
3595 "date: <created>",
3596 AngleBracketTemplateLexer.class);
3597 st.setAttribute("created",
3598 new GregorianCalendar(2005, 07-1, 05));
3599 outer.setAttribute("x", st);
3600 outer.registerRenderer(GregorianCalendar.class, new DateRenderer());
3601 String expecting = "X: date: 2005.07.05";
3602 String result = outer.toString();
3603 assertEquals(expecting, result);
3604 }
3605
3606 public void testRendererForGroup() throws Exception {
3607 String templates =
3608 "group test;" +newline+
3609 "dateThing(created) ::= \"date: <created>\""+newline
3610 ;
3611 StringTemplateGroup group =
3612 new StringTemplateGroup(new StringReader(templates));
3613 StringTemplate st = group.getInstanceOf("dateThing");
3614 st.setAttribute("created",
3615 new GregorianCalendar(2005, 07-1, 05));
3616 group.registerRenderer(GregorianCalendar.class, new DateRenderer());
3617 String expecting = "date: 2005.07.05";
3618 String result = st.toString();
3619 assertEquals(expecting, result);
3620 }
3621
3622 public void testOverriddenRenderer() throws Exception {
3623 String templates =
3624 "group test;" +newline+
3625 "dateThing(created) ::= \"date: <created>\""+newline
3626 ;
3627 StringTemplateGroup group =
3628 new StringTemplateGroup(new StringReader(templates));
3629 StringTemplate st = group.getInstanceOf("dateThing");
3630 st.setAttribute("created",
3631 new GregorianCalendar(2005, 07-1, 05));
3632 group.registerRenderer(GregorianCalendar.class, new DateRenderer());
3633 st.registerRenderer(GregorianCalendar.class, new DateRenderer2());
3634 String expecting = "date: 07/05/2005";
3635 String result = st.toString();
3636 assertEquals(expecting, result);
3637 }
3638
3639 public void testMap() throws Exception {
3640 String templates =
3641 "group test;" +newline+
3642 "typeInit ::= [\"int\":\"0\", \"float\":\"0.0\"] "+newline+
3643 "var(type,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3644 ;
3645 StringTemplateGroup group =
3646 new StringTemplateGroup(new StringReader(templates));
3647 StringTemplate st = group.getInstanceOf("var");
3648 st.setAttribute("type", "int");
3649 st.setAttribute("name", "x");
3650 String expecting = "int x = 0;";
3651 String result = st.toString();
3652 assertEquals(expecting, result);
3653 }
3654
3655 public void testMapValuesAreTemplates() throws Exception {
3656 String templates =
3657 "group test;" +newline+
3658 "typeInit ::= [\"int\":\"0<w>\", \"float\":\"0.0<w>\"] "+newline+
3659 "var(type,w,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3660 ;
3661 StringTemplateGroup group =
3662 new StringTemplateGroup(new StringReader(templates));
3663 StringTemplate st = group.getInstanceOf("var");
3664 st.setAttribute("w", "L");
3665 st.setAttribute("type", "int");
3666 st.setAttribute("name", "x");
3667 String expecting = "int x = 0L;";
3668 String result = st.toString();
3669 assertEquals(expecting, result);
3670 }
3671
3672 public void testMapKeyLookupViaTemplate() throws Exception {
3673 // ST doesn't do a toString on .(key) values, it just uses the value
3674 // of key rather than key itself as the key. But, if you compute a
3675 // key via a template
3676 String templates =
3677 "group test;" +newline+
3678 "typeInit ::= [\"int\":\"0<w>\", \"float\":\"0.0<w>\"] "+newline+
3679 "var(type,w,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3680 ;
3681 StringTemplateGroup group =
3682 new StringTemplateGroup(new StringReader(templates));
3683 StringTemplate st = group.getInstanceOf("var");
3684 st.setAttribute("w", "L");
3685 st.setAttribute("type", new StringTemplate("int"));
3686 st.setAttribute("name", "x");
3687 String expecting = "int x = 0L;";
3688 String result = st.toString();
3689 assertEquals(expecting, result);
3690 }
3691
3692 public void testMapMissingDefaultValueIsEmpty() throws Exception {
3693 String templates =
3694 "group test;" +newline+
3695 "typeInit ::= [\"int\":\"0\", \"float\":\"0.0\"] "+newline+
3696 "var(type,w,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3697 ;
3698 StringTemplateGroup group =
3699 new StringTemplateGroup(new StringReader(templates));
3700 StringTemplate st = group.getInstanceOf("var");
3701 st.setAttribute("w", "L");
3702 st.setAttribute("type", "double"); // double not in typeInit map
3703 st.setAttribute("name", "x");
3704 String expecting = "double x = ;"; // weird, but tests default value is key
3705 String result = st.toString();
3706 assertEquals(expecting, result);
3707 }
3708
3709 public void testMapHiddenByFormalArg() throws Exception {
3710 String templates =
3711 "group test;" +newline+
3712 "typeInit ::= [\"int\":\"0\", \"float\":\"0.0\"] "+newline+
3713 "var(typeInit,type,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3714 ;
3715 StringTemplateGroup group =
3716 new StringTemplateGroup(new StringReader(templates));
3717 StringTemplate st = group.getInstanceOf("var");
3718 st.setAttribute("type", "int");
3719 st.setAttribute("name", "x");
3720 String expecting = "int x = ;";
3721 String result = st.toString();
3722 assertEquals(expecting, result);
3723 }
3724
3725 public void testMapEmptyValueAndAngleBracketStrings() throws Exception {
3726 String templates =
3727 "group test;" +newline+
3728 "typeInit ::= [\"int\":\"0\", \"float\":, \"double\":<<0.0L>>] "+newline+
3729 "var(type,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3730 ;
3731 StringTemplateGroup group =
3732 new StringTemplateGroup(new StringReader(templates));
3733 StringTemplate st = group.getInstanceOf("var");
3734 st.setAttribute("type", "float");
3735 st.setAttribute("name", "x");
3736 String expecting = "float x = ;";
3737 String result = st.toString();
3738 assertEquals(expecting, result);
3739 }
3740
3741 public void testMapDefaultValue() throws Exception {
3742 String templates =
3743 "group test;" +newline+
3744 "typeInit ::= [\"int\":\"0\", default:\"null\"] "+newline+
3745 "var(type,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3746 ;
3747 StringTemplateGroup group =
3748 new StringTemplateGroup(new StringReader(templates));
3749 StringTemplate st = group.getInstanceOf("var");
3750 st.setAttribute("type", "UserRecord");
3751 st.setAttribute("name", "x");
3752 String expecting = "UserRecord x = null;";
3753 String result = st.toString();
3754 assertEquals(expecting, result);
3755 }
3756
3757 public void testMapEmptyDefaultValue() throws Exception {
3758 String templates =
3759 "group test;" +newline+
3760 "typeInit ::= [\"int\":\"0\", default:] "+newline+
3761 "var(type,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3762 ;
3763 StringTemplateGroup group =
3764 new StringTemplateGroup(new StringReader(templates));
3765 StringTemplate st = group.getInstanceOf("var");
3766 st.setAttribute("type", "UserRecord");
3767 st.setAttribute("name", "x");
3768 String expecting = "UserRecord x = ;";
3769 String result = st.toString();
3770 assertEquals(expecting, result);
3771 }
3772
3773 public void testMapDefaultValueIsKey() throws Exception {
3774 String templates =
3775 "group test;" +newline+
3776 "typeInit ::= [\"int\":\"0\", default:key] "+newline+
3777 "var(type,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3778 ;
3779 StringTemplateGroup group =
3780 new StringTemplateGroup(new StringReader(templates));
3781 StringTemplate st = group.getInstanceOf("var");
3782 st.setAttribute("type", "UserRecord");
3783 st.setAttribute("name", "x");
3784 String expecting = "UserRecord x = UserRecord;";
3785 String result = st.toString();
3786 assertEquals(expecting, result);
3787 }
3788
3789 /**
3790 * Test that a map can have only the default entry.
3791 * <p>
3792 * Bug ref: JIRA bug ST-15 (Fixed)
3793 */
3794 public void testMapDefaultStringAsKey() throws Exception {
3795 String templates =
3796 "group test;" +newline+
3797 "typeInit ::= [\"default\":\"foo\"] "+newline+
3798 "var(type,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3799 ;
3800 StringTemplateGroup group =
3801 new StringTemplateGroup(new StringReader(templates));
3802 StringTemplate st = group.getInstanceOf("var");
3803 st.setAttribute("type", "default");
3804 st.setAttribute("name", "x");
3805 String expecting = "default x = foo;";
3806 String result = st.toString();
3807 assertEquals(expecting, result);
3808 }
3809
3810 /**
3811 * Test that a map can return a <b>string</b> with the word: default.
3812 * <p>
3813 * Bug ref: JIRA bug ST-15 (Fixed)
3814 */
3815 public void testMapDefaultIsDefaultString() throws Exception {
3816 String templates =
3817 "group test;" +newline+
3818 "map ::= [default: \"default\"] "+newline+
3819 "t1() ::= \"<map.(1)>\""+newline
3820 ;
3821 StringTemplateGroup group =
3822 new StringTemplateGroup(new StringReader(templates));
3823 StringTemplate st = group.getInstanceOf("t1");
3824 String expecting = "default";
3825 String result = st.toString();
3826 assertEquals(expecting, result);
3827 }
3828
3829 public void testMapViaEnclosingTemplates() throws Exception {
3830 String templates =
3831 "group test;" +newline+
3832 "typeInit ::= [\"int\":\"0\", \"float\":\"0.0\"] "+newline+
3833 "intermediate(type,name) ::= \"<var(...)>\""+newline+
3834 "var(type,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3835 ;
3836 StringTemplateGroup group =
3837 new StringTemplateGroup(new StringReader(templates));
3838 StringTemplate st = group.getInstanceOf("intermediate");
3839 st.setAttribute("type", "int");
3840 st.setAttribute("name", "x");
3841 String expecting = "int x = 0;";
3842 String result = st.toString();
3843 assertEquals(expecting, result);
3844 }
3845
3846 public void testMapViaEnclosingTemplates2() throws Exception {
3847 String templates =
3848 "group test;" +newline+
3849 "typeInit ::= [\"int\":\"0\", \"float\":\"0.0\"] "+newline+
3850 "intermediate(stuff) ::= \"<stuff>\""+newline+
3851 "var(type,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3852 ;
3853 StringTemplateGroup group =
3854 new StringTemplateGroup(new StringReader(templates));
3855 StringTemplate interm = group.getInstanceOf("intermediate");
3856 StringTemplate var = group.getInstanceOf("var");
3857 var.setAttribute("type", "int");
3858 var.setAttribute("name", "x");
3859 interm.setAttribute("stuff", var);
3860 String expecting = "int x = 0;";
3861 String result = interm.toString();
3862 assertEquals(expecting, result);
3863 }
3864
3865 public void testEmptyGroupTemplate() throws Exception {
3866 String templates =
3867 "group test;" +newline+
3868 "foo() ::= \"\""+newline
3869 ;
3870 StringTemplateGroup group =
3871 new StringTemplateGroup(new StringReader(templates));
3872 StringTemplate a = group.getInstanceOf("foo");
3873 String expecting = "";
3874 String result = a.toString();
3875 assertEquals(expecting, result);
3876 }
3877
3878 public void testEmptyStringAndEmptyAnonTemplateAsParameterUsingAngleBracketLexer() throws Exception {
3879 String templates =
3880 "group test;" +newline+
3881 "top() ::= <<<x(a=\"\", b={})\\>>>"+newline+
3882 "x(a,b) ::= \"a=<a>, b=<b>\""+newline;
3883 ;
3884 StringTemplateGroup group =
3885 new StringTemplateGroup(new StringReader(templates));
3886 StringTemplate a = group.getInstanceOf("top");
3887 String expecting = "a=, b=";
3888 String result = a.toString();
3889 assertEquals(expecting, result);
3890 }
3891
3892 public void testEmptyStringAndEmptyAnonTemplateAsParameterUsingDollarLexer() throws Exception {
3893 String templates =
3894 "group test;" +newline+
3895 "top() ::= <<$x(a=\"\", b={})$>>"+newline+
3896 "x(a,b) ::= \"a=$a$, b=$b$\""+newline;
3897 ;
3898 StringTemplateGroup group =
3899 new StringTemplateGroup(new StringReader(templates),
3900 DefaultTemplateLexer.class);
3901 StringTemplate a = group.getInstanceOf("top");
3902 String expecting = "a=, b=";
3903 String result = a.toString();
3904 assertEquals(expecting, result);
3905 }
3906
3907 /**
3908 * FIXME: Dannish does not work if typed directly in with default file
3909 * encoding on windows. The character needs to be escaped as bellow.
3910 * Please correct to escape the correct charcter.
3911 */
3912 public void test8BitEuroChars() throws Exception {
3913 StringTemplate e = new StringTemplate(
3914 "Danish: \u0143 char"
3915 );
3916 e = e.getInstanceOf();
3917 String expecting = "Danish: \u0143 char";
3918 assertEquals(expecting, e.toString());
3919 }
3920
3921 public void test16BitUnicodeChar() throws Exception {
3922 StringTemplate e = new StringTemplate(
3923 "DINGBAT CIRCLED SANS-SERIF DIGIT ONE: \u2780"
3924 );
3925 e = e.getInstanceOf();
3926 String expecting = "DINGBAT CIRCLED SANS-SERIF DIGIT ONE: \u2780";
3927 assertEquals(expecting, e.toString());
3928 }
3929
3930 public void testFirstOp() throws Exception {
3931 StringTemplate e = new StringTemplate(
3932 "$first(names)$"
3933 );
3934 e = e.getInstanceOf();
3935 e.setAttribute("names", "Ter");
3936 e.setAttribute("names", "Tom");
3937 e.setAttribute("names", "Sriram");
3938 String expecting = "Ter";
3939 assertEquals(expecting, e.toString());
3940 }
3941
3942 public void testTruncOp() throws Exception {
3943 StringTemplate e = new StringTemplate(
3944 "$trunc(names); separator=\", \"$"
3945 );
3946 e = e.getInstanceOf();
3947 e.setAttribute("names", "Ter");
3948 e.setAttribute("names", "Tom");
3949 e.setAttribute("names", "Sriram");
3950 String expecting = "Ter, Tom";
3951 assertEquals(expecting, e.toString());
3952 }
3953
3954 public void testRestOp() throws Exception {
3955 StringTemplate e = new StringTemplate(
3956 "$rest(names); separator=\", \"$"
3957 );
3958 e = e.getInstanceOf();
3959 e.setAttribute("names", "Ter");
3960 e.setAttribute("names", "Tom");
3961 e.setAttribute("names", "Sriram");
3962 String expecting = "Tom, Sriram";
3963 assertEquals(expecting, e.toString());
3964 }
3965
3966 public void testRestOpEmptyList() throws Exception {
3967 StringTemplate e = new StringTemplate(
3968 "$rest(names); separator=\", \"$"
3969 );
3970 e = e.getInstanceOf();
3971 e.setAttribute("names", new ArrayList());
3972 String expecting = "";
3973 assertEquals(expecting, e.toString());
3974 }
3975
3976 public void testReUseOfRestResult() throws Exception {
3977 String templates =
3978 "group test;" +newline+
3979 "a(names) ::= \"<b(rest(names))>\""+newline+
3980 "b(x) ::= \"<x>, <x>\""+newline
3981 ;
3982 StringTemplateGroup group =
3983 new StringTemplateGroup(new StringReader(templates));
3984 StringTemplate e = group.getInstanceOf("a");
3985 List names = new ArrayList();
3986 names.add("Ter");
3987 names.add("Tom");
3988 e.setAttribute("names", names);
3989 String expecting = "Tom, Tom";
3990 assertEquals(expecting, e.toString());
3991 }
3992
3993 public void testLastOp() throws Exception {
3994 StringTemplate e = new StringTemplate(
3995 "$last(names)$"
3996 );
3997 e = e.getInstanceOf();
3998 e.setAttribute("names", "Ter");
3999 e.setAttribute("names", "Tom");
4000 e.setAttribute("names", "Sriram");
4001 String expecting = "Sriram";
4002 assertEquals(expecting, e.toString());
4003 }
4004
4005 public void testCombinedOp() throws Exception {
4006 // replace first of yours with first of mine
4007 StringTemplate e = new StringTemplate(
4008 "$[first(mine),rest(yours)]; separator=\", \"$"
4009 );
4010 e = e.getInstanceOf();
4011 e.setAttribute("mine", "1");
4012 e.setAttribute("mine", "2");
4013 e.setAttribute("mine", "3");
4014 e.setAttribute("yours", "a");
4015 e.setAttribute("yours", "b");
4016 String expecting = "1, b";
4017 assertEquals(expecting, e.toString());
4018 }
4019
4020 public void testCatListAndSingleAttribute() throws Exception {
4021 // replace first of yours with first of mine
4022 StringTemplate e = new StringTemplate(
4023 "$[mine,yours]; separator=\", \"$"
4024 );
4025 e = e.getInstanceOf();
4026 e.setAttribute("mine", "1");
4027 e.setAttribute("mine", "2");
4028 e.setAttribute("mine", "3");
4029 e.setAttribute("yours", "a");
4030 String expecting = "1, 2, 3, a";
4031 assertEquals(expecting, e.toString());
4032 }
4033
4034 public void testReUseOfCat() throws Exception {
4035 String templates =
4036 "group test;" +newline+
4037 "a(mine,yours) ::= \"<b([mine,yours])>\""+newline+
4038 "b(x) ::= \"<x>, <x>\""+newline
4039 ;
4040 StringTemplateGroup group =
4041 new StringTemplateGroup(new StringReader(templates));
4042 StringTemplate e = group.getInstanceOf("a");
4043 List mine = new ArrayList();
4044 mine.add("Ter");
4045 mine.add("Tom");
4046 e.setAttribute("mine", mine);
4047 List yours = new ArrayList();
4048 yours.add("Foo");
4049 e.setAttribute("yours", yours);
4050 String expecting = "TerTomFoo, TerTomFoo";
4051 assertEquals(expecting, e.toString());
4052 }
4053
4054 public void testCatListAndEmptyAttributes() throws Exception {
4055 // + is overloaded to be cat strings and cat lists so the
4056 // two operands (from left to right) determine which way it
4057 // goes. In this case, x+mine is a list so everything from their
4058 // to the right becomes list cat.
4059 StringTemplate e = new StringTemplate(
4060 "$[x,mine,y,yours,z]; separator=\", \"$"
4061 );
4062 e = e.getInstanceOf();
4063 e.setAttribute("mine", "1");
4064 e.setAttribute("mine", "2");
4065 e.setAttribute("mine", "3");
4066 e.setAttribute("yours", "a");
4067 String expecting = "1, 2, 3, a";
4068 assertEquals(expecting, e.toString());
4069 }
4070
4071 public void testNestedOp() throws Exception {
4072 StringTemplate e = new StringTemplate(
4073 "$first(rest(names))$" // gets 2nd element
4074 );
4075 e = e.getInstanceOf();
4076 e.setAttribute("names", "Ter");
4077 e.setAttribute("names", "Tom");
4078 e.setAttribute("names", "Sriram");
4079 String expecting = "Tom";
4080 assertEquals(expecting, e.toString());
4081 }
4082
4083 public void testFirstWithOneAttributeOp() throws Exception {
4084 StringTemplate e = new StringTemplate(
4085 "$first(names)$"
4086 );
4087 e = e.getInstanceOf();
4088 e.setAttribute("names", "Ter");
4089 String expecting = "Ter";
4090 assertEquals(expecting, e.toString());
4091 }
4092
4093 public void testLastWithOneAttributeOp() throws Exception {
4094 StringTemplate e = new StringTemplate(
4095 "$last(names)$"
4096 );
4097 e = e.getInstanceOf();
4098 e.setAttribute("names", "Ter");
4099 String expecting = "Ter";
4100 assertEquals(expecting, e.toString());
4101 }
4102
4103 public void testLastWithLengthOneListAttributeOp() throws Exception {
4104 StringTemplate e = new StringTemplate(
4105 "$last(names)$"
4106 );
4107 e = e.getInstanceOf();
4108 e.setAttribute("names", new ArrayList() {{add("Ter");}});
4109 String expecting = "Ter";
4110 assertEquals(expecting, e.toString());
4111 }
4112
4113 public void testRestWithOneAttributeOp() throws Exception {
4114 StringTemplate e = new StringTemplate(
4115 "$rest(names)$"
4116 );
4117 e = e.getInstanceOf();
4118 e.setAttribute("names", "Ter");
4119 String expecting = "";
4120 assertEquals(expecting, e.toString());
4121 }
4122
4123 public void testRestWithLengthOneListAttributeOp() throws Exception {
4124 StringTemplate e = new StringTemplate(
4125 "$rest(names)$"
4126 );
4127 e = e.getInstanceOf();
4128 e.setAttribute("names", new ArrayList() {{add("Ter");}});
4129 String expecting = "";
4130 assertEquals(expecting, e.toString());
4131 }
4132
4133 public void testRepeatedRestOp() throws Exception {
4134 StringTemplate e = new StringTemplate(
4135 "$rest(names)$, $rest(names)$" // gets 2nd element
4136 );
4137 e = e.getInstanceOf();
4138 e.setAttribute("names", "Ter");
4139 e.setAttribute("names", "Tom");
4140 String expecting = "Tom, Tom";
4141 assertEquals(expecting, e.toString());
4142 }
4143
4144 /** If an iterator is sent into ST, it must be cannot be reset after each
4145 * use so repeated refs yield empty values. This would
4146 * work if we passed in a List not an iterator. Avoid sending in iterators
4147 * if you ref it twice.
4148 */
4149 public void testRepeatedIteratedAttrFromArg() throws Exception {
4150 String templates =
4151 "group test;" +newline+
4152 "root(names) ::= \"$other(names)$\""+newline+
4153 "other(x) ::= \"$x$, $x$\""+newline
4154 ;
4155 StringTemplateGroup group =
4156 new StringTemplateGroup(new StringReader(templates),
4157 DefaultTemplateLexer.class);
4158 StringTemplate e = group.getInstanceOf("root");
4159 List names = new ArrayList();
4160 names.add("Ter");
4161 names.add("Tom");
4162 e.setAttribute("names", names.iterator());
4163 String expecting = "TerTom, "; // This does not give TerTom twice!!
4164 assertEquals(expecting, e.toString());
4165 }
4166
4167 /** FIXME: BUG! Iterator is not reset from first to second $x$
4168 * Either reset the iterator or pass an attribute that knows to get
4169 * the iterator each time. Seems like first, tail do not
4170 * have same problem as they yield objects.
4171 *
4172 * Maybe make a RestIterator like I have CatIterator.
4173 */
4174 /*
4175 public void testRepeatedRestOpAsArg() throws Exception {
4176 String templates =
4177 "group test;" +newline+
4178 "root(names) ::= \"$other(rest(names))$\""+newline+
4179 "other(x) ::= \"$x$, $x$\""+newline
4180 ;
4181 StringTemplateGroup group =
4182 new StringTemplateGroup(new StringReader(templates),
4183 DefaultTemplateLexer.class);
4184 StringTemplate e = group.getInstanceOf("root");
4185 e.setAttribute("names", "Ter");
4186 e.setAttribute("names", "Tom");
4187 String expecting = "Tom, Tom";
4188 assertEquals(expecting, e.toString());
4189 }
4190 */
4191
4192 public void testIncomingLists() throws Exception {
4193 StringTemplate e = new StringTemplate(
4194 "$rest(names)$, $rest(names)$" // gets 2nd element
4195 );
4196 e = e.getInstanceOf();
4197 e.setAttribute("names", "Ter");
4198 e.setAttribute("names", "Tom");
4199 String expecting = "Tom, Tom";
4200 assertEquals(expecting, e.toString());
4201 }
4202
4203 public void testIncomingListsAreNotModified() throws Exception {
4204 StringTemplate e = new StringTemplate(
4205 "$names; separator=\", \"$" // gets 2nd element
4206 );
4207 e = e.getInstanceOf();
4208 List names = new ArrayList();
4209 names.add("Ter");
4210 names.add("Tom");
4211 e.setAttribute("names", names);
4212 e.setAttribute("names", "Sriram");
4213 String expecting = "Ter, Tom, Sriram";
4214 assertEquals(expecting, e.toString());
4215
4216 assertEquals(names.size(), 2);
4217 }
4218
4219 public void testIncomingListsAreNotModified2() throws Exception {
4220 StringTemplate e = new StringTemplate(
4221 "$names; separator=\", \"$" // gets 2nd element
4222 );
4223 e = e.getInstanceOf();
4224 List names = new ArrayList();
4225 names.add("Ter");
4226 names.add("Tom");
4227 e.setAttribute("names", "Sriram"); // single element first now
4228 e.setAttribute("names", names);
4229 String expecting = "Sriram, Ter, Tom";
4230 assertEquals(expecting, e.toString());
4231
4232 assertEquals(names.size(), 2);
4233 }
4234
4235 public void testIncomingArraysAreOk() throws Exception {
4236 StringTemplate e = new StringTemplate(
4237 "$names; separator=\", \"$" // gets 2nd element
4238 );
4239 e = e.getInstanceOf();
4240 e.setAttribute("names", new String[] {"Ter","Tom"});
4241 e.setAttribute("names", "Sriram");
4242 String expecting = "Ter, Tom, Sriram";
4243 assertEquals(expecting, e.toString());
4244 }
4245
4246 public void testMultipleRefsToListAttribute() throws Exception {
4247 String templates =
4248 "group test;" +newline+
4249 "f(x) ::= \"<x> <x>\""+newline
4250 ;
4251 StringTemplateGroup group =
4252 new StringTemplateGroup(new StringReader(templates));
4253 StringTemplate e = group.getInstanceOf("f");
4254 e.setAttribute("x", "Ter");
4255 e.setAttribute("x", "Tom");
4256 String expecting = "TerTom TerTom";
4257 assertEquals(expecting, e.toString());
4258 }
4259
4260 public void testApplyTemplateWithSingleFormalArgs() throws Exception {
4261 String templates =
4262 "group test;" +newline+
4263 "test(names) ::= <<<names:bold(item=it); separator=\", \"> >>"+newline+
4264 "bold(item) ::= <<*<item>*>>"+newline
4265 ;
4266 StringTemplateGroup group =
4267 new StringTemplateGroup(new StringReader(templates));
4268 StringTemplate e = group.getInstanceOf("test");
4269 e.setAttribute("names", "Ter");
4270 e.setAttribute("names", "Tom");
4271 String expecting = "*Ter*, *Tom* ";
4272 String result = e.toString();
4273 assertEquals(expecting, result);
4274 }
4275
4276 public void testApplyTemplateWithNoFormalArgs() throws Exception {
4277 String templates =
4278 "group test;" +newline+
4279 "test(names) ::= <<<names:bold(); separator=\", \"> >>"+newline+
4280 "bold() ::= <<*<it>*>>"+newline
4281 ;
4282 StringTemplateGroup group =
4283 new StringTemplateGroup(new StringReader(templates),
4284 AngleBracketTemplateLexer.class);
4285 StringTemplate e = group.getInstanceOf("test");
4286 e.setAttribute("names", "Ter");
4287 e.setAttribute("names", "Tom");
4288 String expecting = "*Ter*, *Tom* ";
4289 String result = e.toString();
4290 assertEquals(expecting, result);
4291 }
4292
4293 public void testAnonTemplateArgs() throws Exception {
4294 StringTemplate e = new StringTemplate(
4295 "$names:{n| $n$}; separator=\", \"$"
4296 );
4297 e = e.getInstanceOf();
4298 e.setAttribute("names", "Ter");
4299 e.setAttribute("names", "Tom");
4300 String expecting = "Ter, Tom";
4301 assertEquals(expecting, e.toString());
4302 }
4303
4304 public void testAnonTemplateWithArgHasNoITArg() throws Exception {
4305 StringTemplate e = new StringTemplate(
4306 "$names:{n| $n$:$it$}; separator=\", \"$"
4307 );
4308 e = e.getInstanceOf();
4309 e.setAttribute("names", "Ter");
4310 e.setAttribute("names", "Tom");
4311 String error = null;
4312 try {
4313 e.toString();
4314 }
4315 catch (NoSuchElementException nse) {
4316 error = nse.getMessage();
4317 }
4318 String expecting = "no such attribute: it in template context [anonymous anonymous]";
4319 assertEquals(error, expecting);
4320 }
4321
4322 public void testAnonTemplateArgs2() throws Exception {
4323 StringTemplate e = new StringTemplate(
4324 "$names:{n| .$n$.}:{ n | _$n$_}; separator=\", \"$"
4325 );
4326 e = e.getInstanceOf();
4327 e.setAttribute("names", "Ter");
4328 e.setAttribute("names", "Tom");
4329 String expecting = "_.Ter._, _.Tom._";
4330 assertEquals(expecting, e.toString());
4331 }
4332
4333 public void testFirstWithCatAttribute() throws Exception {
4334 StringTemplate e = new StringTemplate(
4335 "$first([names,phones])$"
4336 );
4337 e = e.getInstanceOf();
4338 e.setAttribute("names", "Ter");
4339 e.setAttribute("names", "Tom");
4340 e.setAttribute("phones", "1");
4341 e.setAttribute("phones", "2");
4342 String expecting = "Ter";
4343 assertEquals(expecting, e.toString());
4344 }
4345
4346 public void testFirstWithListOfMaps() throws Exception {
4347 StringTemplate e = new StringTemplate(
4348 "$first(maps).Ter$"
4349 );
4350 e = e.getInstanceOf();
4351 final Map m1 = new HashMap();
4352 final Map m2 = new HashMap();
4353 m1.put("Ter", "x5707");
4354 e.setAttribute("maps", m1);
4355 m2.put("Tom", "x5332");
4356 e.setAttribute("maps", m2);
4357 String expecting = "x5707";
4358 assertEquals(expecting, e.toString());
4359
4360 e = e.getInstanceOf();
4361 List list = new ArrayList() {{add(m1); add(m2);}};
4362 e.setAttribute("maps", list);
4363 expecting = "x5707";
4364 assertEquals(expecting, e.toString());
4365 }
4366
4367 // this FAILS!
4368 /*
4369 public void testFirstWithListOfMaps2() throws Exception {
4370 StringTemplate e = new StringTemplate(
4371 "$first(maps):{ m | $m.Ter$ }$"
4372 );
4373 final Map m1 = new HashMap();
4374 final Map m2 = new HashMap();
4375 m1.put("Ter", "x5707");
4376 e.setAttribute("maps", m1);
4377 m2.put("Tom", "x5332");
4378 e.setAttribute("maps", m2);
4379 String expecting = "x5707";
4380 assertEquals(expecting, e.toString());
4381
4382 e = e.getInstanceOf();
4383 List list = new ArrayList() {{add(m1); add(m2);}};
4384 e.setAttribute("maps", list);
4385 expecting = "x5707";
4386 assertEquals(expecting, e.toString());
4387 }
4388 */
4389 public void testJustCat() throws Exception {
4390 StringTemplate e = new StringTemplate(
4391 "$[names,phones]$"
4392 );
4393 e = e.getInstanceOf();
4394 e.setAttribute("names", "Ter");
4395 e.setAttribute("names", "Tom");
4396 e.setAttribute("phones", "1");
4397 e.setAttribute("phones", "2");
4398 String expecting = "TerTom12";
4399 assertEquals(expecting, e.toString());
4400 }
4401
4402 public void testCat2Attributes() throws Exception {
4403 StringTemplate e = new StringTemplate(
4404 "$[names,phones]; separator=\", \"$"
4405 );
4406 e = e.getInstanceOf();
4407 e.setAttribute("names", "Ter");
4408 e.setAttribute("names", "Tom");
4409 e.setAttribute("phones", "1");
4410 e.setAttribute("phones", "2");
4411 String expecting = "Ter, Tom, 1, 2";
4412 assertEquals(expecting, e.toString());
4413 }
4414
4415 public void testCat2AttributesWithApply() throws Exception {
4416 StringTemplate e = new StringTemplate(
4417 "$[names,phones]:{a|$a$.}$"
4418 );
4419 e = e.getInstanceOf();
4420 e.setAttribute("names", "Ter");
4421 e.setAttribute("names", "Tom");
4422 e.setAttribute("phones", "1");
4423 e.setAttribute("phones", "2");
4424 String expecting = "Ter.Tom.1.2.";
4425 assertEquals(expecting, e.toString());
4426 }
4427
4428 public void testCat3Attributes() throws Exception {
4429 StringTemplate e = new StringTemplate(
4430 "$[names,phones,salaries]; separator=\", \"$"
4431 );
4432 e = e.getInstanceOf();
4433 e.setAttribute("names", "Ter");
4434 e.setAttribute("names", "Tom");
4435 e.setAttribute("phones", "1");
4436 e.setAttribute("phones", "2");
4437 e.setAttribute("salaries", "big");
4438 e.setAttribute("salaries", "huge");
4439 String expecting = "Ter, Tom, 1, 2, big, huge";
4440 assertEquals(expecting, e.toString());
4441 }
4442
4443 public void testCatWithTemplateApplicationAsElement() throws Exception {
4444 StringTemplate e = new StringTemplate(
4445 "$[names:{$it$!},phones]; separator=\", \"$"
4446 );
4447 e = e.getInstanceOf();
4448 e.setAttribute("names", "Ter");
4449 e.setAttribute("names", "Tom");
4450 e.setAttribute("phones" , "1");
4451 e.setAttribute("phones", "2");
4452 String expecting = "Ter!, Tom!, 1, 2";
4453 assertEquals(expecting, e.toString());
4454 }
4455
4456 public void testCatWithIFAsElement() throws Exception {
4457 StringTemplate e = new StringTemplate(
4458 "$[{$if(names)$doh$endif$},phones]; separator=\", \"$"
4459 );
4460 e = e.getInstanceOf();
4461 e.setAttribute("names", "Ter");
4462 e.setAttribute("names", "Tom");
4463 e.setAttribute("phones" , "1");
4464 e.setAttribute("phones", "2");
4465 String expecting = "doh, 1, 2";
4466 assertEquals(expecting, e.toString());
4467 }
4468
4469 public void testCatWithNullTemplateApplicationAsElement() throws Exception {
4470 StringTemplate e = new StringTemplate(
4471 "$[names:{$it$!},\"foo\"]:{x}; separator=\", \"$"
4472 );
4473 e = e.getInstanceOf();
4474 e.setAttribute("phones", "1");
4475 e.setAttribute("phones", "2");
4476 String expecting = "x"; // only one since template application gives nothing
4477 assertEquals(expecting, e.toString());
4478 }
4479
4480 public void testCatWithNestedTemplateApplicationAsElement() throws Exception {
4481 StringTemplate e = new StringTemplate(
4482 "$[names, [\"foo\",\"bar\"]:{$it$!},phones]; separator=\", \"$"
4483 );
4484 e = e.getInstanceOf();
4485 e.setAttribute("names", "Ter");
4486 e.setAttribute("names", "Tom");
4487 e.setAttribute("phones", "1");
4488 e.setAttribute("phones", "2");
4489 String expecting = "Ter, Tom, foo!, bar!, 1, 2";
4490 assertEquals(expecting, e.toString());
4491 }
4492
4493 public void testListAsTemplateArgument() throws Exception {
4494 String templates =
4495 "group test;" +newline+
4496 "test(names,phones) ::= \"<foo([names,phones])>\""+newline+
4497 "foo(items) ::= \"<items:{a | *<a>*}>\""+newline
4498 ;
4499 StringTemplateGroup group =
4500 new StringTemplateGroup(new StringReader(templates),
4501 AngleBracketTemplateLexer.class);
4502 StringTemplate e = group.getInstanceOf("test");
4503 e.setAttribute("names", "Ter");
4504 e.setAttribute("names", "Tom");
4505 e.setAttribute("phones", "1");
4506 e.setAttribute("phones", "2");
4507 String expecting = "*Ter**Tom**1**2*";
4508 String result = e.toString();
4509 assertEquals(expecting, result);
4510 }
4511
4512 public void testSingleExprTemplateArgument() throws Exception {
4513 String templates =
4514 "group test;" +newline+
4515 "test(name) ::= \"<bold(name)>\""+newline+
4516 "bold(item) ::= \"*<item>*\""+newline
4517 ;
4518 StringTemplateGroup group =
4519 new StringTemplateGroup(new StringReader(templates),
4520 AngleBracketTemplateLexer.class);
4521 StringTemplate e = group.getInstanceOf("test");
4522 e.setAttribute("name", "Ter");
4523 String expecting = "*Ter*";
4524 String result = e.toString();
4525 assertEquals(expecting, result);
4526 }
4527
4528 public void testSingleExprTemplateArgumentInApply() throws Exception {
4529 // when you specify a single arg on a template application
4530 // it overrides the setting of the iterated value "it" to that
4531 // same single formal arg. Your arg hides the implicitly set "it".
4532 String templates =
4533 "group test;" +newline+
4534 "test(names,x) ::= \"<names:bold(x)>\""+newline+
4535 "bold(item) ::= \"*<item>*\""+newline
4536 ;
4537 StringTemplateGroup group =
4538 new StringTemplateGroup(new StringReader(templates),
4539 AngleBracketTemplateLexer.class);
4540 StringTemplate e = group.getInstanceOf("test");
4541 e.setAttribute("names", "Ter");
4542 e.setAttribute("names", "Tom");
4543 e.setAttribute("x", "ick");
4544 String expecting = "*ick**ick*";
4545 String result = e.toString();
4546 assertEquals(expecting, result);
4547 }
4548
4549 public void testSoleFormalTemplateArgumentInMultiApply() throws Exception {
4550 String templates =
4551 "group test;" +newline+
4552 "test(names) ::= \"<names:bold(),italics()>\""+newline+
4553 "bold(x) ::= \"*<x>*\""+newline+
4554 "italics(y) ::= \"_<y>_\""+newline
4555 ;
4556 StringTemplateGroup group =
4557 new StringTemplateGroup(new StringReader(templates),
4558 AngleBracketTemplateLexer.class);
4559 StringTemplate e = group.getInstanceOf("test");
4560 e.setAttribute("names", "Ter");
4561 e.setAttribute("names", "Tom");
4562 String expecting = "*Ter*_Tom_";
4563 String result = e.toString();
4564 assertEquals(expecting, result);
4565 }
4566
4567 public void testSingleExprTemplateArgumentError() throws Exception {
4568 String templates =
4569 "group test;" +newline+
4570 "test(name) ::= \"<bold(name)>\""+newline+
4571 "bold(item,ick) ::= \"*<item>*\""+newline
4572 ;
4573 StringTemplateErrorListener errors = new ErrorBuffer();
4574 StringTemplateGroup group =
4575 new StringTemplateGroup(new StringReader(templates),
4576 AngleBracketTemplateLexer.class, errors);
4577 StringTemplate e = group.getInstanceOf("test");
4578 e.setAttribute("name", "Ter");
4579 /*String result =*/ e.toString();
4580 String expecting = "template bold must have exactly one formal arg in template context [test <invoke bold arg context>]";
4581 assertEquals(errors.toString(), expecting);
4582 }
4583
4584 public void testInvokeIndirectTemplateWithSingleFormalArgs() throws Exception {
4585 String templates =
4586 "group test;" +newline+
4587 "test(templateName,arg) ::= \"<(templateName)(arg)>\""+newline+
4588 "bold(x) ::= <<*<x>*>>"+newline+
4589 "italics(y) ::= <<_<y>_>>"+newline
4590 ;
4591 StringTemplateGroup group =
4592 new StringTemplateGroup(new StringReader(templates));
4593 StringTemplate e = group.getInstanceOf("test");
4594 e.setAttribute("templateName", "italics");
4595 e.setAttribute("arg", "Ter");
4596 String expecting = "_Ter_";
4597 String result = e.toString();
4598 assertEquals(expecting, result);
4599 }
4600
4601 public void testParallelAttributeIteration() throws Exception {
4602 StringTemplate e = new StringTemplate(
4603 "$names,phones,salaries:{n,p,s | $n$@$p$: $s$\n}$"
4604 );
4605 e = e.getInstanceOf();
4606 e.setAttribute("names", "Ter");
4607 e.setAttribute("names", "Tom");
4608 e.setAttribute("phones", "1");
4609 e.setAttribute("phones", "2");
4610 e.setAttribute("salaries", "big");
4611 e.setAttribute("salaries", "huge");
4612 String expecting = "Ter@1: big"+newline+"Tom@2: huge"+newline;
4613 assertEquals(expecting, e.toString());
4614 }
4615
4616 public void testParallelAttributeIterationWithNullValue() throws Exception {
4617 StringTemplate e = new StringTemplate(
4618 "$names,phones,salaries:{n,p,s | $n$@$p$: $s$\n}$"
4619 );
4620 e = e.getInstanceOf();
4621 e.setAttribute("names", "Ter");
4622 e.setAttribute("names", "Tom");
4623 e.setAttribute("names", "Sriram");
4624 e.setAttribute("phones", new ArrayList() {{add("1"); add(null); add("3");}});
4625 e.setAttribute("salaries", "big");
4626 e.setAttribute("salaries", "huge");
4627 e.setAttribute("salaries", "enormous");
4628 String expecting = "Ter@1: big"+newline+
4629 "Tom@: huge"+newline+
4630 "Sriram@3: enormous"+newline;
4631 assertEquals(expecting, e.toString());
4632 }
4633
4634 public void testParallelAttributeIterationHasI() throws Exception {
4635 StringTemplate e = new StringTemplate(
4636 "$names,phones,salaries:{n,p,s | $i0$. $n$@$p$: $s$\n}$"
4637 );
4638 e = e.getInstanceOf();
4639 e.setAttribute("names", "Ter");
4640 e.setAttribute("names", "Tom");
4641 e.setAttribute("phones", "1");
4642 e.setAttribute("phones", "2");
4643 e.setAttribute("salaries", "big");
4644 e.setAttribute("salaries", "huge");
4645 String expecting = "0. Ter@1: big"+newline+"1. Tom@2: huge"+newline;
4646 assertEquals(expecting, e.toString());
4647 }
4648
4649 public void testParallelAttributeIterationWithDifferentSizes() throws Exception {
4650 StringTemplate e = new StringTemplate(
4651 "$names,phones,salaries:{n,p,s | $n$@$p$: $s$}; separator=\", \"$"
4652 );
4653 e = e.getInstanceOf();
4654 e.setAttribute("names", "Ter");
4655 e.setAttribute("names", "Tom");
4656 e.setAttribute("names", "Sriram");
4657 e.setAttribute("phones", "1");
4658 e.setAttribute("phones", "2");
4659 e.setAttribute("salaries", "big");
4660 String expecting = "Ter@1: big, Tom@2: , Sriram@: ";
4661 assertEquals(expecting, e.toString());
4662 }
4663
4664 public void testParallelAttributeIterationWithSingletons() throws Exception {
4665 StringTemplate e = new StringTemplate(
4666 "$names,phones,salaries:{n,p,s | $n$@$p$: $s$}; separator=\", \"$"
4667 );
4668 e = e.getInstanceOf();
4669 e.setAttribute("names", "Ter");
4670 e.setAttribute("phones", "1");
4671 e.setAttribute("salaries", "big");
4672 String expecting = "Ter@1: big";
4673 assertEquals(expecting, e.toString());
4674 }
4675
4676 public void testParallelAttributeIterationWithMismatchArgListSizes() throws Exception {
4677 StringTemplateErrorListener errors = new ErrorBuffer();
4678 StringTemplate e = new StringTemplate(
4679 "$names,phones,salaries:{n,p | $n$@$p$}; separator=\", \"$"
4680 );
4681 e.setErrorListener(errors);
4682 e = e.getInstanceOf();
4683 e.setAttribute("names", "Ter");
4684 e.setAttribute("names", "Tom");
4685 e.setAttribute("phones", "1");
4686 e.setAttribute("phones", "2");
4687 e.setAttribute("salaries", "big");
4688 String expecting = "Ter@1, Tom@2";
4689 assertEquals(expecting, e.toString());
4690 String errorExpecting = "number of arguments [n, p] mismatch between attribute list and anonymous template in context [anonymous]";
4691 assertEquals(errorExpecting, errors.toString());
4692 }
4693
4694 public void testParallelAttributeIterationWithMissingArgs() throws Exception {
4695 StringTemplateErrorListener errors = new ErrorBuffer();
4696 StringTemplate e = new StringTemplate(
4697 "$names,phones,salaries:{$n$@$p$}; separator=\", \"$"
4698 );
4699 e.setErrorListener(errors);
4700 e = e.getInstanceOf();
4701 e.setAttribute("names", "Tom");
4702 e.setAttribute("phones", "2");
4703 e.setAttribute("salaries", "big");
4704 e.toString(); // generate the error
4705 String errorExpecting = "missing arguments in anonymous template in context [anonymous]";
4706 assertEquals(errorExpecting, errors.toString());
4707 }
4708
4709 public void testParallelAttributeIterationWithDifferentSizesTemplateRefInsideToo() throws Exception {
4710 String templates =
4711 "group test;" +newline+
4712 "page(names,phones,salaries) ::= "+newline+
4713 " <<$names,phones,salaries:{n,p,s | $value(n)$@$value(p)$: $value(s)$}; separator=\", \"$>>"+newline +
4714 "value(x=\"n/a\") ::= \"$x$\"" +newline;
4715 StringTemplateGroup group =
4716 new StringTemplateGroup(new StringReader(templates),
4717 DefaultTemplateLexer.class);
4718 StringTemplate p = group.getInstanceOf("page");
4719 p.setAttribute("names", "Ter");
4720 p.setAttribute("names", "Tom");
4721 p.setAttribute("names", "Sriram");
4722 p.setAttribute("phones", "1");
4723 p.setAttribute("phones", "2");
4724 p.setAttribute("salaries", "big");
4725 String expecting = "Ter@1: big, Tom@2: n/a, Sriram@n/a: n/a";
4726 assertEquals(expecting, p.toString());
4727 }
4728
4729 public void testAnonTemplateOnLeftOfApply() throws Exception {
4730 StringTemplate e = new StringTemplate(
4731 "${foo}:{($it$)}$"
4732 );
4733 String expecting = "(foo)";
4734 assertEquals(expecting, e.toString());
4735 }
4736
4737 public void testOverrideThroughConditional() throws Exception {
4738 String templates =
4739 "group base;" +newline+
4740 "body(ick) ::= \"<if(ick)>ick<f()><else><f()><endif>\"" +
4741 "f() ::= \"foo\""+newline
4742 ;
4743 StringTemplateGroup group =
4744 new StringTemplateGroup(new StringReader(templates));
4745 String templates2 =
4746 "group sub;" +newline+
4747 "f() ::= \"bar\""+newline
4748 ;
4749 StringTemplateGroup subgroup =
4750 new StringTemplateGroup(new StringReader(templates2),
4751 AngleBracketTemplateLexer.class,
4752 null,
4753 group);
4754
4755 StringTemplate b = subgroup.getInstanceOf("body");
4756 String expecting ="bar";
4757 String result = b.toString();
4758 assertEquals(expecting, result);
4759 }
4760
4761 public static class NonPublicProperty {
4762
4763 }
4764
4765 public void testNonPublicPropertyAccess() throws Exception {
4766 StringTemplate st =
4767 new StringTemplate("$x.foo$:$x.bar$");
4768 Object o = new Object() {
4769 public int foo = 9;
4770 public int getBar() { return 34; }
4771 };
4772
4773 st.setAttribute("x", o);
4774 String expecting = "9:34";
4775 assertEquals(expecting, st.toString());
4776 }
4777
4778 public void testIndexVar() throws Exception {
4779 StringTemplateGroup group =
4780 new StringTemplateGroup("dummy", ".");
4781 StringTemplate t =
4782 new StringTemplate(
4783 group,
4784 "$A:{$i$. $it$}; separator=\"\\n\"$"
4785 );
4786 t.setAttribute("A", "parrt");
4787 t.setAttribute("A", "tombu");
4788 String expecting =
4789 "1. parrt" +newline+
4790 "2. tombu";
4791 assertEquals(expecting, t.toString());
4792 }
4793
4794 public void testIndex0Var() throws Exception {
4795 StringTemplateGroup group =
4796 new StringTemplateGroup("dummy", ".");
4797 StringTemplate t =
4798 new StringTemplate(
4799 group,
4800 "$A:{$i0$. $it$}; separator=\"\\n\"$"
4801 );
4802 t.setAttribute("A", "parrt");
4803 t.setAttribute("A", "tombu");
4804 String expecting =
4805 "0. parrt" +newline+
4806 "1. tombu";
4807 assertEquals(expecting, t.toString());
4808 }
4809
4810 public void testIndexVarWithMultipleExprs() throws Exception {
4811 StringTemplateGroup group =
4812 new StringTemplateGroup("dummy", ".");
4813 StringTemplate t =
4814 new StringTemplate(
4815 group,
4816 "$A,B:{a,b|$i$. $a$@$b$}; separator=\"\\n\"$"
4817 );
4818 t.setAttribute("A", "parrt");
4819 t.setAttribute("A", "tombu");
4820 t.setAttribute("B", "x5707");
4821 t.setAttribute("B", "x5000");
4822 String expecting =
4823 "1. parrt@x5707" +newline+
4824 "2. tombu@x5000";
4825 assertEquals(expecting, t.toString());
4826 }
4827
4828 public void testIndex0VarWithMultipleExprs() throws Exception {
4829 StringTemplateGroup group =
4830 new StringTemplateGroup("dummy", ".");
4831 StringTemplate t =
4832 new StringTemplate(
4833 group,
4834 "$A,B:{a,b|$i0$. $a$@$b$}; separator=\"\\n\"$"
4835 );
4836 t.setAttribute("A", "parrt");
4837 t.setAttribute("A", "tombu");
4838 t.setAttribute("B", "x5707");
4839 t.setAttribute("B", "x5000");
4840 String expecting =
4841 "0. parrt@x5707" +newline+
4842 "1. tombu@x5000";
4843 assertEquals(expecting, t.toString());
4844 }
4845
4846 public void testArgumentContext() throws Exception {
4847 // t is referenced within foo and so will be evaluated in that
4848 // context. it can therefore see name.
4849 StringTemplateGroup group =
4850 new StringTemplateGroup("test");
4851 StringTemplate main = group.defineTemplate("main", "$foo(t={Hi, $name$}, name=\"parrt\")$");
4852 /*StringTemplate foo =*/ group.defineTemplate("foo", "$t$");
4853 String expecting="Hi, parrt";
4854 assertEquals(expecting, main.toString());
4855 }
4856
4857 public void testNoDotsInAttributeNames() throws Exception {
4858 StringTemplateGroup group = new StringTemplateGroup("dummy", ".");
4859 StringTemplate t = new StringTemplate(group, "$user.Name$");
4860 String error=null;
4861 try {
4862 t.setAttribute("user.Name", "Kunle");
4863 }
4864 catch (IllegalArgumentException e) {
4865 error = e.getMessage();
4866 }
4867 String expecting = "cannot have '.' in attribute names";
4868 assertEquals(expecting,error);
4869 }
4870
4871 public void testNoDotsInTemplateNames() throws Exception {
4872 StringTemplateErrorListener errors = new ErrorBuffer();
4873 String templates =
4874 "group test;" +newline+
4875 "a.b() ::= <<foo>>"+newline;
4876
4877 /*StringTemplateGroup group =*/
4878 new StringTemplateGroup(new StringReader(templates),
4879 DefaultTemplateLexer.class,
4880 errors);
4881 String expecting = "template group parse error: line 2:1: unexpected token:";
4882 assertTrue(errors.toString().startsWith(expecting));
4883 }
4884
4885 public void testLineWrap() throws Exception {
4886 String templates =
4887 "group test;" +newline+
4888 "array(values) ::= <<int[] a = { <values; wrap=\"\\n\", separator=\",\"> };>>"+newline;
4889 StringTemplateGroup group =
4890 new StringTemplateGroup(new StringReader(templates));
4891
4892 StringTemplate a = group.getInstanceOf("array");
4893 a.setAttribute("values",
4894 new int[] {3,9,20,2,1,4,6,32,5,6,77,888,2,1,6,32,5,6,77,
4895 4,9,20,2,1,4,63,9,20,2,1,4,6,32,5,6,77,6,32,5,6,77,
4896 3,9,20,2,1,4,6,32,5,6,77,888,1,6,32,5});
4897 String expecting =
4898 "int[] a = { 3,9,20,2,1,4,6,32,5,6,77,888,\n" +
4899 "2,1,6,32,5,6,77,4,9,20,2,1,4,63,9,20,2,1,\n" +
4900 "4,6,32,5,6,77,6,32,5,6,77,3,9,20,2,1,4,6,\n" +
4901 "32,5,6,77,888,1,6,32,5 };";
4902 assertEquals(expecting,a.toString(40));
4903 }
4904
4905 public void testLineWrapWithNormalizedNewlines() throws Exception {
4906 String templates =
4907 "group test;" +newline+
4908 "array(values) ::= <<int[] a = { <values; wrap=\"\\r\\n\", separator=\",\"> };>>"+newline;
4909 StringTemplateGroup group =
4910 new StringTemplateGroup(new StringReader(templates));
4911
4912 StringTemplate a = group.getInstanceOf("array");
4913 a.setAttribute("values",
4914 new int[] {3,9,20,2,1,4,6,32,5,6,77,888,2,1,6,32,5,6,77,
4915 4,9,20,2,1,4,63,9,20,2,1,4,6,32,5,6,77,6,32,5,6,77,
4916 3,9,20,2,1,4,6,32,5,6,77,888,1,6,32,5});
4917 String expecting =
4918 "int[] a = { 3,9,20,2,1,4,6,32,5,6,77,888,\n" + // wrap is \r\n, normalize to \n
4919 "2,1,6,32,5,6,77,4,9,20,2,1,4,63,9,20,2,1,\n" +
4920 "4,6,32,5,6,77,6,32,5,6,77,3,9,20,2,1,4,6,\n" +
4921 "32,5,6,77,888,1,6,32,5 };";
4922
4923 StringWriter sw = new StringWriter();
4924 StringTemplateWriter stw = new AutoIndentWriter(sw,"\n"); // force \n as newline
4925 stw.setLineWidth(40);
4926 a.write(stw);
4927 String result = sw.toString();
4928 assertEquals(expecting, result);
4929 }
4930
4931 public void testLineWrapAnchored() throws Exception {
4932 String templates =
4933 "group test;" +newline+
4934 "array(values) ::= <<int[] a = { <values; anchor, wrap=\"\\n\", separator=\",\"> };>>"+newline;
4935 StringTemplateGroup group =
4936 new StringTemplateGroup(new StringReader(templates));
4937
4938 StringTemplate a = group.getInstanceOf("array");
4939 a.setAttribute("values",
4940 new int[] {3,9,20,2,1,4,6,32,5,6,77,888,2,1,6,32,5,6,77,
4941 4,9,20,2,1,4,63,9,20,2,1,4,6,32,5,6,77,6,32,5,6,77,
4942 3,9,20,2,1,4,6,32,5,6,77,888,1,6,32,5});
4943 String expecting =
4944 "int[] a = { 3,9,20,2,1,4,6,32,5,6,77,888,\n" +
4945 " 2,1,6,32,5,6,77,4,9,20,2,1,4,\n" +
4946 " 63,9,20,2,1,4,6,32,5,6,77,6,\n" +
4947 " 32,5,6,77,3,9,20,2,1,4,6,32,\n" +
4948 " 5,6,77,888,1,6,32,5 };";
4949 assertEquals(expecting, a.toString(40));
4950 }
4951
4952 public void testSubtemplatesAnchorToo() throws Exception {
4953 String templates =
4954 "group test;" +newline+
4955 "array(values) ::= <<{ <values; anchor, separator=\", \"> }>>"+newline;
4956 StringTemplateGroup group =
4957 new StringTemplateGroup(new StringReader(templates));
4958
4959 final StringTemplate x = new StringTemplate(group, "<\\n>{ <stuff; anchor, separator=\",\\n\"> }<\\n>");
4960 x.setAttribute("stuff", "1");
4961 x.setAttribute("stuff", "2");
4962 x.setAttribute("stuff", "3");
4963 StringTemplate a = group.getInstanceOf("array");
4964 a.setAttribute("values", new ArrayList() {{
4965 add("a"); add(x); add("b");
4966 }});
4967 String expecting =
4968 "{ a, \n" +
4969 " { 1,\n" +
4970 " 2,\n" +
4971 " 3 }\n" +
4972 " , b }";
4973 assertEquals(expecting, a.toString(40));
4974 }
4975
4976 public void testFortranLineWrap() throws Exception {
4977 String templates =
4978 "group test;" +newline+
4979 "func(args) ::= << FUNCTION line( <args; wrap=\"\\n c\", separator=\",\"> )>>"+newline;
4980 StringTemplateGroup group =
4981 new StringTemplateGroup(new StringReader(templates));
4982
4983 StringTemplate a = group.getInstanceOf("func");
4984 a.setAttribute("args",
4985 new String[] {"a","b","c","d","e","f"});
4986 String expecting =
4987 " FUNCTION line( a,b,c,d,\n" +
4988 " ce,f )";
4989 assertEquals(expecting, a.toString(30));
4990 }
4991
4992 public void testLineWrapWithDiffAnchor() throws Exception {
4993 String templates =
4994 "group test;" +newline+
4995 "array(values) ::= <<int[] a = { <{1,9,2,<values; wrap, separator=\",\">}; anchor> };>>"+newline;
4996 StringTemplateGroup group =
4997 new StringTemplateGroup(new StringReader(templates));
4998
4999 StringTemplate a = group.getInstanceOf("array");
5000 a.setAttribute("values",
5001 new int[] {3,9,20,2,1,4,6,32,5,6,77,888,2,1,6,32,5,6,77,
5002 4,9,20,2,1,4,63,9,20,2,1,4,6});
5003 String expecting =
5004 "int[] a = { 1,9,2,3,9,20,2,1,4,\n" +
5005 " 6,32,5,6,77,888,2,\n" +
5006 " 1,6,32,5,6,77,4,9,\n" +
5007 " 20,2,1,4,63,9,20,2,\n" +
5008 " 1,4,6 };";
5009 assertEquals(expecting, a.toString(30));
5010 }
5011
5012 public void testLineWrapEdgeCase() throws Exception {
5013 String templates =
5014 "group test;" +newline+
5015 "duh(chars) ::= <<<chars; wrap=\"\\n\"\\>>>"+newline;
5016 StringTemplateGroup group =
5017 new StringTemplateGroup(new StringReader(templates));
5018
5019 StringTemplate a = group.getInstanceOf("duh");
5020 a.setAttribute("chars", new String[] {"a","b","c","d","e"});
5021 // lineWidth==3 implies that we can have 3 characters at most
5022 String expecting =
5023 "abc\n"+
5024 "de";
5025 assertEquals(expecting, a.toString(3));
5026 }
5027
5028 public void testLineWrapLastCharIsNewline() throws Exception {
5029 String templates =
5030 "group test;" +newline+
5031 "duh(chars) ::= <<<chars; wrap=\"\\n\"\\>>>"+newline;
5032 StringTemplateGroup group =
5033 new StringTemplateGroup(new StringReader(templates));
5034
5035 StringTemplate a = group.getInstanceOf("duh");
5036 a.setAttribute("chars", new String[] {"a","b","\n","d","e"});
5037 // don't do \n if it's last element anyway
5038 String expecting =
5039 "ab\n"+
5040 "de";
5041 assertEquals(expecting,a.toString(3));
5042 }
5043
5044 public void testLineWrapCharAfterWrapIsNewline() throws Exception {
5045 String templates =
5046 "group test;" +newline+
5047 "duh(chars) ::= <<<chars; wrap=\"\\n\"\\>>>"+newline;
5048 StringTemplateGroup group =
5049 new StringTemplateGroup(new StringReader(templates));
5050
5051 StringTemplate a = group.getInstanceOf("duh");
5052 a.setAttribute("chars", new String[] {"a","b","c","\n","d","e"});
5053 // Once we wrap, we must dump chars as we see them. A newline right
5054 // after a wrap is just an "unfortunate" event. People will expect
5055 // a newline if it's in the data.
5056 String expecting =
5057 "abc\n" +
5058 "\n" +
5059 "de";
5060 assertEquals(expecting, a.toString(3));
5061 }
5062
5063 public void testLineWrapForAnonTemplate() throws Exception {
5064 String templates =
5065 "group test;" +newline+
5066 "duh(data) ::= <<!<data:{v|[<v>]}; wrap>!>>"+newline;
5067 StringTemplateGroup group =
5068 new StringTemplateGroup(new StringReader(templates));
5069
5070 StringTemplate a = group.getInstanceOf("duh");
5071 a.setAttribute("data", new int[] {1,2,3,4,5,6,7,8,9});
5072 String expecting =
5073 "![1][2][3]\n" + // width=9 is the 3 char; don't break til after ]
5074 "[4][5][6]\n" +
5075 "[7][8][9]!";
5076 assertEquals(expecting,a.toString(9));
5077 }
5078
5079 public void testLineWrapForAnonTemplateAnchored() throws Exception {
5080 String templates =
5081 "group test;" +newline+
5082 "duh(data) ::= <<!<data:{v|[<v>]}; anchor, wrap>!>>"+newline;
5083 StringTemplateGroup group =
5084 new StringTemplateGroup(new StringReader(templates));
5085
5086 StringTemplate a = group.getInstanceOf("duh");
5087 a.setAttribute("data", new int[] {1,2,3,4,5,6,7,8,9});
5088 String expecting =
5089 "![1][2][3]\n" +
5090 " [4][5][6]\n" +
5091 " [7][8][9]!";
5092 assertEquals(expecting, a.toString(9));
5093 }
5094
5095 public void testLineWrapForAnonTemplateComplicatedWrap() throws Exception {
5096 String templates =
5097 "group test;" +newline+
5098 "top(s) ::= << <s>.>>"+
5099 "str(data) ::= <<!<data:{v|[<v>]}; wrap=\"!+\\n!\">!>>"+newline;
5100 StringTemplateGroup group =
5101 new StringTemplateGroup(new StringReader(templates));
5102
5103 StringTemplate t = group.getInstanceOf("top");
5104 StringTemplate s = group.getInstanceOf("str");
5105 s.setAttribute("data", new int[] {1,2,3,4,5,6,7,8,9});
5106 t.setAttribute("s", s);
5107 String expecting =
5108 " ![1][2]!+\n" +
5109 " ![3][4]!+\n" +
5110 " ![5][6]!+\n" +
5111 " ![7][8]!+\n" +
5112 " ![9]!.";
5113 assertEquals(expecting,t.toString(9));
5114 }
5115
5116 public void testIndentBeyondLineWidth() throws Exception {
5117 String templates =
5118 "group test;" +newline+
5119 "duh(chars) ::= << <chars; wrap=\"\\n\"\\>>>"+newline;
5120 StringTemplateGroup group =
5121 new StringTemplateGroup(new StringReader(templates));
5122
5123 StringTemplate a = group.getInstanceOf("duh");
5124 a.setAttribute("chars", new String[] {"a","b","c","d","e"});
5125 //
5126 String expecting =
5127 " a\n" +
5128 " b\n" +
5129 " c\n" +
5130 " d\n" +
5131 " e";
5132 assertEquals(expecting, a.toString(2));
5133 }
5134
5135 public void testIndentedExpr() throws Exception {
5136 String templates =
5137 "group test;" +newline+
5138 "duh(chars) ::= << <chars; wrap=\"\\n\"\\>>>"+newline;
5139 StringTemplateGroup group =
5140 new StringTemplateGroup(new StringReader(templates));
5141
5142 StringTemplate a = group.getInstanceOf("duh");
5143 a.setAttribute("chars", new String[] {"a","b","c","d","e"});
5144 //
5145 String expecting =
5146 " ab\n" +
5147 " cd\n" +
5148 " e";
5149 // width=4 spaces + 2 char.
5150 assertEquals(expecting, a.toString(6));
5151 }
5152
5153 public void testNestedIndentedExpr() throws Exception {
5154 String templates =
5155 "group test;" +newline+
5156 "top(d) ::= << <d>!>>"+newline+
5157 "duh(chars) ::= << <chars; wrap=\"\\n\"\\>>>"+newline;
5158 StringTemplateGroup group =
5159 new StringTemplateGroup(new StringReader(templates));
5160
5161 StringTemplate top = group.getInstanceOf("top");
5162 StringTemplate duh = group.getInstanceOf("duh");
5163 duh.setAttribute("chars", new String[] {"a","b","c","d","e"});
5164 top.setAttribute("d", duh);
5165 String expecting =
5166 " ab\n" +
5167 " cd\n" +
5168 " e!";
5169 // width=4 spaces + 2 char.
5170 assertEquals(expecting, top.toString(6));
5171 }
5172
5173 public void testNestedWithIndentAndTrackStartOfExpr() throws Exception {
5174 String templates =
5175 "group test;" +newline+
5176 "top(d) ::= << <d>!>>"+newline+
5177 "duh(chars) ::= <<x: <chars; anchor, wrap=\"\\n\"\\>>>"+newline;
5178 StringTemplateGroup group =
5179 new StringTemplateGroup(new StringReader(templates));
5180
5181 StringTemplate top = group.getInstanceOf("top");
5182 StringTemplate duh = group.getInstanceOf("duh");
5183 duh.setAttribute("chars", new String[] {"a","b","c","d","e"});
5184 top.setAttribute("d", duh);
5185 //
5186 String expecting =
5187 " x: ab\n" +
5188 " cd\n" +
5189 " e!";
5190 assertEquals(expecting, top.toString(7));
5191 }
5192
5193 public void testLineDoesNotWrapDueToLiteral() throws Exception {
5194 String templates =
5195 "group test;" +newline+
5196 "m(args,body) ::= <<public void foo(<args; wrap=\"\\n\",separator=\", \">) throws Ick { <body> }>>"+newline;
5197 StringTemplateGroup group =
5198 new StringTemplateGroup(new StringReader(templates));
5199
5200 StringTemplate a = group.getInstanceOf("m");
5201 a.setAttribute("args",
5202 new String[] {"a", "b", "c"});
5203 a.setAttribute("body", "i=3;");
5204 // make it wrap because of ") throws Ick { " literal
5205 int n = "public void foo(a, b, c".length();
5206 String expecting =
5207 "public void foo(a, b, c) throws Ick { i=3; }";
5208 assertEquals(expecting, a.toString(n));
5209 }
5210
5211 public void testSingleValueWrap() throws Exception {
5212 String templates =
5213 "group test;" +newline+
5214 "m(args,body) ::= <<{ <body; anchor, wrap=\"\\n\"> }>>"+newline;
5215 StringTemplateGroup group =
5216 new StringTemplateGroup(new StringReader(templates));
5217
5218 StringTemplate m = group.getInstanceOf("m");
5219 m.setAttribute("body", "i=3;");
5220 // make it wrap because of ") throws Ick { " literal
5221 String expecting =
5222 "{ \n"+
5223 " i=3; }";
5224 assertEquals(expecting, m.toString(2));
5225 }
5226
5227 public void testLineWrapInNestedExpr() throws Exception {
5228 String templates =
5229 "group test;" +newline+
5230 "top(arrays) ::= <<Arrays: <arrays>done>>"+newline+
5231 "array(values) ::= <<int[] a = { <values; anchor, wrap=\"\\n\", separator=\",\"> };<\\n\\>>>"+newline;
5232 StringTemplateGroup group =
5233 new StringTemplateGroup(new StringReader(templates));
5234
5235 StringTemplate top = group.getInstanceOf("top");
5236 StringTemplate a = group.getInstanceOf("array");
5237 a.setAttribute("values",
5238 new int[] {3,9,20,2,1,4,6,32,5,6,77,888,2,1,6,32,5,6,77,
5239 4,9,20,2,1,4,63,9,20,2,1,4,6,32,5,6,77,6,32,5,6,77,
5240 3,9,20,2,1,4,6,32,5,6,77,888,1,6,32,5});
5241 top.setAttribute("arrays", a);
5242 top.setAttribute("arrays", a); // add twice
5243 String expecting =
5244 "Arrays: int[] a = { 3,9,20,2,1,4,6,32,5,\n" +
5245 " 6,77,888,2,1,6,32,5,\n" +
5246 " 6,77,4,9,20,2,1,4,63,\n" +
5247 " 9,20,2,1,4,6,32,5,6,\n" +
5248 " 77,6,32,5,6,77,3,9,20,\n" +
5249 " 2,1,4,6,32,5,6,77,888,\n" +
5250 " 1,6,32,5 };\n" +
5251 "int[] a = { 3,9,20,2,1,4,6,32,5,6,77,888,\n" +
5252 " 2,1,6,32,5,6,77,4,9,20,2,1,4,\n" +
5253 " 63,9,20,2,1,4,6,32,5,6,77,6,\n" +
5254 " 32,5,6,77,3,9,20,2,1,4,6,32,\n" +
5255 " 5,6,77,888,1,6,32,5 };\n" +
5256 "done";
5257 assertEquals(expecting, top.toString(40));
5258 }
5259
5260 public void testBackslash() throws Exception {
5261 StringTemplateGroup group =
5262 new StringTemplateGroup("test");
5263 StringTemplate t = group.defineTemplate("t", "\\");
5264 String expecting="\\";
5265 assertEquals(expecting, t.toString());
5266 }
5267
5268 public void testBackslash2() throws Exception {
5269 StringTemplateGroup group =
5270 new StringTemplateGroup("test");
5271 StringTemplate t = group.defineTemplate("t", "\\ ");
5272 String expecting="\\ ";
5273 assertEquals(expecting, t.toString());
5274 }
5275
5276 public void testEscapeEscape() throws Exception {
5277 StringTemplateGroup group =
5278 new StringTemplateGroup("test");
5279 StringTemplate t = group.defineTemplate("t", "\\\\$v$");
5280 t.setAttribute("v", "Joe");
5281 //System.out.println(t);
5282 String expecting="\\Joe";
5283 assertEquals(expecting, t.toString());
5284 }
5285
5286 public void testEscapeEscapeNestedAngle() throws Exception {
5287 StringTemplateGroup group =
5288 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5289 StringTemplate t = group.defineTemplate("t", "<v:{a|\\\\<a>}>");
5290 t.setAttribute("v", "Joe");
5291 //System.out.println(t);
5292 String expecting="\\Joe";
5293 assertEquals(expecting, t.toString());
5294 }
5295
5296 public void testListOfIntArrays() throws Exception {
5297 StringTemplateGroup group =
5298 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5299 StringTemplate t =
5300 group.defineTemplate("t", "<data:array()>");
5301 group.defineTemplate("array", "[<it:element(); separator=\",\">]");
5302 group.defineTemplate("element", "<it>");
5303 List data = new ArrayList();
5304 data.add(new int[] {1,2,3});
5305 data.add(new int[] {10,20,30});
5306 t.setAttribute("data", data);
5307 //System.out.println(t);
5308 String expecting="[1,2,3][10,20,30]";
5309 assertEquals(expecting, t.toString());
5310 }
5311
5312 // Test null option
5313
5314 public void testNullOptionSingleNullValue() throws Exception {
5315 StringTemplateGroup group =
5316 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5317 StringTemplate t =
5318 group.defineTemplate("t", "<data; null=\"0\">");
5319 //System.out.println(t);
5320 String expecting="0";
5321 assertEquals(expecting, t.toString());
5322 }
5323
5324 public void testNullOptionHasEmptyNullValue() throws Exception {
5325 StringTemplateGroup group =
5326 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5327 StringTemplate t =
5328 group.defineTemplate("t", "<data; null=\"\", separator=\", \">");
5329 List data = new ArrayList();
5330 data.add(null);
5331 data.add(new Integer(1));
5332 t.setAttribute("data", data);
5333 String expecting=", 1";
5334 assertEquals(expecting, t.toString());
5335 }
5336
5337 public void testNullOptionSingleNullValueInList() throws Exception {
5338 StringTemplateGroup group =
5339 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5340 StringTemplate t =
5341 group.defineTemplate("t", "<data; null=\"0\">");
5342 List data = new ArrayList();
5343 data.add(null);
5344 t.setAttribute("data", data);
5345 //System.out.println(t);
5346 String expecting="0";
5347 assertEquals(expecting, t.toString());
5348 }
5349
5350 public void testNullValueInList() throws Exception {
5351 StringTemplateGroup group =
5352 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5353 StringTemplate t =
5354 group.defineTemplate("t", "<data; null=\"-1\", separator=\", \">");
5355 List data = new ArrayList();
5356 data.add(null);
5357 data.add(new Integer(1));
5358 data.add(null);
5359 data.add(new Integer(3));
5360 data.add(new Integer(4));
5361 data.add(null);
5362 t.setAttribute("data", data);
5363 //System.out.println(t);
5364 String expecting="-1, 1, -1, 3, 4, -1";
5365 assertEquals(expecting, t.toString());
5366 }
5367
5368 public void testNullValueInListNoNullOption() throws Exception {
5369 StringTemplateGroup group =
5370 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5371 StringTemplate t =
5372 group.defineTemplate("t", "<data; separator=\", \">");
5373 List data = new ArrayList();
5374 data.add(null);
5375 data.add(new Integer(1));
5376 data.add(null);
5377 data.add(new Integer(3));
5378 data.add(new Integer(4));
5379 data.add(null);
5380 t.setAttribute("data", data);
5381 //System.out.println(t);
5382 String expecting="1, 3, 4";
5383 assertEquals(expecting, t.toString());
5384 }
5385
5386 public void testNullValueInListWithTemplateApply() throws Exception {
5387 StringTemplateGroup group =
5388 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5389 StringTemplate t =
5390 group.defineTemplate("t", "<data:array(); null=\"-1\", separator=\", \">");
5391 group.defineTemplate("array", "<it>");
5392 List data = new ArrayList();
5393 data.add(new Integer(0));
5394 data.add(null);
5395 data.add(new Integer(2));
5396 data.add(null);
5397 t.setAttribute("data", data);
5398 String expecting="0, -1, 2, -1";
5399 assertEquals(expecting, t.toString());
5400 }
5401
5402 public void testNullValueInListWithTemplateApplyNullFirstValue() throws Exception {
5403 StringTemplateGroup group =
5404 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5405 StringTemplate t =
5406 group.defineTemplate("t", "<data:array(); null=\"-1\", separator=\", \">");
5407 group.defineTemplate("array", "<it>");
5408 List data = new ArrayList();
5409 data.add(null);
5410 data.add(new Integer(0));
5411 data.add(null);
5412 data.add(new Integer(2));
5413 t.setAttribute("data", data);
5414 String expecting="-1, 0, -1, 2";
5415 assertEquals(expecting, t.toString());
5416 }
5417
5418 public void testNullSingleValueInListWithTemplateApply() throws Exception {
5419 StringTemplateGroup group =
5420 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5421 StringTemplate t =
5422 group.defineTemplate("t", "<data:array(); null=\"-1\", separator=\", \">");
5423 group.defineTemplate("array", "<it>");
5424 List data = new ArrayList();
5425 data.add(null);
5426 t.setAttribute("data", data);
5427 String expecting="-1";
5428 assertEquals(expecting, t.toString());
5429 }
5430
5431 public void testNullSingleValueWithTemplateApply() throws Exception {
5432 StringTemplateGroup group =
5433 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5434 StringTemplate t =
5435 group.defineTemplate("t", "<data:array(); null=\"-1\", separator=\", \">");
5436 group.defineTemplate("array", "<it>");
5437 String expecting="-1";
5438 assertEquals(expecting, t.toString());
5439 }
5440
5441 public void testLengthOp() throws Exception {
5442 StringTemplate e = new StringTemplate(
5443 "$length(names)$"
5444 );
5445 e = e.getInstanceOf();
5446 e.setAttribute("names", "Ter");
5447 e.setAttribute("names", "Tom");
5448 e.setAttribute("names", "Sriram");
5449 String expecting = "3";
5450 assertEquals(expecting, e.toString());
5451 }
5452
5453 public void testLengthOpWithMap() throws Exception {
5454 StringTemplate e = new StringTemplate(
5455 "$length(names)$"
5456 );
5457 e = e.getInstanceOf();
5458 Map m = new HashMap();
5459 m.put("Tom", "foo");
5460 m.put("Sriram", "foo");
5461 m.put("Doug", "foo");
5462 e.setAttribute("names", m);
5463 String expecting = "3";
5464 assertEquals(expecting, e.toString());
5465 }
5466
5467 public void testLengthOpWithSet() throws Exception {
5468 StringTemplate e = new StringTemplate(
5469 "$length(names)$"
5470 );
5471 e = e.getInstanceOf();
5472 Set m = new HashSet();
5473 m.add("Tom");
5474 m.add("Sriram");
5475 m.add("Doug");
5476 e.setAttribute("names", m);
5477 String expecting = "3";
5478 assertEquals(expecting, e.toString());
5479 }
5480
5481 public void testLengthOpNull() throws Exception {
5482 StringTemplate e = new StringTemplate(
5483 "$length(names)$"
5484 );
5485 e = e.getInstanceOf();
5486 e.setAttribute("names", null);
5487 String expecting = "0";
5488 assertEquals(expecting, e.toString());
5489 }
5490
5491 public void testLengthOpSingleValue() throws Exception {
5492 StringTemplate e = new StringTemplate(
5493 "$length(names)$"
5494 );
5495 e = e.getInstanceOf();
5496 e.setAttribute("names", "Ter");
5497 String expecting = "1";
5498 assertEquals(expecting, e.toString());
5499 }
5500
5501 public void testLengthOpPrimitive() throws Exception {
5502 StringTemplate e = new StringTemplate(
5503 "$length(ints)$"
5504 );
5505 e = e.getInstanceOf();
5506 e.setAttribute("ints", new int[] {1,2,3,4} );
5507 String expecting = "4";
5508 assertEquals(expecting, e.toString());
5509 }
5510
5511 public void testLengthOpOfListWithNulls() throws Exception {
5512 StringTemplate e = new StringTemplate(
5513 "$length(data)$"
5514 );
5515 e = e.getInstanceOf();
5516 List data = new ArrayList();
5517 data.add("Hi");
5518 data.add(null);
5519 data.add("mom");
5520 data.add(null);
5521 e.setAttribute("data", data);
5522 String expecting = "4"; // nulls are counted
5523 assertEquals(expecting, e.toString());
5524 }
5525
5526 public void testStripOpOfListWithNulls() throws Exception {
5527 StringTemplate e = new StringTemplate(
5528 "$strip(data)$"
5529 );
5530 e = e.getInstanceOf();
5531 List data = new ArrayList();
5532 data.add("Hi");
5533 data.add(null);
5534 data.add("mom");
5535 data.add(null);
5536 e.setAttribute("data", data);
5537 String expecting = "Himom"; // nulls are skipped
5538 assertEquals(expecting, e.toString());
5539 }
5540
5541 public void testStripOpOfListOfListsWithNulls() throws Exception {
5542 StringTemplate e = new StringTemplate(
5543 "$strip(data):{list | $strip(list)$}; separator=\",\"$"
5544 );
5545 e = e.getInstanceOf();
5546 List data = new ArrayList();
5547 List dataOne = new ArrayList();
5548 dataOne.add("Hi");
5549 dataOne.add("mom");
5550 data.add(dataOne);
5551 data.add(null);
5552 List dataTwo = new ArrayList();
5553 dataTwo.add("Hi");
5554 dataTwo.add(null);
5555 dataTwo.add("dad");
5556 dataTwo.add(null);
5557 data.add(dataTwo);
5558 e.setAttribute("data", data);
5559 String expecting = "Himom,Hidad"; // nulls are skipped
5560 assertEquals(expecting, e.toString());
5561 }
5562
5563 public void testStripOpOfSingleAlt() throws Exception {
5564 StringTemplate e = new StringTemplate(
5565 "$strip(data)$"
5566 );
5567 e = e.getInstanceOf();
5568 e.setAttribute("data", "hi");
5569 String expecting = "hi"; // nulls are skipped
5570 assertEquals(expecting, e.toString());
5571 }
5572
5573 public void testStripOpOfNull() throws Exception {
5574 StringTemplate e = new StringTemplate(
5575 "$strip(data)$"
5576 );
5577 e = e.getInstanceOf();
5578 String expecting = ""; // nulls are skipped
5579 assertEquals(expecting, e.toString());
5580 }
5581
5582 public void testReUseOfStripResult() throws Exception {
5583 String templates =
5584 "group test;" +newline+
5585 "a(names) ::= \"<b(strip(names))>\""+newline+
5586 "b(x) ::= \"<x>, <x>\""+newline
5587 ;
5588 StringTemplateGroup group =
5589 new StringTemplateGroup(new StringReader(templates));
5590 StringTemplate e = group.getInstanceOf("a");
5591 List names = new ArrayList();
5592 names.add("Ter");
5593 names.add(null);
5594 names.add("Tom");
5595 e.setAttribute("names", names);
5596 String expecting = "TerTom, TerTom";
5597 assertEquals(expecting, e.toString());
5598 }
5599
5600 public void testLengthOpOfStrippedListWithNulls() throws Exception {
5601 StringTemplate e = new StringTemplate(
5602 "$length(strip(data))$"
5603 );
5604 e = e.getInstanceOf();
5605 List data = new ArrayList();
5606 data.add("Hi");
5607 data.add(null);
5608 data.add("mom");
5609 data.add(null);
5610 e.setAttribute("data", data);
5611 String expecting = "2"; // nulls are counted
5612 assertEquals(expecting, e.toString());
5613 }
5614
5615 public void testLengthOpOfStrippedListWithNullsFrontAndBack() throws Exception {
5616 StringTemplate e = new StringTemplate(
5617 "$length(strip(data))$"
5618 );
5619 e = e.getInstanceOf();
5620 List data = new ArrayList();
5621 data.add(null);
5622 data.add(null);
5623 data.add(null);
5624 data.add("Hi");
5625 data.add(null);
5626 data.add(null);
5627 data.add(null);
5628 data.add("mom");
5629 data.add(null);
5630 data.add(null);
5631 data.add(null);
5632 e.setAttribute("data", data);
5633 String expecting = "2"; // nulls are counted
5634 assertEquals(expecting, e.toString());
5635 }
5636
5637 public void testMapKeys() throws Exception {
5638 StringTemplateGroup group =
5639 new StringTemplateGroup("dummy", ".", AngleBracketTemplateLexer.class);
5640 StringTemplate t =
5641 new StringTemplate(group,
5642 "<aMap.keys:{k|<k>:<aMap.(k)>}; separator=\", \">");
5643 HashMap map = new LinkedHashMap();
5644 map.put("int","0");
5645 map.put("float","0.0");
5646 t.setAttribute("aMap", map);
5647 assertEquals("int:0, float:0.0",t.toString());
5648 }
5649
5650 public void testMapValues() throws Exception {
5651 StringTemplateGroup group =
5652 new StringTemplateGroup("dummy", ".", AngleBracketTemplateLexer.class);
5653 StringTemplate t =
5654 new StringTemplate(group,
5655 "<aMap.values; separator=\", \"> <aMap.(\"i\"+\"nt\")>");
5656 HashMap map = new LinkedHashMap();
5657 map.put("int","0");
5658 map.put("float","0.0");
5659 t.setAttribute("aMap", map);
5660 assertEquals("0, 0.0 0", t.toString());
5661 }
5662
5663 public void testMapKeysWithIntegerType() throws Exception {
5664 // must get back an Integer from keys not a toString()'d version
5665 StringTemplateGroup group =
5666 new StringTemplateGroup("dummy", ".", AngleBracketTemplateLexer.class);
5667 StringTemplate t =
5668 new StringTemplate(group,
5669 "<aMap.keys:{k|<k>:<aMap.(k)>}; separator=\", \">");
5670 Map map = new HashMap();
5671 map.put(new Integer(1),new ArrayList(){{add("ick"); add("foo");}});
5672 map.put(new Integer(2),new ArrayList(){{add("x"); add("y");}});
5673 t.setAttribute("aMap", map);
5674
5675 String res = t.toString();
5676 boolean passed = false;
5677 if (res.equals("2:xy, 1:ickfoo") || res.equals("1:ickfoo, 2:xy")) {
5678 passed = true;
5679 }
5680
5681 assertTrue("Map traversal did not return expected strings", passed);
5682
5683 }
5684
5685 /** Use when super.attr name is implemented
5686 public void testArgumentContext2() throws Exception {
5687 // t is referenced within foo and so will be evaluated in that
5688 // context. it can therefore see name.
5689 StringTemplateGroup group =
5690 new StringTemplateGroup("test");
5691 StringTemplate main = group.defineTemplate("main", "$foo(t={Hi, $super.name$}, name=\"parrt\")$");
5692 main.setAttribute("name", "tombu");
5693 StringTemplate foo = group.defineTemplate("foo", "$t$");
5694 String expecting="Hi, parrt";
5695 assertEquals(expecting, main.toString());
5696 }
5697 */
5698
5699 /**
5700 * Check what happens when a semicolon is appended to a single line template
5701 * Should fail with a parse error(?) and not a missing template error.
5702 * FIXME: This should generate a warning or error about that semi colon.
5703 * <p>
5704 * Bug ref: JIRA bug ST-2
5705 */
5706 /*
5707 public void testGroupTrailingSemiColon() throws Exception {
5708 //try {
5709 String templates =
5710 "group test;" +newline+
5711 "t1()::=\"R1\"; "+newline+
5712 "t2() ::= \"R2\""+newline
5713 ;
5714 StringTemplateGroup group =
5715 new StringTemplateGroup(new StringReader(templates));
5716
5717 StringTemplate st = group.getInstanceOf("t1");
5718 assertEquals("R1", st.toString());
5719
5720 st = group.getInstanceOf("t2");
5721 assertEquals("R2", st.toString());
5722
5723 fail("A parse error should have been generated");
5724 //} catch (ParseError??) {
5725 //}
5726 }
5727 */
5728 public void testSuperReferenceInIfClause() throws Exception {
5729 String superGroupString =
5730 "group super;" + newline +
5731 "a(x) ::= \"super.a\"" + newline +
5732 "b(x) ::= \"<c()>super.b\"" + newline +
5733 "c() ::= \"super.c\""
5734 ;
5735 StringTemplateGroup superGroup = new StringTemplateGroup(
5736 new StringReader(superGroupString), AngleBracketTemplateLexer.class);
5737 String subGroupString =
5738 "group sub;\n" +
5739 "a(x) ::= \"<if(x)><super.a()><endif>\"" + newline +
5740 "b(x) ::= \"<if(x)><else><super.b()><endif>\"" + newline +
5741 "c() ::= \"sub.c\""
5742 ;
5743 StringTemplateGroup subGroup = new StringTemplateGroup(
5744 new StringReader(subGroupString), AngleBracketTemplateLexer.class);
5745 subGroup.setSuperGroup(superGroup);
5746 StringTemplate a = subGroup.getInstanceOf("a");
5747 a.setAttribute("x", "foo");
5748 assertEquals("super.a", a.toString());
5749 StringTemplate b = subGroup.getInstanceOf("b");
5750 assertEquals("sub.csuper.b", b.toString());
5751 StringTemplate c = subGroup.getInstanceOf("c");
5752 assertEquals("sub.c", c.toString());
5753 }
5754
5755 /** Added feature for ST-21 */
5756 public void testListLiteralWithEmptyElements() throws Exception {
5757 StringTemplate e = new StringTemplate(
5758 "$[\"Ter\",,\"Jesse\"]:{n | $i$:$n$}; separator=\", \", null=\"\"$"
5759 );
5760 e = e.getInstanceOf();
5761 e.setAttribute("names", "Ter");
5762 e.setAttribute("phones", "1");
5763 e.setAttribute("salaries", "big");
5764 String expecting = "1:Ter, 2:, 3:Jesse";
5765 assertEquals(expecting, e.toString());
5766 }
5767
5768 public void testTemplateApplicationAsOptionValue() throws Exception {
5769 StringTemplate st =new StringTemplate(
5770 "Tokens : <rules; separator=names:{<it>}> ;",
5771 AngleBracketTemplateLexer.class);
5772 st.setAttribute("rules", "A");
5773 st.setAttribute("rules", "B");
5774 st.setAttribute("names", "Ter");
5775 st.setAttribute("names", "Tom");
5776 String expecting = "Tokens : ATerTomB ;";
5777 assertEquals(expecting, st.toString());
5778 }
5779
5780 public static void writeFile(String dir, String fileName, String content) {
5781 try {
5782 File f = new File(dir, fileName);
5783 FileWriter w = new FileWriter(f);
5784 BufferedWriter bw = new BufferedWriter(w);
5785 bw.write(content);
5786 bw.close();
5787 w.close();
5788 }
5789 catch (IOException ioe) {
5790 System.err.println("can't write file");
5791 ioe.printStackTrace(System.err);
5792 }
5793 }
5794
5795 }
0 // start of a body
1 <statements; separator="\n">
2 // end of a body
0 <visibility> <returnType> <name>(<args>) {
1 <org/antlr/stringtemplate/test/body()>
2 }
0 $users:org/antlr/stringtemplate/test/row()$
0 /*
1 [The "BSD licence"]
2 Copyright (c) 2003-2005 Terence Parr
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 package org.antlr.stringtemplate.test;
28
29 import junit.framework.TestCase;
30 import org.antlr.stringtemplate.*;
31 import org.antlr.stringtemplate.language.AngleBracketTemplateLexer;
32 import org.antlr.stringtemplate.language.DefaultTemplateLexer;
33
34 import java.io.*;
35 import java.text.SimpleDateFormat;
36 import java.util.*;
37
38 public class TestStringTemplate extends TestCase {
39 static final String newline = System.getProperty("line.separator");
40
41 static class ErrorBuffer implements StringTemplateErrorListener {
42 StringBuffer errorOutput = new StringBuffer(500);
43 int n = 0;
44 public void error(String msg, Throwable e) {
45 n++;
46 if ( n>1 ) {
47 errorOutput.append('\n');
48 }
49 if ( e!=null ) {
50 StringWriter duh = new StringWriter();
51 e.printStackTrace(new PrintWriter(duh));
52 errorOutput.append(msg+": "+duh.toString());
53 }
54 else {
55 errorOutput.append(msg);
56 }
57 }
58 public void warning(String msg) {
59 n++;
60 errorOutput.append(msg);
61 }
62 public boolean equals(Object o) {
63 String me = toString();
64 String them = o.toString();
65 return me.equals(them);
66 }
67 public String toString() {
68 return errorOutput.toString();
69 }
70 }
71
72 public void testInterfaceFileFormat() throws Exception {
73 String groupI =
74 "interface test;" +newline+
75 "t();" +newline+
76 "bold(item);"+newline+
77 "optional duh(a,b,c);"+newline;
78 StringTemplateGroupInterface I =
79 new StringTemplateGroupInterface(new StringReader(groupI));
80
81 String expecting =
82 "interface test;\n" +
83 "t();\n" +
84 "bold(item);\n" +
85 "optional duh(a, b, c);\n";
86 assertEquals(expecting,I.toString());
87 }
88
89 public void testNoGroupLoader() throws Exception {
90 // this also tests the group loader
91 StringTemplateErrorListener errors = new ErrorBuffer();
92 String tmpdir = System.getProperty("java.io.tmpdir");
93
94 String templates =
95 "group testG implements blort;" +newline+
96 "t() ::= <<foo>>" +newline+
97 "bold(item) ::= <<foo>>"+newline+
98 "duh(a,b,c) ::= <<foo>>"+newline;
99
100 writeFile(tmpdir, "testG.stg", templates);
101
102 /*StringTemplateGroup group =*/
103 new StringTemplateGroup(new FileReader(tmpdir+"/testG.stg"), errors);
104
105 String expecting = "no group loader registered";
106 assertEquals(expecting,errors.toString());
107 }
108
109 public void testCannotFindInterfaceFile() throws Exception {
110 // this also tests the group loader
111 StringTemplateErrorListener errors = new ErrorBuffer();
112 String tmpdir = System.getProperty("java.io.tmpdir");
113 StringTemplateGroup.registerGroupLoader(new PathGroupLoader(tmpdir,errors));
114
115 String templates =
116 "group testG implements blort;" +newline+
117 "t() ::= <<foo>>" +newline+
118 "bold(item) ::= <<foo>>"+newline+
119 "duh(a,b,c) ::= <<foo>>"+newline;
120
121 writeFile(tmpdir, "testG.stg", templates);
122
123 /*StringTemplateGroup group =*/
124 new StringTemplateGroup(new FileReader(tmpdir+"/testG.stg"), errors);
125
126 String expecting = "no such interface file blort.sti";
127 assertEquals(expecting,errors.toString());
128 }
129
130 public void testMultiDirGroupLoading() throws Exception {
131 // this also tests the group loader
132 StringTemplateErrorListener errors = new ErrorBuffer();
133 String tmpdir = System.getProperty("java.io.tmpdir");
134 if ( !(new File(tmpdir+"/sub").exists()) ) {
135 if ( !(new File(tmpdir+"/sub").mkdir()) ) { // create a subdir
136 System.err.println("can't make subdir in test");
137 return;
138 }
139 }
140 StringTemplateGroup.registerGroupLoader(
141 new PathGroupLoader(tmpdir+":"+tmpdir+"/sub",errors)
142 );
143
144 String templates =
145 "group testG2;" +newline+
146 "t() ::= <<foo>>" +newline+
147 "bold(item) ::= <<foo>>"+newline+
148 "duh(a,b,c) ::= <<foo>>"+newline;
149
150 writeFile(tmpdir+"/sub", "testG2.stg", templates);
151
152 StringTemplateGroup group =
153 StringTemplateGroup.loadGroup("testG2");
154 String expecting = "group testG2;\n" +
155 "bold(item) ::= <<foo>>\n" +
156 "duh(a,b,c) ::= <<foo>>\n" +
157 "t() ::= <<foo>>\n";
158 assertEquals(expecting,group.toString());
159 }
160
161 public void testGroupSatisfiesSingleInterface() throws Exception {
162 // this also tests the group loader
163 StringTemplateErrorListener errors = new ErrorBuffer();
164 String tmpdir = System.getProperty("java.io.tmpdir");
165 StringTemplateGroup.registerGroupLoader(new PathGroupLoader(tmpdir,errors));
166 String groupI =
167 "interface testI;" +newline+
168 "t();" +newline+
169 "bold(item);"+newline+
170 "optional duh(a,b,c);"+newline;
171 writeFile(tmpdir, "testI.sti", groupI);
172
173 String templates =
174 "group testG implements testI;" +newline+
175 "t() ::= <<foo>>" +newline+
176 "bold(item) ::= <<foo>>"+newline+
177 "duh(a,b,c) ::= <<foo>>"+newline;
178
179 writeFile(tmpdir, "testG.stg", templates);
180
181 /*StringTemplateGroup group =*/
182 new StringTemplateGroup(new FileReader(tmpdir+"/testG.stg"), errors);
183
184 String expecting = ""; // should be no errors
185 assertEquals(expecting,errors.toString());
186 }
187
188 public void testGroupExtendsSuperGroup() throws Exception {
189 // this also tests the group loader
190 StringTemplateErrorListener errors = new ErrorBuffer();
191 String tmpdir = System.getProperty("java.io.tmpdir");
192 StringTemplateGroup.registerGroupLoader(
193 new PathGroupLoader(tmpdir,errors)
194 );
195 String superGroup =
196 "group superG;" +newline+
197 "bold(item) ::= <<*$item$*>>;\n"+newline;
198 writeFile(tmpdir, "superG.stg", superGroup);
199
200 String templates =
201 "group testG : superG;" +newline+
202 "main(x) ::= <<$bold(x)$>>"+newline;
203
204 writeFile(tmpdir, "testG.stg", templates);
205
206 StringTemplateGroup group =
207 new StringTemplateGroup(new FileReader(tmpdir+"/testG.stg"),
208 DefaultTemplateLexer.class,
209 errors);
210 StringTemplate st = group.getInstanceOf("main");
211 st.setAttribute("x", "foo");
212
213 String expecting = "*foo*";
214 assertEquals(expecting, st.toString());
215 }
216
217 public void testGroupExtendsSuperGroupWithAngleBrackets() throws Exception {
218 // this also tests the group loader
219 StringTemplateErrorListener errors = new ErrorBuffer();
220 String tmpdir = System.getProperty("java.io.tmpdir");
221 StringTemplateGroup.registerGroupLoader(
222 new PathGroupLoader(tmpdir,errors)
223 );
224 String superGroup =
225 "group superG;" +newline+
226 "bold(item) ::= <<*<item>*>>;\n"+newline;
227 writeFile(tmpdir, "superG.stg", superGroup);
228
229 String templates =
230 "group testG : superG;" +newline+
231 "main(x) ::= \"<bold(x)>\""+newline;
232
233 writeFile(tmpdir, "testG.stg", templates);
234
235 StringTemplateGroup group =
236 new StringTemplateGroup(new FileReader(tmpdir+"/testG.stg"),
237 errors);
238 StringTemplate st = group.getInstanceOf("main");
239 st.setAttribute("x", "foo");
240
241 String expecting = "*foo*";
242 assertEquals(expecting, st.toString());
243 }
244
245 public void testMissingInterfaceTemplate() throws Exception {
246 // this also tests the group loader
247 StringTemplateErrorListener errors = new ErrorBuffer();
248 String tmpdir = System.getProperty("java.io.tmpdir");
249 StringTemplateGroup.registerGroupLoader(new PathGroupLoader(tmpdir,errors));
250 String groupI =
251 "interface testI;" +newline+
252 "t();" +newline+
253 "bold(item);"+newline+
254 "optional duh(a,b,c);"+newline;
255 writeFile(tmpdir, "testI.sti", groupI);
256
257 String templates =
258 "group testG implements testI;" +newline+
259 "t() ::= <<foo>>" +newline+
260 "duh(a,b,c) ::= <<foo>>"+newline;
261
262 writeFile(tmpdir, "testG.stg", templates);
263
264 /*StringTemplateGroup group =*/
265 new StringTemplateGroup(new FileReader(tmpdir+"/testG.stg"), errors);
266
267 String expecting = "group testG does not satisfy interface testI: missing templates [bold]";
268 assertEquals(expecting, errors.toString());
269 }
270
271 public void testMissingOptionalInterfaceTemplate() throws Exception {
272 // this also tests the group loader
273 StringTemplateErrorListener errors = new ErrorBuffer();
274 String tmpdir = System.getProperty("java.io.tmpdir");
275 StringTemplateGroup.registerGroupLoader(new PathGroupLoader(tmpdir,errors));
276 String groupI =
277 "interface testI;" +newline+
278 "t();" +newline+
279 "bold(item);"+newline+
280 "optional duh(a,b,c);"+newline;
281 writeFile(tmpdir, "testI.sti", groupI);
282
283 String templates =
284 "group testG implements testI;" +newline+
285 "t() ::= <<foo>>" +newline+
286 "bold(item) ::= <<foo>>";
287
288 writeFile(tmpdir, "testG.stg", templates);
289
290 /*StringTemplateGroup group =*/
291 new StringTemplateGroup(new FileReader(tmpdir+"/testG.stg"), errors);
292
293 String expecting = ""; // should be NO errors
294 assertEquals(expecting, errors.toString());
295 }
296
297 public void testMismatchedInterfaceTemplate() throws Exception {
298 // this also tests the group loader
299 StringTemplateErrorListener errors = new ErrorBuffer();
300 String tmpdir = System.getProperty("java.io.tmpdir");
301 StringTemplateGroup.registerGroupLoader(new PathGroupLoader(tmpdir,errors));
302 String groupI =
303 "interface testI;" +newline+
304 "t();" +newline+
305 "bold(item);"+newline+
306 "optional duh(a,b,c);"+newline;
307 writeFile(tmpdir, "testI.sti", groupI);
308
309 String templates =
310 "group testG implements testI;" +newline+
311 "t() ::= <<foo>>" +newline+
312 "bold(item) ::= <<foo>>"+newline+
313 "duh(a,c) ::= <<foo>>"+newline;
314
315 writeFile(tmpdir, "testG.stg", templates);
316
317 /*StringTemplateGroup group =*/
318 new StringTemplateGroup(new FileReader(tmpdir+"/testG.stg"), errors);
319
320 String expecting = "group testG does not satisfy interface testI: mismatched arguments on these templates [optional duh(a, b, c)]";
321 assertEquals(expecting,errors.toString());
322 }
323
324 public void testGroupFileFormat() throws Exception {
325 String templates =
326 "group test;" +newline+
327 "t() ::= \"literal template\"" +newline+
328 "bold(item) ::= \"<b>$item$</b>\""+newline+
329 "duh() ::= <<"+newline+"xx"+newline+">>"+newline;
330 StringTemplateGroup group =
331 new StringTemplateGroup(new StringReader(templates),
332 DefaultTemplateLexer.class);
333
334 String expecting = "group test;" +newline+
335 "bold(item) ::= <<<b>$item$</b>>>" +newline+
336 "duh() ::= <<xx>>" +newline+
337 "t() ::= <<literal template>>"+newline;
338 assertEquals(expecting,group.toString());
339
340 StringTemplate a = group.getInstanceOf("t");
341 expecting = "literal template";
342 assertEquals(expecting,a.toString());
343
344 StringTemplate b = group.getInstanceOf("bold");
345 b.setAttribute("item", "dork");
346 expecting = "<b>dork</b>";
347 assertEquals(expecting,b.toString());
348 }
349
350 public void testEscapedTemplateDelimiters() throws Exception {
351 String templates =
352 "group test;" +newline+
353 "t() ::= <<$\"literal\":{a|$a$\\}}$ template\n>>" +newline+
354 "bold(item) ::= <<<b>$item$</b\\>>>"+newline+
355 "duh() ::= <<"+newline+"xx"+newline+">>"+newline;
356 StringTemplateGroup group =
357 new StringTemplateGroup(new StringReader(templates),
358 DefaultTemplateLexer.class);
359
360 String expecting = "group test;" +newline+
361 "bold(item) ::= <<<b>$item$</b>>>" +newline+
362 "duh() ::= <<xx>>" +newline+
363 "t() ::= <<$\"literal\":{a|$a$\\}}$ template>>"+newline;
364 assertEquals(expecting,group.toString());
365
366 StringTemplate b = group.getInstanceOf("bold");
367 b.setAttribute("item", "dork");
368 expecting = "<b>dork</b>";
369 assertEquals(expecting,b.toString());
370
371 StringTemplate a = group.getInstanceOf("t");
372 expecting = "literal} template";
373 assertEquals(expecting,a.toString());
374 }
375
376 /** Check syntax and setAttribute-time errors */
377 public void testTemplateParameterDecls() throws Exception {
378 String templates =
379 "group test;" +newline+
380 "t() ::= \"no args but ref $foo$\"" +newline+
381 "t2(item) ::= \"decl but not used is ok\""+newline +
382 "t3(a,b,c,d) ::= <<$a$ $d$>>"+newline+
383 "t4(a,b,c,d) ::= <<$a$ $b$ $c$ $d$>>"+newline
384 ;
385 StringTemplateGroup group =
386 new StringTemplateGroup(new StringReader(templates),
387 DefaultTemplateLexer.class);
388
389 // check setting unknown arg in empty formal list
390 StringTemplate a = group.getInstanceOf("t");
391 String error = null;
392 try {
393 a.setAttribute("foo", "x"); // want NoSuchElementException
394 }
395 catch (NoSuchElementException e) {
396 error = e.getMessage();
397 }
398 String expecting = "no such attribute: foo in template context [t]";
399 assertEquals(expecting,error);
400
401 // check setting known arg
402 a = group.getInstanceOf("t2");
403 a.setAttribute("item", "x"); // shouldn't get exception
404
405 // check setting unknown arg in nonempty list of formal args
406 a = group.getInstanceOf("t3");
407 a.setAttribute("b", "x");
408 }
409
410 public void testTemplateRedef() throws Exception {
411 String templates =
412 "group test;" +newline+
413 "a() ::= \"x\"" +newline+
414 "b() ::= \"y\"" +newline+
415 "a() ::= \"z\"" +newline;
416 StringTemplateErrorListener errors = new ErrorBuffer();
417 /*StringTemplateGroup group =*/
418 new StringTemplateGroup(new StringReader(templates), errors);
419 String expecting = "redefinition of template: a";
420 assertEquals(expecting,errors.toString());
421 }
422
423 public void testMissingInheritedAttribute() throws Exception {
424 String templates =
425 "group test;" +newline+
426 "page(title,font) ::= <<"+newline +
427 "<html>"+newline +
428 "<body>"+newline +
429 "$title$<br>"+newline +
430 "$body()$"+newline +
431 "</body>"+newline +
432 "</html>"+newline +
433 ">>"+newline +
434 "body() ::= \"<font face=$font$>my body</font>\"" +newline;
435 StringTemplateGroup group =
436 new StringTemplateGroup(new StringReader(templates),
437 DefaultTemplateLexer.class);
438 StringTemplate t = group.getInstanceOf("page");
439 t.setAttribute("title","my title");
440 t.setAttribute("font","Helvetica"); // body() will see it
441 t.toString(); // should be no problem
442 }
443
444 public void testFormalArgumentAssignment() throws Exception {
445 String templates =
446 "group test;" +newline+
447 "page() ::= <<$body(font=\"Times\")$>>"+newline +
448 "body(font) ::= \"<font face=$font$>my body</font>\"" +newline;
449 StringTemplateGroup group =
450 new StringTemplateGroup(new StringReader(templates),
451 DefaultTemplateLexer.class);
452 StringTemplate t = group.getInstanceOf("page");
453 String expecting = "<font face=Times>my body</font>";
454 assertEquals(expecting, t.toString());
455 }
456
457 public void testUndefinedArgumentAssignment() throws Exception {
458 String templates =
459 "group test;" +newline+
460 "page(x) ::= <<$body(font=x)$>>"+newline +
461 "body() ::= \"<font face=$font$>my body</font>\"" +newline;
462 StringTemplateGroup group =
463 new StringTemplateGroup(new StringReader(templates),
464 DefaultTemplateLexer.class);
465 StringTemplate t = group.getInstanceOf("page");
466 t.setAttribute("x","Times");
467 String error = "";
468 try {
469 t.toString();
470 }
471 catch (NoSuchElementException iae) {
472 error = iae.getMessage();
473 }
474 String expecting = "template body has no such attribute: font in template context [page <invoke body arg context>]";
475 assertEquals(expecting, error);
476 }
477
478 public void testFormalArgumentAssignmentInApply() throws Exception {
479 String templates =
480 "group test;" +newline+
481 "page(name) ::= <<$name:bold(font=\"Times\")$>>"+newline +
482 "bold(font) ::= \"<font face=$font$><b>$it$</b></font>\"" +newline;
483 StringTemplateGroup group =
484 new StringTemplateGroup(new StringReader(templates),
485 DefaultTemplateLexer.class);
486 StringTemplate t = group.getInstanceOf("page");
487 t.setAttribute("name", "Ter");
488 String expecting = "<font face=Times><b>Ter</b></font>";
489 assertEquals(expecting, t.toString());
490 }
491
492 public void testUndefinedArgumentAssignmentInApply() throws Exception {
493 String templates =
494 "group test;" +newline+
495 "page(name,x) ::= <<$name:bold(font=x)$>>"+newline +
496 "bold() ::= \"<font face=$font$><b>$it$</b></font>\"" +newline;
497 StringTemplateGroup group =
498 new StringTemplateGroup(new StringReader(templates),
499 DefaultTemplateLexer.class);
500 StringTemplate t = group.getInstanceOf("page");
501 t.setAttribute("x","Times");
502 t.setAttribute("name", "Ter");
503 String error = "";
504 try {
505 t.toString();
506 }
507 catch (NoSuchElementException iae) {
508 error = iae.getMessage();
509 }
510 String expecting = "template bold has no such attribute: font in template context [page <invoke bold arg context>]";
511 assertEquals(expecting,error);
512 }
513
514 public void testUndefinedAttributeReference() throws Exception {
515 String templates =
516 "group test;" +newline+
517 "page() ::= <<$bold()$>>"+newline +
518 "bold() ::= \"$name$\"" +newline;
519 StringTemplateGroup group =
520 new StringTemplateGroup(new StringReader(templates),
521 DefaultTemplateLexer.class);
522 StringTemplate t = group.getInstanceOf("page");
523 String error = "";
524 try {
525 t.toString();
526 }
527 catch (NoSuchElementException iae) {
528 error = iae.getMessage();
529 }
530 String expecting = "no such attribute: name in template context [page bold]";
531 assertEquals(expecting,error);
532 }
533
534 public void testUndefinedDefaultAttributeReference() throws Exception {
535 String templates =
536 "group test;" +newline+
537 "page() ::= <<$bold()$>>"+newline +
538 "bold() ::= \"$it$\"" +newline;
539 StringTemplateGroup group =
540 new StringTemplateGroup(new StringReader(templates),
541 DefaultTemplateLexer.class);
542 StringTemplate t = group.getInstanceOf("page");
543 String error = "";
544 try {
545 t.toString();
546 }
547 catch (NoSuchElementException nse) {
548 error = nse.getMessage();
549 }
550 String expecting = "no such attribute: it in template context [page bold]";
551 assertEquals(expecting,error);
552 }
553
554 public void testAngleBracketsWithGroupFile() throws Exception {
555 String templates =
556 "group test;" +newline+
557 "a(s) ::= \"<s:{case <i> : <it> break;}>\""+newline +
558 "b(t) ::= \"<t; separator=\\\",\\\">\"" +newline+
559 "c(t) ::= << <t; separator=\",\"> >>" +newline;
560 // mainly testing to ensure we don't get parse errors of above
561 StringTemplateGroup group =
562 new StringTemplateGroup(
563 new StringReader(templates));
564 StringTemplate t = group.getInstanceOf("a");
565 t.setAttribute("s","Test");
566 String expecting = "case 1 : Test break;";
567 assertEquals(expecting, t.toString());
568 }
569
570 public void testAngleBracketsNoGroup() throws Exception {
571 StringTemplate st =new StringTemplate(
572 "Tokens : <rules; separator=\"|\"> ;",
573 AngleBracketTemplateLexer.class);
574 st.setAttribute("rules", "A");
575 st.setAttribute("rules", "B");
576 String expecting = "Tokens : A|B ;";
577 assertEquals(expecting, st.toString());
578 }
579
580 public void testRegionRef() throws Exception {
581 String templates =
582 "group test;" +newline+
583 "a() ::= \"X$@r()$Y\"" +newline;
584 StringTemplateGroup group =
585 new StringTemplateGroup(new StringReader(templates),
586 DefaultTemplateLexer.class);
587 StringTemplate st = group.getInstanceOf("a");
588 String result = st.toString();
589 String expecting = "XY";
590 assertEquals(expecting, result);
591 }
592
593 public void testEmbeddedRegionRef() throws Exception {
594 String templates =
595 "group test;" +newline+
596 "a() ::= \"X$@r$blort$@end$Y\"" +newline;
597 StringTemplateGroup group =
598 new StringTemplateGroup(new StringReader(templates),
599 DefaultTemplateLexer.class);
600 StringTemplate st = group.getInstanceOf("a");
601 String result = st.toString();
602 String expecting = "XblortY";
603 assertEquals(expecting, result);
604 }
605
606 public void testRegionRefAngleBrackets() throws Exception {
607 String templates =
608 "group test;" +newline+
609 "a() ::= \"X<@r()>Y\"" +newline;
610 StringTemplateGroup group =
611 new StringTemplateGroup(new StringReader(templates));
612 StringTemplate st = group.getInstanceOf("a");
613 String result = st.toString();
614 String expecting = "XY";
615 assertEquals(expecting, result);
616 }
617
618 public void testEmbeddedRegionRefAngleBrackets() throws Exception {
619 String templates =
620 "group test;" +newline+
621 "a() ::= \"X<@r>blort<@end>Y\"" +newline;
622 StringTemplateGroup group =
623 new StringTemplateGroup(new StringReader(templates));
624 StringTemplate st = group.getInstanceOf("a");
625 String result = st.toString();
626 String expecting = "XblortY";
627 assertEquals(expecting, result);
628 }
629
630 // FIXME: This test fails due to inserted white space...
631 public void testEmbeddedRegionRefWithNewlinesAngleBrackets() throws Exception {
632 String templates =
633 "group test;" +newline+
634 "a() ::= \"X<@r>" +newline+
635 "blort" +newline+
636 "<@end>" +newline+
637 "Y\"" +newline;
638 StringTemplateGroup group =
639 new StringTemplateGroup(new StringReader(templates));
640 StringTemplate st = group.getInstanceOf("a");
641 String result = st.toString();
642 String expecting = "XblortY";
643 assertEquals(expecting, result);
644 }
645
646 public void testRegionRefWithDefAngleBrackets() throws Exception {
647 String templates =
648 "group test;" +newline+
649 "a() ::= \"X<@r()>Y\"" +newline+
650 "@a.r() ::= \"foo\"" +newline;
651 StringTemplateGroup group =
652 new StringTemplateGroup(new StringReader(templates));
653 StringTemplate st = group.getInstanceOf("a");
654 String result = st.toString();
655 String expecting = "XfooY";
656 assertEquals(expecting, result);
657 }
658
659 public void testRegionRefWithDefInConditional() throws Exception {
660 String templates =
661 "group test;" +newline+
662 "a(v) ::= \"X<if(v)>A<@r()>B<endif>Y\"" +newline+
663 "@a.r() ::= \"foo\"" +newline;
664 StringTemplateGroup group =
665 new StringTemplateGroup(new StringReader(templates));
666 StringTemplate st = group.getInstanceOf("a");
667 st.setAttribute("v", "true");
668 String result = st.toString();
669 String expecting = "XAfooBY";
670 assertEquals(expecting, result);
671 }
672
673 public void testRegionRefWithImplicitDefInConditional() throws Exception {
674 String templates =
675 "group test;" +newline+
676 "a(v) ::= \"X<if(v)>A<@r>yo<@end>B<endif>Y\"" +newline+
677 "@a.r() ::= \"foo\"" +newline;
678 StringTemplateErrorListener errors = new ErrorBuffer();
679 StringTemplateGroup group =
680 new StringTemplateGroup(new StringReader(templates),
681 errors);
682 StringTemplate st = group.getInstanceOf("a");
683 st.setAttribute("v", "true");
684 String result = st.toString();
685 String expecting = "XAyoBY";
686 assertEquals(expecting, result);
687
688 String err_result = errors.toString();
689 String err_expecting = "group test line 3: redefinition of template region: @a.r";
690 assertEquals(err_expecting,err_result);
691 }
692
693 public void testRegionOverride() throws Exception {
694 String templates1 =
695 "group super;" +newline+
696 "a() ::= \"X<@r()>Y\"" +
697 "@a.r() ::= \"foo\"" +newline;
698 StringTemplateGroup group =
699 new StringTemplateGroup(new StringReader(templates1));
700
701 String templates2 =
702 "group sub;" +newline+
703 "@a.r() ::= \"foo\"" +newline;
704 StringTemplateGroup subGroup =
705 new StringTemplateGroup(new StringReader(templates2),
706 AngleBracketTemplateLexer.class,
707 null,
708 group);
709
710 StringTemplate st = subGroup.getInstanceOf("a");
711 String result = st.toString();
712 String expecting = "XfooY";
713 assertEquals(expecting, result);
714 }
715
716 public void testRegionOverrideRefSuperRegion() throws Exception {
717 String templates1 =
718 "group super;" +newline+
719 "a() ::= \"X<@r()>Y\"" +
720 "@a.r() ::= \"foo\"" +newline;
721 StringTemplateGroup group =
722 new StringTemplateGroup(new StringReader(templates1));
723
724 String templates2 =
725 "group sub;" +newline+
726 "@a.r() ::= \"A<@super.r()>B\"" +newline;
727 StringTemplateGroup subGroup =
728 new StringTemplateGroup(new StringReader(templates2),
729 AngleBracketTemplateLexer.class,
730 null,
731 group);
732
733 StringTemplate st = subGroup.getInstanceOf("a");
734 String result = st.toString();
735 String expecting = "XAfooBY";
736 assertEquals(expecting, result);
737 }
738
739 public void testRegionOverrideRefSuperRegion3Levels() throws Exception {
740 // Bug: This was causing infinite recursion:
741 // getInstanceOf(super::a)
742 // getInstanceOf(sub::a)
743 // getInstanceOf(subsub::a)
744 // getInstanceOf(subsub::region__a__r)
745 // getInstanceOf(subsub::super.region__a__r)
746 // getInstanceOf(subsub::super.region__a__r)
747 // getInstanceOf(subsub::super.region__a__r)
748 // ...
749 // Somehow, the ref to super in subsub is not moving up the chain
750 // to the @super.r(); oh, i introduced a bug when i put setGroup
751 // into STG.getInstanceOf()!
752
753 String templates1 =
754 "group super;" +newline+
755 "a() ::= \"X<@r()>Y\"" +
756 "@a.r() ::= \"foo\"" +newline;
757 StringTemplateGroup group =
758 new StringTemplateGroup(new StringReader(templates1));
759
760 String templates2 =
761 "group sub;" +newline+
762 "@a.r() ::= \"<@super.r()>2\"" +newline;
763 StringTemplateGroup subGroup =
764 new StringTemplateGroup(new StringReader(templates2),
765 AngleBracketTemplateLexer.class,
766 null,
767 group);
768
769 String templates3 =
770 "group subsub;" +newline+
771 "@a.r() ::= \"<@super.r()>3\"" +newline;
772 StringTemplateGroup subSubGroup =
773 new StringTemplateGroup(new StringReader(templates3),
774 AngleBracketTemplateLexer.class,
775 null,
776 subGroup);
777
778 StringTemplate st = subSubGroup.getInstanceOf("a");
779 String result = st.toString();
780 String expecting = "Xfoo23Y";
781 assertEquals(expecting, result);
782 }
783
784 public void testRegionOverrideRefSuperImplicitRegion() throws Exception {
785 String templates1 =
786 "group super;" +newline+
787 "a() ::= \"X<@r>foo<@end>Y\""+newline;
788 StringTemplateGroup group =
789 new StringTemplateGroup(new StringReader(templates1));
790
791 String templates2 =
792 "group sub;" +newline+
793 "@a.r() ::= \"A<@super.r()>\"" +newline;
794 StringTemplateGroup subGroup =
795 new StringTemplateGroup(new StringReader(templates2),
796 AngleBracketTemplateLexer.class,
797 null,
798 group);
799
800 StringTemplate st = subGroup.getInstanceOf("a");
801 String result = st.toString();
802 String expecting = "XAfooY";
803 assertEquals(expecting, result);
804 }
805
806 public void testEmbeddedRegionRedefError() throws Exception {
807 // cannot define an embedded template within group
808 String templates =
809 "group test;" +newline+
810 "a() ::= \"X<@r>dork<@end>Y\"" +
811 "@a.r() ::= \"foo\"" +newline;
812 StringTemplateErrorListener errors = new ErrorBuffer();
813 StringTemplateGroup group =
814 new StringTemplateGroup(new StringReader(templates),
815 errors);
816 StringTemplate st = group.getInstanceOf("a");
817 st.toString();
818 String result = errors.toString();
819 String expecting = "group test line 2: redefinition of template region: @a.r";
820 assertEquals(expecting, result);
821 }
822
823 public void testImplicitRegionRedefError() throws Exception {
824 // cannot define an implicitly-defined template more than once
825 String templates =
826 "group test;" +newline+
827 "a() ::= \"X<@r()>Y\"" +newline+
828 "@a.r() ::= \"foo\"" +newline+
829 "@a.r() ::= \"bar\"" +newline;
830 StringTemplateErrorListener errors = new ErrorBuffer();
831 StringTemplateGroup group =
832 new StringTemplateGroup(new StringReader(templates),
833 errors);
834 StringTemplate st = group.getInstanceOf("a");
835 st.toString();
836 String result = errors.toString();
837 String expecting = "group test line 4: redefinition of template region: @a.r";
838 assertEquals(expecting, result);
839 }
840
841 public void testImplicitOverriddenRegionRedefError() throws Exception {
842 String templates1 =
843 "group super;" +newline+
844 "a() ::= \"X<@r()>Y\"" +
845 "@a.r() ::= \"foo\"" +newline;
846 StringTemplateGroup group =
847 new StringTemplateGroup(new StringReader(templates1));
848
849 String templates2 =
850 "group sub;" +newline+
851 "@a.r() ::= \"foo\"" +newline+
852 "@a.r() ::= \"bar\"" +newline;
853 StringTemplateErrorListener errors = new ErrorBuffer();
854 StringTemplateGroup subGroup =
855 new StringTemplateGroup(new StringReader(templates2),
856 AngleBracketTemplateLexer.class,
857 errors,
858 group);
859
860 /*StringTemplate st =*/ subGroup.getInstanceOf("a");
861 String result = errors.toString();
862 String expecting = "group sub line 3: redefinition of template region: @a.r";
863 assertEquals(expecting, result);
864 }
865
866 public void testUnknownRegionDefError() throws Exception {
867 // cannot define an implicitly-defined template more than once
868 String templates =
869 "group test;" +newline+
870 "a() ::= \"X<@r()>Y\"" +newline+
871 "@a.q() ::= \"foo\"" +newline;
872 StringTemplateErrorListener errors = new ErrorBuffer();
873 StringTemplateGroup group =
874 new StringTemplateGroup(new StringReader(templates),
875 errors);
876 StringTemplate st = group.getInstanceOf("a");
877 st.toString();
878 String result = errors.toString();
879 String expecting = "group test line 3: template a has no region called q";
880 assertEquals(expecting, result);
881 }
882
883 public void testSuperRegionRefError() throws Exception {
884 String templates1 =
885 "group super;" +newline+
886 "a() ::= \"X<@r()>Y\"" +
887 "@a.r() ::= \"foo\"" +newline;
888 StringTemplateGroup group =
889 new StringTemplateGroup(new StringReader(templates1));
890
891 String templates2 =
892 "group sub;" +newline+
893 "@a.r() ::= \"A<@super.q()>B\"" +newline;
894 StringTemplateErrorListener errors = new ErrorBuffer();
895 StringTemplateGroup subGroup =
896 new StringTemplateGroup(new StringReader(templates2),
897 AngleBracketTemplateLexer.class,
898 errors,
899 group);
900
901 /*StringTemplate st =*/ subGroup.getInstanceOf("a");
902 String result = errors.toString();
903 String expecting = "template a has no region called q";
904 assertEquals(expecting, result);
905 }
906
907 public void testMissingEndRegionError() throws Exception {
908 // cannot define an implicitly-defined template more than once
909 String templates =
910 "group test;" +newline+
911 "a() ::= \"X$@r$foo\"" +newline;
912 StringTemplateErrorListener errors = new ErrorBuffer();
913 StringTemplateGroup group =
914 new StringTemplateGroup(new StringReader(templates),
915 DefaultTemplateLexer.class,
916 errors,
917 null);
918 StringTemplate st = group.getInstanceOf("a");
919 st.toString();
920 String result = errors.toString();
921 String expecting = "missing region r $@end$ tag";
922 assertEquals(expecting, result);
923 }
924
925 public void testMissingEndRegionErrorAngleBrackets() throws Exception {
926 // cannot define an implicitly-defined template more than once
927 String templates =
928 "group test;" +newline+
929 "a() ::= \"X<@r>foo\"" +newline;
930 StringTemplateErrorListener errors = new ErrorBuffer();
931 StringTemplateGroup group =
932 new StringTemplateGroup(new StringReader(templates),
933 errors);
934 StringTemplate st = group.getInstanceOf("a");
935 st.toString();
936 String result = errors.toString();
937 String expecting = "missing region r <@end> tag";
938 assertEquals(expecting, result);
939 }
940
941 public void testSimpleInheritance() throws Exception {
942 // make a bold template in the super group that you can inherit from sub
943 StringTemplateGroup supergroup = new StringTemplateGroup("super");
944 StringTemplateGroup subgroup = new StringTemplateGroup("sub");
945 /*StringTemplate bold =*/ supergroup.defineTemplate("bold", "<b>$it$</b>");
946 subgroup.setSuperGroup(supergroup);
947 StringTemplateErrorListener errors = new ErrorBuffer();
948 subgroup.setErrorListener(errors);
949 supergroup.setErrorListener(errors);
950 StringTemplate duh = new StringTemplate(subgroup, "$name:bold()$");
951 duh.setAttribute("name", "Terence");
952 String expecting = "<b>Terence</b>";
953 assertEquals(expecting,duh.toString());
954 }
955
956 public void testOverrideInheritance() throws Exception {
957 // make a bold template in the super group and one in sub group
958 StringTemplateGroup supergroup = new StringTemplateGroup("super");
959 StringTemplateGroup subgroup = new StringTemplateGroup("sub");
960 supergroup.defineTemplate("bold", "<b>$it$</b>");
961 subgroup.defineTemplate("bold", "<strong>$it$</strong>");
962 subgroup.setSuperGroup(supergroup);
963 StringTemplateErrorListener errors = new ErrorBuffer();
964 subgroup.setErrorListener(errors);
965 supergroup.setErrorListener(errors);
966 StringTemplate duh = new StringTemplate(subgroup, "$name:bold()$");
967 duh.setAttribute("name", "Terence");
968 String expecting = "<strong>Terence</strong>";
969 assertEquals(expecting,duh.toString());
970 }
971
972 public void testMultiLevelInheritance() throws Exception {
973 // must loop up two levels to find bold()
974 StringTemplateGroup rootgroup = new StringTemplateGroup("root");
975 StringTemplateGroup level1 = new StringTemplateGroup("level1");
976 StringTemplateGroup level2 = new StringTemplateGroup("level2");
977 rootgroup.defineTemplate("bold", "<b>$it$</b>");
978 level1.setSuperGroup(rootgroup);
979 level2.setSuperGroup(level1);
980 StringTemplateErrorListener errors = new ErrorBuffer();
981 rootgroup.setErrorListener(errors);
982 level1.setErrorListener(errors);
983 level2.setErrorListener(errors);
984 StringTemplate duh = new StringTemplate(level2, "$name:bold()$");
985 duh.setAttribute("name", "Terence");
986 String expecting = "<b>Terence</b>";
987 assertEquals(expecting,duh.toString());
988 }
989
990 public void testComplicatedInheritance() throws Exception {
991 // in super: decls invokes labels
992 // in sub: overridden decls which calls super.decls
993 // overridden labels
994 // Bug: didn't see the overridden labels. In other words,
995 // the overridden decls called super which called labels, but
996 // didn't get the subgroup overridden labels--it calls the
997 // one in the superclass. Ouput was "DL" not "DSL"; didn't
998 // invoke sub's labels().
999 String basetemplates =
1000 "group base;" +newline+
1001 "decls() ::= \"D<labels()>\""+newline+
1002 "labels() ::= \"L\"" +newline
1003 ;
1004 StringTemplateGroup base =
1005 new StringTemplateGroup(new StringReader(basetemplates));
1006 String subtemplates =
1007 "group sub;" +newline+
1008 "decls() ::= \"<super.decls()>\""+newline+
1009 "labels() ::= \"SL\"" +newline
1010 ;
1011 StringTemplateGroup sub =
1012 new StringTemplateGroup(new StringReader(subtemplates));
1013 sub.setSuperGroup(base);
1014 StringTemplate st = sub.getInstanceOf("decls");
1015 String expecting = "DSL";
1016 String result = st.toString();
1017 assertEquals(expecting, result);
1018 }
1019
1020 public void test3LevelSuperRef() throws Exception {
1021 String templates1 =
1022 "group super;" +newline+
1023 "r() ::= \"foo\"" +newline;
1024 StringTemplateGroup group =
1025 new StringTemplateGroup(new StringReader(templates1));
1026
1027 String templates2 =
1028 "group sub;" +newline+
1029 "r() ::= \"<super.r()>2\"" +newline;
1030 StringTemplateGroup subGroup =
1031 new StringTemplateGroup(new StringReader(templates2),
1032 AngleBracketTemplateLexer.class,
1033 null,
1034 group);
1035
1036 String templates3 =
1037 "group subsub;" +newline+
1038 "r() ::= \"<super.r()>3\"" +newline;
1039 StringTemplateGroup subSubGroup =
1040 new StringTemplateGroup(new StringReader(templates3),
1041 AngleBracketTemplateLexer.class,
1042 null,
1043 subGroup);
1044
1045 StringTemplate st = subSubGroup.getInstanceOf("r");
1046 String result = st.toString();
1047 String expecting = "foo23";
1048 assertEquals(expecting, result);
1049 }
1050
1051 public void testExprInParens() throws Exception {
1052 // specify a template to apply to an attribute
1053 // Use a template group so we can specify the start/stop chars
1054 StringTemplateGroup group =
1055 new StringTemplateGroup("dummy", ".");
1056 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$it$</b>");
1057 StringTemplate duh = new StringTemplate(group, "$(\"blort: \"+(list)):bold()$");
1058 duh.setAttribute("list", "a");
1059 duh.setAttribute("list", "b");
1060 duh.setAttribute("list", "c");
1061 // System.out.println(duh);
1062 String expecting = "<b>blort: abc</b>";
1063 assertEquals(expecting, duh.toString());
1064 }
1065
1066 public void testMultipleAdditions() throws Exception {
1067 // specify a template to apply to an attribute
1068 // Use a template group so we can specify the start/stop chars
1069 StringTemplateGroup group =
1070 new StringTemplateGroup("dummy", ".");
1071 group.defineTemplate("link", "<a href=\"$url$\"><b>$title$</b></a>");
1072 StringTemplate duh =
1073 new StringTemplate(group,
1074 "$link(url=\"/member/view?ID=\"+ID+\"&x=y\"+foo, title=\"the title\")$");
1075 duh.setAttribute("ID", "3321");
1076 duh.setAttribute("foo", "fubar");
1077 String expecting = "<a href=\"/member/view?ID=3321&x=yfubar\"><b>the title</b></a>";
1078 assertEquals(expecting, duh.toString());
1079 }
1080
1081 public void testCollectionAttributes() throws Exception {
1082 StringTemplateGroup group =
1083 new StringTemplateGroup("test");
1084 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$it$</b>");
1085 StringTemplate t =
1086 new StringTemplate(group, "$data$, $data:bold()$, "+
1087 "$list:bold():bold()$, $array$, $a2$, $a3$, $a4$");
1088 Vector v = new Vector();
1089 v.addElement("1");
1090 v.addElement("2");
1091 v.addElement("3");
1092 List list = new ArrayList();
1093 list.add("a");
1094 list.add("b");
1095 list.add("c");
1096 t.setAttribute("data", v);
1097 t.setAttribute("list", list);
1098 t.setAttribute("array", new String[] {"x","y"});
1099 t.setAttribute("a2", new int[] {10,20});
1100 t.setAttribute("a3", new float[] {1.2f,1.3f});
1101 t.setAttribute("a4", new double[] {8.7,9.2});
1102 //System.out.println(t);
1103 String expecting="123, <b>1</b><b>2</b><b>3</b>, "+
1104 "<b><b>a</b></b><b><b>b</b></b><b><b>c</b></b>, xy, 1020, 1.21.3, 8.79.2";
1105 assertEquals(expecting, t.toString());
1106 }
1107
1108 public void testParenthesizedExpression() throws Exception {
1109 StringTemplateGroup group =
1110 new StringTemplateGroup("test");
1111 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$it$</b>");
1112 StringTemplate t = new StringTemplate(group, "$(f+l):bold()$");
1113 t.setAttribute("f", "Joe");
1114 t.setAttribute("l", "Schmoe");
1115 //System.out.println(t);
1116 String expecting="<b>JoeSchmoe</b>";
1117 assertEquals(expecting, t.toString());
1118 }
1119
1120 public void testApplyTemplateNameExpression() throws Exception {
1121 StringTemplateGroup group =
1122 new StringTemplateGroup("test");
1123 /* StringTemplate bold =*/ group.defineTemplate("foobar", "foo$attr$bar");
1124 StringTemplate t = new StringTemplate(group, "$data:(name+\"bar\")()$");
1125 t.setAttribute("data", "Ter");
1126 t.setAttribute("data", "Tom");
1127 t.setAttribute("name", "foo");
1128 //System.out.println(t);
1129 String expecting="fooTerbarfooTombar";
1130 assertEquals(expecting, t.toString());
1131 }
1132
1133 public void testApplyTemplateNameTemplateEval() throws Exception {
1134 StringTemplateGroup group =
1135 new StringTemplateGroup("test");
1136 /*StringTemplate foobar =*/ group.defineTemplate("foobar", "foo$it$bar");
1137 /*StringTemplate a =*/ group.defineTemplate("a", "$it$bar");
1138 StringTemplate t = new StringTemplate(group, "$data:(\"foo\":a())()$");
1139 t.setAttribute("data", "Ter");
1140 t.setAttribute("data", "Tom");
1141 //System.out.println(t);
1142 String expecting="fooTerbarfooTombar";
1143 assertEquals(expecting, t.toString());
1144 }
1145
1146 public void testTemplateNameExpression() throws Exception {
1147 StringTemplateGroup group =
1148 new StringTemplateGroup("test");
1149 /*StringTemplate foo =*/ group.defineTemplate("foo", "hi there!");
1150 StringTemplate t = new StringTemplate(group, "$(name)()$");
1151 t.setAttribute("name", "foo");
1152 //System.out.println(t);
1153 String expecting="hi there!";
1154 assertEquals(expecting, t.toString());
1155 }
1156
1157 public void testMissingEndDelimiter() throws Exception {
1158 StringTemplateGroup group =
1159 new StringTemplateGroup("test");
1160 StringTemplateErrorListener errors = new ErrorBuffer();
1161 group.setErrorListener(errors);
1162 /*StringTemplate t =*/ new StringTemplate(group, "stuff $a then more junk etc...");
1163 String expectingError="problem parsing template 'anonymous': line 1:31: expecting '$', found '<EOF>'";
1164 //System.out.println("error: '"+errors+"'");
1165 //System.out.println("expecting: '"+expectingError+"'");
1166 assertTrue(errors.toString().startsWith(expectingError));
1167 }
1168
1169 public void testSetButNotRefd() throws Exception {
1170 StringTemplate.setLintMode(true);
1171 StringTemplateGroup group =
1172 new StringTemplateGroup("test");
1173 StringTemplate t = new StringTemplate(group, "$a$ then $b$ and $c$ refs.");
1174 t.setAttribute("a", "Terence");
1175 t.setAttribute("b", "Terence");
1176 t.setAttribute("cc", "Terence"); // oops...should be 'c'
1177 StringTemplateErrorListener errors = new ErrorBuffer();
1178 group.setErrorListener(errors);
1179 String expectingError="anonymous: set but not used: cc";
1180 /*String result =*/ t.toString(); // result is irrelevant
1181 //System.out.println("result error: '"+errors+"'");
1182 //System.out.println("expecting: '"+expectingError+"'");
1183 StringTemplate.setLintMode(false);
1184 assertEquals(expectingError,errors.toString());
1185 }
1186
1187 public void testNullTemplateApplication() throws Exception {
1188 StringTemplateGroup group =
1189 new StringTemplateGroup("test");
1190 StringTemplateErrorListener errors = new ErrorBuffer();
1191 group.setErrorListener(errors);
1192 StringTemplate t = new StringTemplate(group, "$names:bold(x=it)$");
1193 t.setAttribute("names", "Terence");
1194
1195 String error = null;
1196 try {
1197 t.toString();
1198 }
1199 catch (IllegalArgumentException iae) {
1200 error = iae.getMessage();
1201 }
1202 String expecting = "Can't find template bold.st; context is [anonymous]; group hierarchy is [test]" ;
1203 assertEquals(expecting,error);
1204 }
1205
1206 public void testNullTemplateToMultiValuedApplication() throws Exception {
1207 StringTemplateGroup group =
1208 new StringTemplateGroup("test");
1209 StringTemplateErrorListener errors = new ErrorBuffer();
1210 group.setErrorListener(errors);
1211 StringTemplate t = new StringTemplate(group, "$names:bold(x=it)$");
1212 t.setAttribute("names", "Terence");
1213 t.setAttribute("names", "Tom");
1214 //System.out.println(t);
1215 String error = null;
1216 try {
1217 t.toString();
1218 }
1219 catch (IllegalArgumentException iae) {
1220 error = iae.getMessage();
1221 }
1222 String expecting = "Can't find template bold.st; context is [anonymous]; group hierarchy is [test]"; // bold not found...empty string
1223 assertEquals(expecting,error);
1224 }
1225
1226 public void testChangingAttrValueTemplateApplicationToVector() throws Exception {
1227 StringTemplateGroup group =
1228 new StringTemplateGroup("test");
1229 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$x$</b>");
1230 StringTemplate t = new StringTemplate(group, "$names:bold(x=it)$");
1231 t.setAttribute("names", "Terence");
1232 t.setAttribute("names", "Tom");
1233 //System.out.println("'"+t.toString()+"'");
1234 String expecting="<b>Terence</b><b>Tom</b>";
1235 assertEquals(expecting, t.toString());
1236 }
1237
1238 public void testChangingAttrValueRepeatedTemplateApplicationToVector() throws Exception {
1239 StringTemplateGroup group =
1240 new StringTemplateGroup("dummy", ".");
1241 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$item$</b>");
1242 /*StringTemplate italics =*/ group.defineTemplate("italics", "<i>$it$</i>");
1243 StringTemplate members =
1244 new StringTemplate(group, "$members:bold(item=it):italics(it=it)$");
1245 members.setAttribute("members", "Jim");
1246 members.setAttribute("members", "Mike");
1247 members.setAttribute("members", "Ashar");
1248 //System.out.println("members="+members);
1249 String expecting = "<i><b>Jim</b></i><i><b>Mike</b></i><i><b>Ashar</b></i>";
1250 assertEquals(expecting,members.toString());
1251 }
1252
1253 public void testAlternatingTemplateApplication() throws Exception {
1254 StringTemplateGroup group =
1255 new StringTemplateGroup("dummy", ".");
1256 /*StringTemplate listItem =*/ group.defineTemplate("listItem", "<li>$it$</li>");
1257 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$it$</b>");
1258 /*StringTemplate italics =*/ group.defineTemplate("italics", "<i>$it$</i>");
1259 StringTemplate item =
1260 new StringTemplate(group, "$item:bold(),italics():listItem()$");
1261 item.setAttribute("item", "Jim");
1262 item.setAttribute("item", "Mike");
1263 item.setAttribute("item", "Ashar");
1264 //System.out.println("ITEM="+item);
1265 String expecting = "<li><b>Jim</b></li><li><i>Mike</i></li><li><b>Ashar</b></li>";
1266 assertEquals(item.toString(), expecting);
1267 }
1268
1269 public void testExpressionAsRHSOfAssignment() throws Exception {
1270 StringTemplateGroup group =
1271 new StringTemplateGroup("test");
1272 /*StringTemplate hostname =*/ group.defineTemplate("hostname", "$machine$.jguru.com");
1273 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$x$</b>");
1274 StringTemplate t = new StringTemplate(group, "$bold(x=hostname(machine=\"www\"))$");
1275 String expecting="<b>www.jguru.com</b>";
1276 assertEquals(expecting, t.toString());
1277 }
1278
1279 public void testTemplateApplicationAsRHSOfAssignment() throws Exception {
1280 StringTemplateGroup group =
1281 new StringTemplateGroup("test");
1282 /*StringTemplate hostname =*/ group.defineTemplate("hostname", "$machine$.jguru.com");
1283 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$x$</b>");
1284 /*StringTemplate italics =*/ group.defineTemplate("italics", "<i>$it$</i>");
1285 StringTemplate t = new StringTemplate(group, "$bold(x=hostname(machine=\"www\"):italics())$");
1286 String expecting="<b><i>www.jguru.com</i></b>";
1287 assertEquals(expecting, t.toString());
1288 }
1289
1290 public void testParameterAndAttributeScoping() throws Exception {
1291 StringTemplateGroup group =
1292 new StringTemplateGroup("test");
1293 /*StringTemplate italics =*/ group.defineTemplate("italics", "<i>$x$</i>");
1294 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$x$</b>");
1295 StringTemplate t = new StringTemplate(group, "$bold(x=italics(x=name))$");
1296 t.setAttribute("name", "Terence");
1297 //System.out.println(t);
1298 String expecting="<b><i>Terence</i></b>";
1299 assertEquals(expecting, t.toString());
1300 }
1301
1302 public void testComplicatedSeparatorExpr() throws Exception {
1303 StringTemplateGroup group =
1304 new StringTemplateGroup("test");
1305 /*StringTemplate bold =*/ group.defineTemplate("bulletSeparator", "</li>$foo$<li>");
1306 // make separator a complicated expression with args passed to included template
1307 StringTemplate t =
1308 new StringTemplate(group,
1309 "<ul>$name; separator=bulletSeparator(foo=\" \")+\"&nbsp;\"$</ul>");
1310 t.setAttribute("name", "Ter");
1311 t.setAttribute("name", "Tom");
1312 t.setAttribute("name", "Mel");
1313 //System.out.println(t);
1314 String expecting = "<ul>Ter</li> <li>&nbsp;Tom</li> <li>&nbsp;Mel</ul>";
1315 assertEquals(expecting, t.toString());
1316 }
1317
1318 public void testAttributeRefButtedUpAgainstEndifAndWhitespace() throws Exception {
1319 StringTemplateGroup group =
1320 new StringTemplateGroup("test");
1321 StringTemplate a = new StringTemplate(group,
1322 "$if (!firstName)$$email$$endif$");
1323 a.setAttribute("email", "parrt@jguru.com");
1324 String expecting = "parrt@jguru.com";
1325 assertEquals(a.toString(), expecting);
1326 }
1327
1328 public void testStringCatenationOnSingleValuedAttributeViaTemplateLiteral() throws Exception {
1329 StringTemplateGroup group =
1330 new StringTemplateGroup("test");
1331 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$it$</b>");
1332 //StringTemplate a = new StringTemplate(group, "$\" Parr\":bold()$");
1333 StringTemplate b = new StringTemplate(group, "$bold(it={$name$ Parr})$");
1334 //a.setAttribute("name", "Terence");
1335 b.setAttribute("name", "Terence");
1336 String expecting = "<b>Terence Parr</b>";
1337 //assertEquals(a.toString(), expecting);
1338 assertEquals(b.toString(), expecting);
1339 }
1340
1341 public void testStringCatenationOpOnArg() throws Exception {
1342 StringTemplateGroup group =
1343 new StringTemplateGroup("test");
1344 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$it$</b>");
1345 StringTemplate b = new StringTemplate(group, "$bold(it=name+\" Parr\")$");
1346 //a.setAttribute("name", "Terence");
1347 b.setAttribute("name", "Terence");
1348 String expecting = "<b>Terence Parr</b>";
1349 //assertEquals(expecting, a.toString());
1350 assertEquals(expecting, b.toString());
1351 }
1352
1353 public void testStringCatenationOpOnArgWithEqualsInString() throws Exception {
1354 StringTemplateGroup group =
1355 new StringTemplateGroup("test");
1356 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$it$</b>");
1357 StringTemplate b = new StringTemplate(group, "$bold(it=name+\" Parr=\")$");
1358 //a.setAttribute("name", "Terence");
1359 b.setAttribute("name", "Terence");
1360 String expecting = "<b>Terence Parr=</b>";
1361 //assertEquals(expecting, a.toString());
1362 assertEquals(expecting, b.toString());
1363 }
1364
1365 public void testApplyingTemplateFromDiskWithPrecompiledIF()
1366 throws Exception
1367 {
1368 // Create a temporary working directory
1369 File tmpDir = new File(System.getProperty("java.io.tmpdir"));
1370 File tmpWorkDir;
1371 int counter = (new Random()).nextInt() & 65535;;
1372 do {
1373 counter++;
1374 StringBuffer name = new StringBuffer("st-junit-");
1375 name.append(counter);
1376 tmpWorkDir = new File(tmpDir, name.toString());
1377 } while (tmpWorkDir.exists());
1378 tmpWorkDir.mkdirs();
1379
1380 // write the template files first to /tmp
1381 File pageFile = new File(tmpWorkDir,"page.st");
1382 FileWriter fw = new FileWriter(pageFile);
1383 fw.write("<html><head>"+newline);
1384 //fw.write(" <title>PeerScope: $title$</title>"+newline);
1385 fw.write("</head>"+newline);
1386 fw.write("<body>"+newline);
1387 fw.write("$if(member)$User: $member:terse()$$endif$"+newline);
1388 fw.write("</body>"+newline);
1389 fw.write("</head>"+newline);
1390 fw.close();
1391
1392 File terseFile = new File(tmpWorkDir,"terse.st");
1393 fw = new FileWriter(terseFile);
1394 fw.write("$it.firstName$ $it.lastName$ (<tt>$it.email$</tt>)"+newline);
1395 fw.close();
1396
1397 // specify a template to apply to an attribute
1398 // Use a template group so we can specify the start/stop chars
1399 StringTemplateGroup group =
1400 new StringTemplateGroup("dummy", tmpWorkDir.toString());
1401
1402 StringTemplate a = group.getInstanceOf("page");
1403 a.setAttribute("member", new Connector());
1404 String expecting = "<html><head>"+newline+
1405 "</head>"+newline+
1406 "<body>"+newline+
1407 "User: Terence Parr (<tt>parrt@jguru.com</tt>)"+newline+
1408 "</body>"+newline+
1409 "</head>";
1410 //System.out.println("'"+a+"'");
1411 assertEquals(expecting, a.toString());
1412
1413 // Cleanup the temp folder.
1414 pageFile.delete();
1415 terseFile.delete();
1416 tmpWorkDir.delete();
1417 }
1418
1419 public void testMultiValuedAttributeWithAnonymousTemplateUsingIndexVariableI()
1420 throws Exception
1421 {
1422 StringTemplateGroup tgroup =
1423 new StringTemplateGroup("dummy", ".");
1424 StringTemplate t =
1425 new StringTemplate(tgroup,
1426 " List:"+newline+" "+newline+"foo"+newline+newline+
1427 "$names:{<br>$i$. $it$"+newline+
1428 "}$");
1429 t.setAttribute("names", "Terence");
1430 t.setAttribute("names", "Jim");
1431 t.setAttribute("names", "Sriram");
1432 //System.out.println(t);
1433 String expecting =
1434 " List:"+newline+
1435 " "+newline+
1436 "foo"+newline+newline+
1437 "<br>1. Terence"+newline+
1438 "<br>2. Jim"+newline+
1439 "<br>3. Sriram"+newline;
1440 assertEquals(expecting, t.toString());
1441 }
1442
1443 public void testFindTemplateInCLASSPATH() throws Exception {
1444 // Look for templates in CLASSPATH as resources
1445 StringTemplateGroup mgroup =
1446 new StringTemplateGroup("method stuff",
1447 AngleBracketTemplateLexer.class);
1448 StringTemplate m = mgroup.getInstanceOf("org/antlr/stringtemplate/test/method");
1449 // "method.st" references body() so "body.st" will be loaded too
1450 m.setAttribute("visibility", "public");
1451 m.setAttribute("name", "foobar");
1452 m.setAttribute("returnType", "void");
1453 m.setAttribute("statements", "i=1;"); // body inherits these from method
1454 m.setAttribute("statements", "x=i;");
1455 String expecting =
1456 "public void foobar() {"+newline+
1457 "\t// start of a body"+newline+
1458 "\ti=1;"+newline+
1459 "\tx=i;"+newline+
1460 "\t// end of a body"+newline+
1461 "}";
1462 //System.out.println(m);
1463 assertEquals(expecting, m.toString());
1464 }
1465
1466 public void testApplyTemplateToSingleValuedAttribute() throws Exception {
1467 StringTemplateGroup group =
1468 new StringTemplateGroup("test");
1469 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$x$</b>");
1470 StringTemplate name = new StringTemplate(group, "$name:bold(x=name)$");
1471 name.setAttribute("name", "Terence");
1472 assertEquals("<b>Terence</b>",name.toString());
1473 }
1474
1475 public void testStringLiteralAsAttribute() throws Exception {
1476 StringTemplateGroup group =
1477 new StringTemplateGroup("test");
1478 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$it$</b>");
1479 StringTemplate name = new StringTemplate(group, "$\"Terence\":bold()$");
1480 assertEquals("<b>Terence</b>",name.toString());
1481 }
1482
1483 public void testApplyTemplateToSingleValuedAttributeWithDefaultAttribute() throws Exception {
1484 StringTemplateGroup group =
1485 new StringTemplateGroup("test");
1486 /*StringTemplate bold =*/ group.defineTemplate("bold", "<b>$it$</b>");
1487 StringTemplate name = new StringTemplate(group, "$name:bold()$");
1488 name.setAttribute("name", "Terence");
1489 assertEquals("<b>Terence</b>",name.toString());
1490 }
1491
1492 public void testApplyAnonymousTemplateToSingleValuedAttribute() throws Exception {
1493 // specify a template to apply to an attribute
1494 // Use a template group so we can specify the start/stop chars
1495 StringTemplateGroup group =
1496 new StringTemplateGroup("dummy", ".");
1497 StringTemplate item =
1498 new StringTemplate(group, "$item:{<li>$it$</li>}$");
1499 item.setAttribute("item", "Terence");
1500 assertEquals("<li>Terence</li>",item.toString());
1501 }
1502
1503 public void testApplyAnonymousTemplateToMultiValuedAttribute() throws Exception {
1504 // specify a template to apply to an attribute
1505 // Use a template group so we can specify the start/stop chars
1506 StringTemplateGroup group =
1507 new StringTemplateGroup("dummy", ".");
1508 StringTemplate list =
1509 new StringTemplate(group, "<ul>$items$</ul>");
1510 // demonstrate setting arg to anonymous subtemplate
1511 StringTemplate item =
1512 new StringTemplate(group, "$item:{<li>$it$</li>}; separator=\",\"$");
1513 item.setAttribute("item", "Terence");
1514 item.setAttribute("item", "Jim");
1515 item.setAttribute("item", "John");
1516 list.setAttribute("items", item); // nested template
1517 String expecting = "<ul><li>Terence</li>,<li>Jim</li>,<li>John</li></ul>";
1518 assertEquals(expecting,list.toString());
1519 }
1520
1521 public void testApplyAnonymousTemplateToAggregateAttribute() throws Exception {
1522 StringTemplate st =
1523 new StringTemplate("$items:{$it.lastName$, $it.firstName$\n}$");
1524 // also testing wacky spaces in aggregate spec
1525 st.setAttribute("items.{ firstName ,lastName}", "Ter", "Parr");
1526 st.setAttribute("items.{firstName, lastName }", "Tom", "Burns");
1527 String expecting =
1528 "Parr, Ter"+newline +
1529 "Burns, Tom"+newline;
1530 assertEquals(expecting, st.toString());
1531 }
1532
1533 public void testRepeatedApplicationOfTemplateToSingleValuedAttribute() throws Exception {
1534 StringTemplateGroup group =
1535 new StringTemplateGroup("dummy", ".");
1536 /*StringTemplate search =*/ group.defineTemplate("bold", "<b>$it$</b>");
1537 StringTemplate item =
1538 new StringTemplate(group, "$item:bold():bold()$");
1539 item.setAttribute("item", "Jim");
1540 assertEquals("<b><b>Jim</b></b>", item.toString());
1541 }
1542
1543 public void testRepeatedApplicationOfTemplateToMultiValuedAttributeWithSeparator() throws Exception {
1544 StringTemplateGroup group =
1545 new StringTemplateGroup("dummy", ".");
1546 /*StringTemplate search =*/ group.defineTemplate("bold", "<b>$it$</b>");
1547 StringTemplate item =
1548 new StringTemplate(group, "$item:bold():bold(); separator=\",\"$");
1549 item.setAttribute("item", "Jim");
1550 item.setAttribute("item", "Mike");
1551 item.setAttribute("item", "Ashar");
1552 // first application of template must yield another vector!
1553 //System.out.println("ITEM="+item);
1554 String expecting = "<b><b>Jim</b></b>,<b><b>Mike</b></b>,<b><b>Ashar</b></b>";
1555 assertEquals(item.toString(), expecting);
1556 }
1557
1558 // ### NEED A TEST OF obj ASSIGNED TO ARG?
1559
1560 public void testMultiValuedAttributeWithSeparator() throws Exception {
1561 StringTemplate query;
1562
1563 // if column can be multi-valued, specify a separator
1564 StringTemplateGroup group =
1565 new StringTemplateGroup("dummy", ".", AngleBracketTemplateLexer.class);
1566 query = new StringTemplate(group, "SELECT <distinct> <column; separator=\", \"> FROM <table>;");
1567 query.setAttribute("column", "name");
1568 query.setAttribute("column", "email");
1569 query.setAttribute("table", "User");
1570 // uncomment next line to make "DISTINCT" appear in output
1571 // query.setAttribute("distince", "DISTINCT");
1572 // System.out.println(query);
1573 assertEquals("SELECT name, email FROM User;",query.toString());
1574 }
1575
1576 public void testSingleValuedAttributes() throws Exception {
1577 // all attributes are single-valued:
1578 StringTemplate query =
1579 new StringTemplate("SELECT $column$ FROM $table$;");
1580 query.setAttribute("column", "name");
1581 query.setAttribute("table", "User");
1582 // System.out.println(query);
1583 assertEquals("SELECT name FROM User;",query.toString());
1584 }
1585
1586 public void testIFTemplate() throws Exception {
1587 StringTemplateGroup group =
1588 new StringTemplateGroup("dummy", ".", AngleBracketTemplateLexer.class);
1589 StringTemplate t =
1590 new StringTemplate(group,
1591 "SELECT <column> FROM PERSON "+
1592 "<if(cond)>WHERE ID=<id><endif>;");
1593 t.setAttribute("column", "name");
1594 t.setAttribute("cond", "true");
1595 t.setAttribute("id", "231");
1596 assertEquals("SELECT name FROM PERSON WHERE ID=231;",t.toString());
1597 }
1598
1599 public void testIFCondWithParensTemplate() throws Exception {
1600 StringTemplateGroup group =
1601 new StringTemplateGroup("dummy", ".", AngleBracketTemplateLexer.class);
1602 StringTemplate t =
1603 new StringTemplate(group,
1604 "<if(map.(type))><type> <prop>=<map.(type)>;<endif>");
1605 HashMap map = new HashMap();
1606 map.put("int","0");
1607 t.setAttribute("map", map);
1608 t.setAttribute("prop", "x");
1609 t.setAttribute("type", "int");
1610 assertEquals("int x=0;",t.toString());
1611 }
1612
1613 public void testIFCondWithParensDollarDelimsTemplate() throws Exception {
1614 StringTemplateGroup group =
1615 new StringTemplateGroup("dummy", ".");
1616 StringTemplate t =
1617 new StringTemplate(group,
1618 "$if(map.(type))$$type$ $prop$=$map.(type)$;$endif$");
1619 HashMap map = new HashMap();
1620 map.put("int","0");
1621 t.setAttribute("map", map);
1622 t.setAttribute("prop", "x");
1623 t.setAttribute("type", "int");
1624 assertEquals("int x=0;",t.toString());
1625 }
1626
1627 /** As of 2.0, you can test a boolean value */
1628 public void testIFBoolean() throws Exception {
1629 StringTemplateGroup group =
1630 new StringTemplateGroup("dummy", ".");
1631 StringTemplate t =
1632 new StringTemplate(group,
1633 "$if(b)$x$endif$ $if(!b)$y$endif$");
1634 t.setAttribute("b", new Boolean(true));
1635 assertEquals(t.toString(), "x ");
1636
1637 t = t.getInstanceOf();
1638 t.setAttribute("b", new Boolean(false));
1639 assertEquals(" y", t.toString());
1640 }
1641
1642 public void testNestedIFTemplate() throws Exception {
1643 StringTemplateGroup group =
1644 new StringTemplateGroup("dummy", ".", AngleBracketTemplateLexer.class);
1645 StringTemplate t =
1646 new StringTemplate(group,
1647 "ack<if(a)>"+newline+
1648 "foo"+newline+
1649 "<if(!b)>stuff<endif>"+newline+
1650 "<if(b)>no<endif>"+newline+
1651 "junk"+newline+
1652 "<endif>"
1653 );
1654 t.setAttribute("a", "blort");
1655 // leave b as null
1656 //System.out.println("t="+t);
1657 String expecting =
1658 "ackfoo"+newline+
1659 "stuff"+newline+
1660 "junk";
1661 assertEquals(expecting, t.toString());
1662 }
1663
1664 public void testIFConditionWithTemplateApplication() throws Exception {
1665 StringTemplateGroup group =
1666 new StringTemplateGroup("dummy", ".");
1667 StringTemplate t =
1668 new StringTemplate(group,
1669 "$if(names:{$it$})$Fail!$endif$ $if(!names:{$it$})$Works!$endif$");
1670 t.setAttribute("b", new Boolean(true));
1671 assertEquals(t.toString(), " Works!");
1672 }
1673
1674 public class Connector {
1675 public int getID() { return 1; }
1676 public String getFirstName() { return "Terence"; }
1677 public String getLastName() { return "Parr"; }
1678 public String getEmail() { return "parrt@jguru.com"; }
1679 public String getBio() { return "Superhero by night..."; }
1680 /** As of 2.0, booleans work as you expect. In 1.x,
1681 * a missing value simulated a boolean.
1682 */
1683 public boolean getCanEdit() { return false; }
1684 }
1685
1686 public class Connector2 {
1687 public int getID() { return 2; }
1688 public String getFirstName() { return "Tom"; }
1689 public String getLastName() { return "Burns"; }
1690 public String getEmail() { return "tombu@jguru.com"; }
1691 public String getBio() { return "Superhero by day..."; }
1692 public Boolean getCanEdit() { return new Boolean(true); }
1693 }
1694
1695 public void testObjectPropertyReference() throws Exception {
1696 StringTemplateGroup group =
1697 new StringTemplateGroup("dummy", ".");
1698 StringTemplate t =
1699 new StringTemplate(
1700 group,
1701 "<b>Name: $p.firstName$ $p.lastName$</b><br>"+newline+
1702 "<b>Email: $p.email$</b><br>"+newline+
1703 "$p.bio$"
1704 );
1705 t.setAttribute("p", new Connector());
1706 //System.out.println("t is "+t.toString());
1707 String expecting =
1708 "<b>Name: Terence Parr</b><br>"+newline+
1709 "<b>Email: parrt@jguru.com</b><br>"+newline+
1710 "Superhero by night...";
1711 assertEquals(expecting, t.toString());
1712 }
1713
1714 public void testApplyRepeatedAnonymousTemplateWithForeignTemplateRefToMultiValuedAttribute() throws Exception {
1715 // specify a template to apply to an attribute
1716 // Use a template group so we can specify the start/stop chars
1717 StringTemplateGroup group =
1718 new StringTemplateGroup("dummy", ".");
1719 group.defineTemplate("link", "<a href=\"$url$\"><b>$title$</b></a>");
1720 StringTemplate duh =
1721 new StringTemplate(group,
1722 "start|$p:{$link(url=\"/member/view?ID=\"+it.ID, title=it.firstName)$ $if(it.canEdit)$canEdit$endif$}:"+
1723 "{$it$<br>\n}$|end");
1724 duh.setAttribute("p", new Connector());
1725 duh.setAttribute("p", new Connector2());
1726 //System.out.println(duh);
1727 String expecting = "start|<a href=\"/member/view?ID=1\"><b>Terence</b></a> <br>"+newline+
1728 "<a href=\"/member/view?ID=2\"><b>Tom</b></a> canEdit<br>"+newline+
1729 "|end";
1730 assertEquals(expecting,duh.toString());
1731 }
1732
1733 public static class Tree {
1734 protected List children = new LinkedList();
1735 protected String text;
1736 public Tree(String t) {
1737 text = t;
1738 }
1739 public String getText() {
1740 return text;
1741 }
1742 public void addChild(Tree c) {
1743 children.add(c);
1744 }
1745 public Tree getFirstChild() {
1746 if ( children.size()==0 ) {
1747 return null;
1748 }
1749 return (Tree)children.get(0);
1750 }
1751 public List getChildren() {
1752 return children;
1753 }
1754 }
1755
1756 public void testRecursion() throws Exception {
1757 StringTemplateGroup group =
1758 new StringTemplateGroup("dummy", ".", AngleBracketTemplateLexer.class);
1759 group.defineTemplate("tree",
1760 "<if(it.firstChild)>"+
1761 "( <it.text> <it.children:tree(); separator=\" \"> )" +
1762 "<else>" +
1763 "<it.text>" +
1764 "<endif>");
1765 StringTemplate tree = group.getInstanceOf("tree");
1766 // build ( a b (c d) e )
1767 Tree root = new Tree("a");
1768 root.addChild(new Tree("b"));
1769 Tree subtree = new Tree("c");
1770 subtree.addChild(new Tree("d"));
1771 root.addChild(subtree);
1772 root.addChild(new Tree("e"));
1773 tree.setAttribute("it", root);
1774 String expecting = "( a b ( c d ) e )";
1775 assertEquals(expecting, tree.toString());
1776 }
1777
1778 public void testNestedAnonymousTemplates() throws Exception {
1779 StringTemplateGroup group =
1780 new StringTemplateGroup("dummy", ".");
1781 StringTemplate t =
1782 new StringTemplate(
1783 group,
1784 "$A:{" + newline +
1785 "<i>$it:{" + newline +
1786 "<b>$it$</b>" + newline +
1787 "}$</i>" + newline +
1788 "}$"
1789 );
1790 t.setAttribute("A", "parrt");
1791 String expecting = newline +
1792 "<i>" + newline +
1793 "<b>parrt</b>" + newline +
1794 "</i>" + newline;
1795 assertEquals(expecting, t.toString());
1796 }
1797
1798 public void testAnonymousTemplateAccessToEnclosingAttributes() throws Exception {
1799 StringTemplateGroup group =
1800 new StringTemplateGroup("dummy", ".");
1801 StringTemplate t =
1802 new StringTemplate(
1803 group,
1804 "$A:{" + newline +
1805 "<i>$it:{" + newline +
1806 "<b>$it$, $B$</b>" + newline +
1807 "}$</i>" + newline +
1808 "}$"
1809 );
1810 t.setAttribute("A", "parrt");
1811 t.setAttribute("B", "tombu");
1812 String expecting = newline +
1813 "<i>" + newline +
1814 "<b>parrt, tombu</b>" + newline +
1815 "</i>" + newline;
1816 assertEquals(expecting, t.toString());
1817 }
1818
1819 public void testNestedAnonymousTemplatesAgain() throws Exception {
1820
1821 StringTemplateGroup group =
1822 new StringTemplateGroup("dummy", ".");
1823 StringTemplate t =
1824 new StringTemplate(
1825 group,
1826 "<table>"+newline +
1827 "$names:{<tr>$it:{<td>$it:{<b>$it$</b>}$</td>}$</tr>}$"+newline +
1828 "</table>"+newline
1829 );
1830 t.setAttribute("names", "parrt");
1831 t.setAttribute("names", "tombu");
1832 String expecting =
1833 "<table>" + newline +
1834 "<tr><td><b>parrt</b></td></tr><tr><td><b>tombu</b></td></tr>" + newline +
1835 "</table>" + newline;
1836 assertEquals(expecting, t.toString());
1837 }
1838
1839 public void testEscapes() throws Exception {
1840 StringTemplateGroup group =
1841 new StringTemplateGroup("dummy", ".");
1842 group.defineTemplate("foo", "$x$ && $it$");
1843 StringTemplate t =
1844 new StringTemplate(
1845 group,
1846 "$A:foo(x=\"dog\\\"\\\"\")$" // $A:foo("dog\"\"")$
1847 );
1848 StringTemplate u =
1849 new StringTemplate(
1850 group,
1851 "$A:foo(x=\"dog\\\"g\")$" // $A:foo(x="dog\"g")$
1852 );
1853 StringTemplate v =
1854 new StringTemplate(
1855 group,
1856 // $A:{$attr:foo(x="\{dog\}\"")$ is cool}$
1857 "$A:{$it:foo(x=\"\\{dog\\}\\\"\")$ is cool}$"
1858 );
1859 t.setAttribute("A", "ick");
1860 u.setAttribute("A", "ick");
1861 v.setAttribute("A", "ick");
1862 //System.out.println("t is '"+t.toString()+"'");
1863 //System.out.println("u is '"+u.toString()+"'");
1864 //System.out.println("v is '"+v.toString()+"'");
1865 String expecting = "dog\"\" && ick";
1866 assertEquals(expecting, t.toString());
1867 expecting = "dog\"g && ick";
1868 assertEquals(expecting,u.toString());
1869 expecting = "{dog}\" && ick is cool";
1870 assertEquals(expecting,v.toString());
1871 }
1872
1873 public void testEscapesOutsideExpressions() throws Exception {
1874 StringTemplate b = new StringTemplate("It\\'s ok...\\$; $a:{\\'hi\\', $it$}$");
1875 b.setAttribute("a", "Ter");
1876 String expecting ="It\\'s ok...$; \\'hi\\', Ter";
1877 String result = b.toString();
1878 assertEquals(expecting, result);
1879 }
1880
1881 public void testElseClause() throws Exception {
1882 StringTemplate e = new StringTemplate(
1883 "$if(title)$"+newline +
1884 "foo"+newline +
1885 "$else$"+newline +
1886 "bar"+newline +
1887 "$endif$"
1888 );
1889 e.setAttribute("title", "sample");
1890 String expecting = "foo";
1891 assertEquals(expecting, e.toString());
1892
1893 e = e.getInstanceOf();
1894 expecting = "bar";
1895 assertEquals(expecting, e.toString());
1896 }
1897
1898 public void testElseIfClause() throws Exception {
1899 StringTemplate e = new StringTemplate(
1900 "$if(x)$"+newline +
1901 "foo"+newline +
1902 "$elseif(y)$"+newline +
1903 "bar"+newline +
1904 "$endif$"
1905 );
1906 e.setAttribute("y", "yep");
1907 String expecting = "bar";
1908 assertEquals(expecting, e.toString());
1909 }
1910
1911 public void testElseIfClauseAngleBrackets() throws Exception {
1912 StringTemplate e = new StringTemplate(
1913 "<if(x)>"+newline +
1914 "foo"+newline +
1915 "<elseif(y)>"+newline +
1916 "bar"+newline +
1917 "<endif>",
1918 AngleBracketTemplateLexer.class
1919 );
1920 e.setAttribute("y", "yep");
1921 String expecting = "bar";
1922 assertEquals(expecting, e.toString());
1923 }
1924
1925 public void testElseIfClause2() throws Exception {
1926 StringTemplate e = new StringTemplate(
1927 "$if(x)$"+newline +
1928 "foo"+newline +
1929 "$elseif(y)$"+newline +
1930 "bar"+newline +
1931 "$elseif(z)$"+newline +
1932 "blort"+newline +
1933 "$endif$"
1934 );
1935 e.setAttribute("z", "yep");
1936 String expecting = "blort";
1937 assertEquals(expecting, e.toString());
1938 }
1939
1940 public void testElseIfClauseAndElse() throws Exception {
1941 StringTemplate e = new StringTemplate(
1942 "$if(x)$"+newline +
1943 "foo"+newline +
1944 "$elseif(y)$"+newline +
1945 "bar"+newline +
1946 "$elseif(z)$"+newline +
1947 "z"+newline +
1948 "$else$"+newline +
1949 "blort"+newline +
1950 "$endif$"
1951 );
1952 String expecting = "blort";
1953 assertEquals(expecting, e.toString());
1954 }
1955
1956 public void testNestedIF() throws Exception {
1957 StringTemplate e = new StringTemplate(
1958 "$if(title)$"+newline +
1959 "foo"+newline +
1960 "$else$"+newline +
1961 "$if(header)$"+newline +
1962 "bar"+newline +
1963 "$else$"+newline +
1964 "blort"+newline +
1965 "$endif$"+newline +
1966 "$endif$"
1967 );
1968 e.setAttribute("title", "sample");
1969 String expecting = "foo";
1970 assertEquals(expecting, e.toString());
1971
1972 e = e.getInstanceOf();
1973 e.setAttribute("header", "more");
1974 expecting = "bar";
1975 assertEquals(expecting, e.toString());
1976
1977 e = e.getInstanceOf();
1978 expecting = "blort";
1979 assertEquals(expecting, e.toString());
1980 }
1981
1982 public void testEmbeddedMultiLineIF() throws Exception {
1983 StringTemplateGroup group =
1984 new StringTemplateGroup("test");
1985 StringTemplate main = new StringTemplate(group, "$sub$");
1986 StringTemplate sub = new StringTemplate(group,
1987 "begin" + newline +
1988 "$if(foo)$" + newline +
1989 "$foo$" + newline +
1990 "$else$" +newline +
1991 "blort" + newline +
1992 "$endif$" + newline
1993 );
1994 sub.setAttribute("foo", "stuff");
1995 main.setAttribute("sub", sub);
1996 String expecting =
1997 "begin"+newline+
1998 "stuff";
1999 assertEquals(expecting, main.toString());
2000
2001 main = new StringTemplate(group, "$sub$");
2002 sub = sub.getInstanceOf();
2003 main.setAttribute("sub", sub);
2004 expecting =
2005 "begin"+newline+
2006 "blort";
2007 assertEquals(expecting, main.toString());
2008 }
2009
2010 public void testSimpleIndentOfAttributeList()
2011 throws Exception
2012 {
2013 String templates =
2014 "group test;" +newline+
2015 "list(names) ::= <<" +
2016 " $names; separator=\"\n\"$"+newline+
2017 ">>"+newline;
2018 StringTemplateErrorListener errors = new ErrorBuffer();
2019 StringTemplateGroup group =
2020 new StringTemplateGroup(new StringReader(templates),
2021 DefaultTemplateLexer.class,
2022 errors);
2023 StringTemplate t = group.getInstanceOf("list");
2024 t.setAttribute("names", "Terence");
2025 t.setAttribute("names", "Jim");
2026 t.setAttribute("names", "Sriram");
2027 String expecting =
2028 " Terence"+newline+
2029 " Jim"+newline+
2030 " Sriram";
2031 assertEquals(expecting, t.toString());
2032 }
2033
2034 public void testIndentOfMultilineAttributes()
2035 throws Exception
2036 {
2037 String templates =
2038 "group test;" +newline+
2039 "list(names) ::= <<" +
2040 " $names; separator=\"\n\"$"+newline+
2041 ">>"+newline;
2042 StringTemplateErrorListener errors = new ErrorBuffer();
2043 StringTemplateGroup group =
2044 new StringTemplateGroup(new StringReader(templates),
2045 DefaultTemplateLexer.class,
2046 errors);
2047 StringTemplate t = group.getInstanceOf("list");
2048 t.setAttribute("names", "Terence\nis\na\nmaniac");
2049 t.setAttribute("names", "Jim");
2050 t.setAttribute("names", "Sriram\nis\ncool");
2051 String expecting =
2052 " Terence"+newline+
2053 " is"+newline+
2054 " a"+newline+
2055 " maniac"+newline+
2056 " Jim"+newline+
2057 " Sriram"+newline+
2058 " is"+newline+
2059 " cool";
2060 assertEquals(expecting, t.toString());
2061 }
2062
2063 public void testIndentOfMultipleBlankLines()
2064 throws Exception
2065 {
2066 String templates =
2067 "group test;" +newline+
2068 "list(names) ::= <<" +
2069 " $names$"+newline+
2070 ">>"+newline;
2071 StringTemplateErrorListener errors = new ErrorBuffer();
2072 StringTemplateGroup group =
2073 new StringTemplateGroup(new StringReader(templates),
2074 DefaultTemplateLexer.class,
2075 errors);
2076 StringTemplate t = group.getInstanceOf("list");
2077 t.setAttribute("names", "Terence\n\nis a maniac");
2078 String expecting =
2079 " Terence"+newline+
2080 ""+newline+ // no indent on blank line
2081 " is a maniac";
2082 assertEquals(expecting, t.toString());
2083 }
2084
2085 public void testIndentBetweenLeftJustifiedLiterals()
2086 throws Exception
2087 {
2088 String templates =
2089 "group test;" +newline+
2090 "list(names) ::= <<" +
2091 "Before:"+newline +
2092 " $names; separator=\"\\n\"$"+newline+
2093 "after" +newline+
2094 ">>"+newline;
2095 StringTemplateErrorListener errors = new ErrorBuffer();
2096 StringTemplateGroup group =
2097 new StringTemplateGroup(new StringReader(templates),
2098 DefaultTemplateLexer.class,
2099 errors);
2100 StringTemplate t = group.getInstanceOf("list");
2101 t.setAttribute("names", "Terence");
2102 t.setAttribute("names", "Jim");
2103 t.setAttribute("names", "Sriram");
2104 String expecting =
2105 "Before:" +newline+
2106 " Terence"+newline+
2107 " Jim"+newline+
2108 " Sriram"+newline+
2109 "after";
2110 assertEquals(expecting, t.toString());
2111 }
2112
2113 public void testNestedIndent()
2114 throws Exception
2115 {
2116 String templates =
2117 "group test;" +newline+
2118 "method(name,stats) ::= <<" +
2119 "void $name$() {"+newline +
2120 "\t$stats; separator=\"\\n\"$"+newline+
2121 "}" +newline+
2122 ">>"+newline+
2123 "ifstat(expr,stats) ::= <<"+newline +
2124 "if ($expr$) {"+newline +
2125 " $stats; separator=\"\\n\"$"+newline +
2126 "}" +
2127 ">>"+newline +
2128 "assign(lhs,expr) ::= <<$lhs$=$expr$;>>"+newline
2129 ;
2130 StringTemplateErrorListener errors = new ErrorBuffer();
2131 StringTemplateGroup group =
2132 new StringTemplateGroup(new StringReader(templates),
2133 DefaultTemplateLexer.class,
2134 errors);
2135 StringTemplate t = group.getInstanceOf("method");
2136 t.setAttribute("name", "foo");
2137 StringTemplate s1 = group.getInstanceOf("assign");
2138 s1.setAttribute("lhs", "x");
2139 s1.setAttribute("expr", "0");
2140 StringTemplate s2 = group.getInstanceOf("ifstat");
2141 s2.setAttribute("expr", "x>0");
2142 StringTemplate s2a = group.getInstanceOf("assign");
2143 s2a.setAttribute("lhs", "y");
2144 s2a.setAttribute("expr", "x+y");
2145 StringTemplate s2b = group.getInstanceOf("assign");
2146 s2b.setAttribute("lhs", "z");
2147 s2b.setAttribute("expr", "4");
2148 s2.setAttribute("stats", s2a);
2149 s2.setAttribute("stats", s2b);
2150 t.setAttribute("stats", s1);
2151 t.setAttribute("stats", s2);
2152 String expecting =
2153 "void foo() {"+newline+
2154 "\tx=0;"+newline+
2155 "\tif (x>0) {"+newline+
2156 "\t y=x+y;"+newline+
2157 "\t z=4;"+newline+
2158 "\t}"+newline+
2159 "}";
2160 assertEquals(expecting, t.toString());
2161 }
2162
2163 public void testAlternativeWriter() throws Exception {
2164 final StringBuffer buf = new StringBuffer();
2165 StringTemplateWriter w = new StringTemplateWriter() {
2166 public void pushIndentation(String indent) {
2167 }
2168 public String popIndentation() {
2169 return null;
2170 }
2171 public void pushAnchorPoint() {
2172 }
2173 public void popAnchorPoint() {
2174 }
2175 public void setLineWidth(int lineWidth) { }
2176 public int write(String str, String wrap) throws IOException {
2177 return 0;
2178 }
2179 public int write(String str) throws IOException {
2180 buf.append(str); // just pass thru
2181 return str.length();
2182 }
2183 public int writeWrapSeparator(String wrap) throws IOException {
2184 return 0;
2185 }
2186 public int writeSeparator(String str) throws IOException {
2187 return write(str);
2188 }
2189 };
2190 StringTemplateGroup group =
2191 new StringTemplateGroup("test");
2192 group.defineTemplate("bold", "<b>$x$</b>");
2193 StringTemplate name = new StringTemplate(group, "$name:bold(x=name)$");
2194 name.setAttribute("name", "Terence");
2195 name.write(w);
2196 assertEquals("<b>Terence</b>", buf.toString());
2197 }
2198
2199 public void testApplyAnonymousTemplateToMapAndSet() throws Exception {
2200 StringTemplate st =
2201 new StringTemplate("$items:{<li>$it$</li>}$");
2202 Map m = new LinkedHashMap();
2203 m.put("a", "1");
2204 m.put("b", "2");
2205 m.put("c", "3");
2206 st.setAttribute("items", m);
2207 String expecting = "<li>1</li><li>2</li><li>3</li>";
2208 assertEquals(expecting, st.toString());
2209
2210 st = st.getInstanceOf();
2211 Set s = new HashSet();
2212 s.add("1");
2213 s.add("2");
2214 s.add("3");
2215 st.setAttribute("items", s);
2216 expecting = "<li>3</li><li>2</li><li>1</li>";
2217 assertEquals(expecting, st.toString());
2218 }
2219
2220 public void testDumpMapAndSet() throws Exception {
2221 StringTemplate st =
2222 new StringTemplate("$items; separator=\",\"$");
2223 Map m = new LinkedHashMap();
2224 m.put("a", "1");
2225 m.put("b", "2");
2226 m.put("c", "3");
2227 st.setAttribute("items", m);
2228 String expecting = "1,2,3";
2229 assertEquals(expecting, st.toString());
2230
2231 st = st.getInstanceOf();
2232 Set s = new HashSet();
2233 s.add("1");
2234 s.add("2");
2235 s.add("3");
2236 st.setAttribute("items", s);
2237 expecting = "3,2,1";
2238 assertEquals(expecting, st.toString());
2239 }
2240
2241 public class Connector3 {
2242 public int[] getValues() { return new int[] {1,2,3}; }
2243 public Map getStuff() {
2244 Map m = new LinkedHashMap(); m.put("a","1"); m.put("b","2"); return m;
2245 }
2246 }
2247
2248 public void testApplyAnonymousTemplateToArrayAndMapProperty() throws Exception {
2249 StringTemplate st =
2250 new StringTemplate("$x.values:{<li>$it$</li>}$");
2251 st.setAttribute("x", new Connector3());
2252 String expecting = "<li>1</li><li>2</li><li>3</li>";
2253 assertEquals(expecting, st.toString());
2254
2255 st = new StringTemplate("$x.stuff:{<li>$it$</li>}$");
2256 st.setAttribute("x", new Connector3());
2257 expecting = "<li>1</li><li>2</li>";
2258 assertEquals(expecting, st.toString());
2259 }
2260
2261 public void testSuperTemplateRef()
2262 throws Exception
2263 {
2264 // you can refer to a template defined in a super group via super.t()
2265 StringTemplateGroup group = new StringTemplateGroup("super");
2266 StringTemplateGroup subGroup = new StringTemplateGroup("sub");
2267 subGroup.setSuperGroup(group);
2268 group.defineTemplate("page", "$font()$:text");
2269 group.defineTemplate("font", "Helvetica");
2270 subGroup.defineTemplate("font", "$super.font()$ and Times");
2271 StringTemplate st = subGroup.getInstanceOf("page");
2272 String expecting =
2273 "Helvetica and Times:text";
2274 assertEquals(expecting, st.toString());
2275 }
2276
2277 public void testApplySuperTemplateRef()
2278 throws Exception
2279 {
2280 StringTemplateGroup group = new StringTemplateGroup("super");
2281 StringTemplateGroup subGroup = new StringTemplateGroup("sub");
2282 subGroup.setSuperGroup(group);
2283 group.defineTemplate("bold", "<b>$it$</b>");
2284 subGroup.defineTemplate("bold", "<strong>$it$</strong>");
2285 subGroup.defineTemplate("page", "$name:super.bold()$");
2286 StringTemplate st = subGroup.getInstanceOf("page");
2287 st.setAttribute("name", "Ter");
2288 String expecting =
2289 "<b>Ter</b>";
2290 assertEquals(expecting, st.toString());
2291 }
2292
2293 public void testLazyEvalOfSuperInApplySuperTemplateRef()
2294 throws Exception
2295 {
2296 StringTemplateGroup group = new StringTemplateGroup("base");
2297 StringTemplateGroup subGroup = new StringTemplateGroup("sub");
2298 subGroup.setSuperGroup(group);
2299 group.defineTemplate("bold", "<b>$it$</b>");
2300 subGroup.defineTemplate("bold", "<strong>$it$</strong>");
2301 // this is the same as testApplySuperTemplateRef() test
2302 // 'cept notice that here the supergroup defines page
2303 // As long as you create the instance via the subgroup,
2304 // "super." will evaluate lazily (i.e., not statically
2305 // during template compilation) to the templates
2306 // getGroup().superGroup value. If I create instance
2307 // of page in group not subGroup, however, I will get
2308 // an error as superGroup is null for group "group".
2309 group.defineTemplate("page", "$name:super.bold()$");
2310 StringTemplate st = subGroup.getInstanceOf("page");
2311 st.setAttribute("name", "Ter");
2312 String error = null;
2313 try {
2314 st.toString();
2315 }
2316 catch (IllegalArgumentException iae) {
2317 error = iae.getMessage();
2318 }
2319 String expectingError = "base has no super group; invalid template: super.bold";
2320 assertEquals(expectingError, error);
2321 }
2322
2323 public void testTemplatePolymorphism()
2324 throws Exception
2325 {
2326 StringTemplateGroup group = new StringTemplateGroup("super");
2327 StringTemplateGroup subGroup = new StringTemplateGroup("sub");
2328 subGroup.setSuperGroup(group);
2329 // bold is defined in both super and sub
2330 // if you create an instance of page via the subgroup,
2331 // then bold() should evaluate to the subgroup not the super
2332 // even though page is defined in the super. Just like polymorphism.
2333 group.defineTemplate("bold", "<b>$it$</b>");
2334 group.defineTemplate("page", "$name:bold()$");
2335 subGroup.defineTemplate("bold", "<strong>$it$</strong>");
2336 StringTemplate st = subGroup.getInstanceOf("page");
2337 st.setAttribute("name", "Ter");
2338 String expecting =
2339 "<strong>Ter</strong>";
2340 assertEquals(expecting, st.toString());
2341 }
2342
2343 public void testListOfEmbeddedTemplateSeesEnclosingAttributes() throws Exception {
2344 String templates =
2345 "group test;" +newline+
2346 "output(cond,items) ::= <<page: $items$>>" +newline+
2347 "mybody() ::= <<$font()$stuff>>" +newline+
2348 "font() ::= <<$if(cond)$this$else$that$endif$>>"
2349 ;
2350 StringTemplateErrorListener errors = new ErrorBuffer();
2351 StringTemplateGroup group =
2352 new StringTemplateGroup(new StringReader(templates),
2353 DefaultTemplateLexer.class,
2354 errors);
2355 StringTemplate outputST = group.getInstanceOf("output");
2356 StringTemplate bodyST1 = group.getInstanceOf("mybody");
2357 StringTemplate bodyST2 = group.getInstanceOf("mybody");
2358 StringTemplate bodyST3 = group.getInstanceOf("mybody");
2359 outputST.setAttribute("items", bodyST1);
2360 outputST.setAttribute("items", bodyST2);
2361 outputST.setAttribute("items", bodyST3);
2362 String expecting = "page: thatstuffthatstuffthatstuff";
2363 assertEquals(expecting, outputST.toString());
2364 }
2365
2366 public void testInheritArgumentFromRecursiveTemplateApplication() throws Exception {
2367 // do not inherit attributes through formal args
2368 String templates =
2369 "group test;" +newline+
2370 "block(stats) ::= \"<stats>\"" +
2371 "ifstat(stats) ::= \"IF true then <stats>\""+newline
2372 ;
2373 StringTemplateGroup group =
2374 new StringTemplateGroup(new StringReader(templates));
2375 StringTemplate b = group.getInstanceOf("block");
2376 b.setAttribute("stats", group.getInstanceOf("ifstat"));
2377 b.setAttribute("stats", group.getInstanceOf("ifstat"));
2378 String expecting = "IF true then IF true then ";
2379 String result = b.toString();
2380 //System.err.println("result='"+result+"'");
2381 assertEquals(expecting, result);
2382 }
2383
2384
2385 public void testDeliberateRecursiveTemplateApplication() throws Exception {
2386 // This test will cause infinite loop. block contains a stat which
2387 // contains the same block. Must be in lintMode to detect
2388 String templates =
2389 "group test;" +newline+
2390 "block(stats) ::= \"<stats>\"" +
2391 "ifstat(stats) ::= \"IF true then <stats>\""+newline
2392 ;
2393 StringTemplate.setLintMode(true);
2394 StringTemplate.resetTemplateCounter();
2395 StringTemplateGroup group =
2396 new StringTemplateGroup(new StringReader(templates));
2397 StringTemplate b = group.getInstanceOf("block");
2398 StringTemplate ifstat = group.getInstanceOf("ifstat");
2399 b.setAttribute("stats", ifstat); // block has if stat
2400 ifstat.setAttribute("stats", b); // but make "if" contain block
2401 String expectingError =
2402 "infinite recursion to <ifstat([stats])@4> referenced in <block([stats])@3>; stack trace:"+newline +
2403 "<ifstat([stats])@4>, attributes=[stats=<block()@3>]>"+newline +
2404 "<block([stats])@3>, attributes=[stats=<ifstat()@4>], references=[stats]>"+newline +
2405 "<ifstat([stats])@4> (start of recursive cycle)"+newline +
2406 "...";
2407 // note that attributes attribute doesn't show up in ifstat() because
2408 // recursion detection traps the problem before it writes out the
2409 // infinitely-recursive template; I set the attributes attribute right
2410 // before I render.
2411 String errors = "";
2412 try {
2413 /*String result =*/ b.toString();
2414 }
2415 catch (IllegalStateException ise) {
2416 errors = ise.getMessage();
2417 }
2418 //System.err.println("errors="+errors+"'");
2419 //System.err.println("expecting="+expectingError+"'");
2420 StringTemplate.setLintMode(false);
2421 assertEquals(expectingError, errors);
2422 }
2423
2424
2425 public void testImmediateTemplateAsAttributeLoop() throws Exception {
2426 // even though block has a stats value that refers to itself,
2427 // there is no recursion because each instance of block hides
2428 // the stats value from above since it's a formal arg.
2429 String templates =
2430 "group test;" +newline+
2431 "block(stats) ::= \"{<stats>}\""
2432 ;
2433 StringTemplateGroup group =
2434 new StringTemplateGroup(new StringReader(templates));
2435 StringTemplate b = group.getInstanceOf("block");
2436 b.setAttribute("stats", group.getInstanceOf("block"));
2437 String expecting ="{{}}";
2438 String result = b.toString();
2439 //System.err.println(result);
2440 assertEquals(expecting, result);
2441 }
2442
2443
2444 public void testTemplateAlias() throws Exception {
2445 String templates =
2446 "group test;" +newline+
2447 "page(name) ::= \"name is <name>\"" +
2448 "other ::= page"+newline
2449 ;
2450 StringTemplateGroup group =
2451 new StringTemplateGroup(new StringReader(templates));
2452 StringTemplate b = group.getInstanceOf("other"); // alias for page
2453 b.setAttribute("name", "Ter");
2454 String expecting ="name is Ter";
2455 String result = b.toString();
2456 assertEquals(expecting, result);
2457 }
2458
2459 public void testTemplateGetPropertyGetsAttribute() throws Exception {
2460 // This test will cause infinite loop if missing attribute no
2461 // properly caught in getAttribute
2462 String templates =
2463 "group test;"+newline+
2464 "Cfile(funcs) ::= <<"+newline +
2465 "#include \\<stdio.h>"+newline+
2466 "<funcs:{public void <it.name>(<it.args>);}; separator=\"\\n\">"+newline+
2467 "<funcs; separator=\"\\n\">"+newline+
2468 ">>"+newline +
2469 "func(name,args,body) ::= <<"+newline+
2470 "public void <name>(<args>) {<body>}"+newline +
2471 ">>"+newline
2472 ;
2473 StringTemplateGroup group =
2474 new StringTemplateGroup(new StringReader(templates));
2475 StringTemplate b = group.getInstanceOf("Cfile");
2476 StringTemplate f1 = group.getInstanceOf("func");
2477 StringTemplate f2 = group.getInstanceOf("func");
2478 f1.setAttribute("name", "f");
2479 f1.setAttribute("args", "");
2480 f1.setAttribute("body", "i=1;");
2481 f2.setAttribute("name", "g");
2482 f2.setAttribute("args", "int arg");
2483 f2.setAttribute("body", "y=1;");
2484 b.setAttribute("funcs",f1);
2485 b.setAttribute("funcs",f2);
2486 String expecting = "#include <stdio.h>" +newline+
2487 "public void f();"+newline+
2488 "public void g(int arg);" +newline+
2489 "public void f() {i=1;}"+newline+
2490 "public void g(int arg) {y=1;}";
2491 assertEquals(expecting,b.toString());
2492 }
2493
2494 public static class Decl {
2495 String name;
2496 String type;
2497 public Decl(String name, String type) {this.name=name; this.type=type;}
2498 public String getName() {return name;}
2499 public String getType() {return type;}
2500 }
2501
2502 public void testComplicatedIndirectTemplateApplication() throws Exception {
2503 String templates =
2504 "group Java;"+newline +
2505 ""+newline +
2506 "file(variables) ::= <<" +
2507 "<variables:{ v | <v.decl:(v.format)()>}; separator=\"\\n\">"+newline +
2508 ">>"+newline+
2509 "intdecl(decl) ::= \"int <decl.name> = 0;\""+newline +
2510 "intarray(decl) ::= \"int[] <decl.name> = null;\""+newline
2511 ;
2512 StringTemplateGroup group =
2513 new StringTemplateGroup(new StringReader(templates));
2514 StringTemplate f = group.getInstanceOf("file");
2515 f.setAttribute("variables.{decl,format}", new Decl("i","int"), "intdecl");
2516 f.setAttribute("variables.{decl,format}", new Decl("a","int-array"), "intarray");
2517 //System.out.println("f='"+f+"'");
2518 String expecting = "int i = 0;" +newline+
2519 "int[] a = null;";
2520 assertEquals(expecting, f.toString());
2521 }
2522
2523 public void testIndirectTemplateApplication() throws Exception {
2524 String templates =
2525 "group dork;"+newline +
2526 ""+newline +
2527 "test(name) ::= <<" +
2528 "<(name)()>"+newline +
2529 ">>"+newline+
2530 "first() ::= \"the first\""+newline +
2531 "second() ::= \"the second\""+newline
2532 ;
2533 StringTemplateGroup group =
2534 new StringTemplateGroup(new StringReader(templates));
2535 StringTemplate f = group.getInstanceOf("test");
2536 f.setAttribute("name", "first");
2537 String expecting = "the first";
2538 assertEquals(expecting, f.toString());
2539 }
2540
2541 public void testIndirectTemplateWithArgsApplication() throws Exception {
2542 String templates =
2543 "group dork;"+newline +
2544 ""+newline +
2545 "test(name) ::= <<" +
2546 "<(name)(a=\"foo\")>"+newline +
2547 ">>"+newline+
2548 "first(a) ::= \"the first: <a>\""+newline +
2549 "second(a) ::= \"the second <a>\""+newline
2550 ;
2551 StringTemplateGroup group =
2552 new StringTemplateGroup(new StringReader(templates));
2553 StringTemplate f = group.getInstanceOf("test");
2554 f.setAttribute("name", "first");
2555 String expecting = "the first: foo";
2556 assertEquals(f.toString(), expecting);
2557 }
2558
2559 public void testNullIndirectTemplateApplication() throws Exception {
2560 String templates =
2561 "group dork;"+newline +
2562 ""+newline +
2563 "test(names,t) ::= <<" +
2564 "<names:(t)()>"+newline + // t null be must be defined else error: null attr w/o formal def
2565 ">>"+newline+
2566 "ind() ::= \"[<it>]\""+newline;
2567 ;
2568 StringTemplateGroup group =
2569 new StringTemplateGroup(new StringReader(templates));
2570 StringTemplate f = group.getInstanceOf("test");
2571 f.setAttribute("names", "me");
2572 f.setAttribute("names", "you");
2573 String expecting = "";
2574 assertEquals(expecting, f.toString());
2575 }
2576
2577 public void testNullIndirectTemplate() throws Exception {
2578 String templates =
2579 "group dork;"+newline +
2580 ""+newline +
2581 "test(name) ::= <<" +
2582 "<(name)()>"+newline +
2583 ">>"+newline+
2584 "first() ::= \"the first\""+newline +
2585 "second() ::= \"the second\""+newline
2586 ;
2587 StringTemplateGroup group =
2588 new StringTemplateGroup(new StringReader(templates));
2589 StringTemplate f = group.getInstanceOf("test");
2590 //f.setAttribute("name", "first");
2591 String expecting = "";
2592 assertEquals(expecting, f.toString());
2593 }
2594
2595 public void testHashMapPropertyFetch() throws Exception {
2596 StringTemplate a = new StringTemplate("$stuff.prop$");
2597 HashMap map = new HashMap();
2598 a.setAttribute("stuff", map);
2599 map.put("prop", "Terence");
2600 String results = a.toString();
2601 //System.out.println(results);
2602 String expecting = "Terence";
2603 assertEquals(expecting, results);
2604 }
2605
2606 public void testHashMapPropertyFetchEmbeddedStringTemplate() throws Exception {
2607 StringTemplate a = new StringTemplate("$stuff.prop$");
2608 HashMap map = new HashMap();
2609 a.setAttribute("stuff", map);
2610 a.setAttribute("title", "ST rocks");
2611 map.put("prop", new StringTemplate("embedded refers to $title$"));
2612 String results = a.toString();
2613 //System.out.println(results);
2614 String expecting = "embedded refers to ST rocks";
2615 assertEquals(expecting, results);
2616 }
2617
2618 public void testEmbeddedComments() throws Exception {
2619 StringTemplate st = new StringTemplate(
2620 "Foo $! ignore !$bar" +newline
2621 );
2622 String expecting ="Foo bar"+newline;
2623 String result = st.toString();
2624 assertEquals(expecting, result);
2625
2626 st = new StringTemplate(
2627 "Foo $! ignore" +newline+
2628 " and a line break!$" +newline+
2629 "bar" +newline
2630 );
2631 expecting ="Foo "+newline+"bar"+newline;
2632 result = st.toString();
2633 assertEquals(expecting, result);
2634
2635 st = new StringTemplate(
2636 "$! start of line $ and $! ick" +newline+
2637 "!$boo"+newline
2638 );
2639 expecting ="boo"+newline;
2640 result = st.toString();
2641 assertEquals(expecting, result);
2642
2643 st = new StringTemplate(
2644 "$! start of line !$" +newline+
2645 "$! another to ignore !$" +newline+
2646 "$! ick" +newline+
2647 "!$boo"+newline
2648 );
2649 expecting ="boo"+newline;
2650 result = st.toString();
2651 assertEquals(expecting, result);
2652
2653 st = new StringTemplate(
2654 "$! back !$$! to back !$" +newline+ // can't detect; leaves \n
2655 "$! ick" +newline+
2656 "!$boo"+newline
2657 );
2658 expecting =newline+"boo"+newline;
2659 result = st.toString();
2660 assertEquals(expecting, result);
2661 }
2662
2663 public void testEmbeddedCommentsAngleBracketed() throws Exception {
2664 StringTemplate st = new StringTemplate(
2665 "Foo <! ignore !>bar" +newline,
2666 AngleBracketTemplateLexer.class
2667 );
2668 String expecting ="Foo bar"+newline;
2669 String result = st.toString();
2670 assertEquals(expecting, result);
2671
2672 st = new StringTemplate(
2673 "Foo <! ignore" +newline+
2674 " and a line break!>" +newline+
2675 "bar" +newline,
2676 AngleBracketTemplateLexer.class
2677 );
2678 expecting ="Foo "+newline+"bar"+newline;
2679 result = st.toString();
2680 assertEquals(expecting, result);
2681
2682 st = new StringTemplate(
2683 "<! start of line $ and <! ick" +newline+
2684 "!>boo"+newline,
2685 AngleBracketTemplateLexer.class
2686 );
2687 expecting ="boo"+newline;
2688 result = st.toString();
2689 assertEquals(expecting, result);
2690
2691 st = new StringTemplate(
2692 "<! start of line !>" +
2693 "<! another to ignore !>" +
2694 "<! ick" +newline+
2695 "!>boo"+newline,
2696 AngleBracketTemplateLexer.class
2697 );
2698 expecting ="boo"+newline;
2699 result = st.toString();
2700 //System.out.println(result);
2701 assertEquals(expecting, result);
2702
2703 st = new StringTemplate(
2704 "<! back !><! to back !>" +newline+ // can't detect; leaves \n
2705 "<! ick" +newline+
2706 "!>boo"+newline,
2707 AngleBracketTemplateLexer.class
2708 );
2709 expecting =newline+"boo"+newline;
2710 result = st.toString();
2711 assertEquals(expecting, result);
2712 }
2713
2714 public void testLineBreak() throws Exception {
2715 StringTemplate st = new StringTemplate(
2716 "Foo <\\\\>"+newline+
2717 " \t bar" +newline,
2718 AngleBracketTemplateLexer.class
2719 );
2720 StringWriter sw = new StringWriter();
2721 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2722 String result = sw.toString();
2723 String expecting ="Foo bar"+newline; // expect \n in output
2724 assertEquals(expecting, result);
2725 }
2726
2727 public void testLineBreak2() throws Exception {
2728 StringTemplate st = new StringTemplate(
2729 "Foo <\\\\> "+newline+
2730 " \t bar" +newline,
2731 AngleBracketTemplateLexer.class
2732 );
2733 StringWriter sw = new StringWriter();
2734 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2735 String result = sw.toString();
2736 String expecting ="Foo bar"+newline; // expect \n in output
2737 assertEquals(expecting, result);
2738 }
2739
2740 public void testLineBreakNoWhiteSpace() throws Exception {
2741 StringTemplate st = new StringTemplate(
2742 "Foo <\\\\>"+newline+
2743 "bar" +newline,
2744 AngleBracketTemplateLexer.class
2745 );
2746 StringWriter sw = new StringWriter();
2747 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2748 String result = sw.toString();
2749 String expecting ="Foo bar"+newline; // expect \n in output
2750 assertEquals(expecting, result);
2751 }
2752
2753 public void testLineBreakDollar() throws Exception {
2754 StringTemplate st = new StringTemplate(
2755 "Foo $\\\\$"+newline+
2756 " \t bar" +newline,
2757 DefaultTemplateLexer.class
2758 );
2759 StringWriter sw = new StringWriter();
2760 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2761 String result = sw.toString();
2762 String expecting ="Foo bar"+newline; // expect \n in output
2763 assertEquals(expecting, result);
2764 }
2765
2766 public void testLineBreakDollar2() throws Exception {
2767 StringTemplate st = new StringTemplate(
2768 "Foo $\\\\$ "+newline+
2769 " \t bar" +newline,
2770 DefaultTemplateLexer.class
2771 );
2772 StringWriter sw = new StringWriter();
2773 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2774 String result = sw.toString();
2775 String expecting ="Foo bar"+newline; // expect \n in output
2776 assertEquals(expecting, result);
2777 }
2778
2779 public void testLineBreakNoWhiteSpaceDollar() throws Exception {
2780 StringTemplate st = new StringTemplate(
2781 "Foo $\\\\$"+newline+
2782 "bar" +newline,
2783 DefaultTemplateLexer.class
2784 );
2785 StringWriter sw = new StringWriter();
2786 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2787 String result = sw.toString();
2788 String expecting ="Foo bar"+newline; // expect \n in output
2789 assertEquals(expecting, result);
2790 }
2791
2792 public void testCharLiterals() throws Exception {
2793 StringTemplate st = new StringTemplate(
2794 "Foo <\\r\\n><\\n><\\t> bar" +newline,
2795 AngleBracketTemplateLexer.class
2796 );
2797 StringWriter sw = new StringWriter();
2798 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2799 String result = sw.toString();
2800 String expecting ="Foo \n\n\t bar"+newline; // expect \n in output
2801 assertEquals(expecting, result);
2802
2803 st = new StringTemplate(
2804 "Foo $\\n$$\\t$ bar" +newline);
2805 sw = new StringWriter();
2806 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2807 expecting ="Foo \n\t bar"+newline; // expect \n in output
2808 result = sw.toString();
2809 assertEquals(expecting, result);
2810
2811 st = new StringTemplate(
2812 "Foo$\\ $bar$\\n$");
2813 sw = new StringWriter();
2814 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2815 result = sw.toString();
2816 expecting ="Foo bar\n"; // force \n
2817 assertEquals(expecting, result);
2818 }
2819
2820 public void testNewlineNormalizationInTemplateString() throws Exception {
2821 StringTemplate st = new StringTemplate(
2822 "Foo\r\n"+
2823 "Bar\n",
2824 AngleBracketTemplateLexer.class
2825 );
2826 StringWriter sw = new StringWriter();
2827 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2828 String result = sw.toString();
2829 String expecting ="Foo\nBar\n"; // expect \n in output
2830 assertEquals(expecting, result);
2831 }
2832
2833 public void testNewlineNormalizationInTemplateStringPC() throws Exception {
2834 StringTemplate st = new StringTemplate(
2835 "Foo\r\n"+
2836 "Bar\n",
2837 AngleBracketTemplateLexer.class
2838 );
2839 StringWriter sw = new StringWriter();
2840 st.write(new AutoIndentWriter(sw,"\r\n")); // force \r\n as newline
2841 String result = sw.toString();
2842 String expecting ="Foo\r\nBar\r\n"; // expect \r\n in output
2843 assertEquals(expecting, result);
2844 }
2845
2846 public void testNewlineNormalizationInAttribute() throws Exception {
2847 StringTemplate st = new StringTemplate(
2848 "Foo\r\n"+
2849 "<name>\n",
2850 AngleBracketTemplateLexer.class
2851 );
2852 st.setAttribute("name", "a\nb\r\nc");
2853 StringWriter sw = new StringWriter();
2854 st.write(new AutoIndentWriter(sw,"\n")); // force \n as newline
2855 String result = sw.toString();
2856 String expecting ="Foo\na\nb\nc\n"; // expect \n in output
2857 assertEquals(expecting, result);
2858 }
2859
2860 public void testUnicodeLiterals() throws Exception {
2861 StringTemplate st = new StringTemplate(
2862 "Foo <\\uFEA5\\n\\u00C2> bar" +newline,
2863 AngleBracketTemplateLexer.class
2864 );
2865 String expecting ="Foo \ufea5"+newline+"\u00C2 bar"+newline;
2866 String result = st.toString();
2867 assertEquals(expecting, result);
2868
2869 st = new StringTemplate(
2870 "Foo $\\uFEA5\\n\\u00C2$ bar" +newline);
2871 expecting ="Foo \ufea5"+newline+"\u00C2 bar"+newline;
2872 result = st.toString();
2873 assertEquals(expecting, result);
2874
2875 st = new StringTemplate(
2876 "Foo$\\ $bar$\\n$");
2877 expecting ="Foo bar"+newline;
2878 result = st.toString();
2879 assertEquals(expecting, result);
2880 }
2881
2882
2883 public void testEmptyIteratedValueGetsSeparator() throws Exception {
2884 StringTemplateGroup group =
2885 new StringTemplateGroup("test");
2886 StringTemplateErrorListener errors = new ErrorBuffer();
2887 group.setErrorListener(errors);
2888 StringTemplate t = new StringTemplate(group, "$names; separator=\",\"$");
2889 t.setAttribute("names", "Terence");
2890 t.setAttribute("names", "");
2891 t.setAttribute("names", "");
2892 t.setAttribute("names", "Tom");
2893 t.setAttribute("names", "Frank");
2894 t.setAttribute("names", "");
2895 // empty values get separator still
2896 String expecting="Terence,,,Tom,Frank,";
2897 String result = t.toString();
2898 assertEquals(expecting, result);
2899 }
2900
2901 public void testMissingIteratedConditionalValueGetsNOSeparator() throws Exception {
2902 StringTemplateGroup group =
2903 new StringTemplateGroup("test");
2904 StringTemplateErrorListener errors = new ErrorBuffer();
2905 group.setErrorListener(errors);
2906 StringTemplate t = new StringTemplate(group,
2907 "$users:{$if(it.ok)$$it.name$$endif$}; separator=\",\"$");
2908 t.setAttribute("users.{name,ok}", "Terence", new Boolean(true));
2909 t.setAttribute("users.{name,ok}", "Tom", new Boolean(false));
2910 t.setAttribute("users.{name,ok}", "Frank", new Boolean(true));
2911 t.setAttribute("users.{name,ok}", "Johnny", new Boolean(false));
2912 // empty conditional values get no separator
2913 String expecting="Terence,Frank";
2914 String result = t.toString();
2915 assertEquals(expecting, result);
2916 }
2917
2918 public void testMissingIteratedConditionalValueGetsNOSeparator2() throws Exception {
2919 StringTemplateGroup group =
2920 new StringTemplateGroup("test");
2921 StringTemplateErrorListener errors = new ErrorBuffer();
2922 group.setErrorListener(errors);
2923 StringTemplate t = new StringTemplate(group,
2924 "$users:{$if(it.ok)$$it.name$$endif$}; separator=\",\"$");
2925 t.setAttribute("users.{name,ok}", "Terence", new Boolean(true));
2926 t.setAttribute("users.{name,ok}", "Tom", new Boolean(false));
2927 t.setAttribute("users.{name,ok}", "Frank", new Boolean(false));
2928 t.setAttribute("users.{name,ok}", "Johnny", new Boolean(false));
2929 // empty conditional values get no separator
2930 String expecting="Terence";
2931 String result = t.toString();
2932 assertEquals(expecting, result);
2933 }
2934
2935 public void testMissingIteratedDoubleConditionalValueGetsNOSeparator() throws Exception {
2936 StringTemplateGroup group =
2937 new StringTemplateGroup("test");
2938 StringTemplateErrorListener errors = new ErrorBuffer();
2939 group.setErrorListener(errors);
2940 StringTemplate t = new StringTemplate(group,
2941 "$users:{$if(it.ok)$$it.name$$endif$$if(it.ok)$$it.name$$endif$}; separator=\",\"$");
2942 t.setAttribute("users.{name,ok}", "Terence", new Boolean(false));
2943 t.setAttribute("users.{name,ok}", "Tom", new Boolean(true));
2944 t.setAttribute("users.{name,ok}", "Frank", new Boolean(true));
2945 t.setAttribute("users.{name,ok}", "Johnny", new Boolean(true));
2946 // empty conditional values get no separator
2947 String expecting="TomTom,FrankFrank,JohnnyJohnny";
2948 String result = t.toString();
2949 assertEquals(expecting, result);
2950 }
2951
2952 public void testIteratedConditionalWithEmptyElseValueGetsSeparator() throws Exception {
2953 StringTemplateGroup group =
2954 new StringTemplateGroup("test");
2955 StringTemplateErrorListener errors = new ErrorBuffer();
2956 group.setErrorListener(errors);
2957 StringTemplate t = new StringTemplate(group,
2958 "$users:{$if(it.ok)$$it.name$$else$$endif$}; separator=\",\"$");
2959 t.setAttribute("users.{name,ok}", "Terence", new Boolean(true));
2960 t.setAttribute("users.{name,ok}", "Tom", new Boolean(false));
2961 t.setAttribute("users.{name,ok}", "Frank", new Boolean(true));
2962 t.setAttribute("users.{name,ok}", "Johnny", new Boolean(false));
2963 // empty conditional values get no separator
2964 String expecting="Terence,,Frank,";
2965 String result = t.toString();
2966 assertEquals(expecting, result);
2967 }
2968
2969 public void testWhiteSpaceAtEndOfTemplate() throws Exception {
2970 StringTemplateGroup group = new StringTemplateGroup("group");
2971 StringTemplate pageST = group.getInstanceOf("org/antlr/stringtemplate/test/page");
2972 StringTemplate listST = group.getInstanceOf("org/antlr/stringtemplate/test/users_list");
2973 // users.list references row.st which has a single blank line at the end.
2974 // I.e., there are 2 \n in a row at the end
2975 // ST should eat all whitespace at end
2976 listST.setAttribute("users", new Connector());
2977 listST.setAttribute("users", new Connector2());
2978 pageST.setAttribute("title", "some title");
2979 pageST.setAttribute("body", listST);
2980 String expecting ="some title" +newline+
2981 "Terence parrt@jguru.comTom tombu@jguru.com";
2982 String result = pageST.toString();
2983 //System.out.println("'"+result+"'");
2984 assertEquals(expecting, result);
2985 }
2986
2987 static class Duh {
2988 public List users = new ArrayList();
2989 }
2990
2991 public void testSizeZeroButNonNullListGetsNoOutput() throws Exception {
2992 StringTemplateGroup group =
2993 new StringTemplateGroup("test");
2994 StringTemplateErrorListener errors = new ErrorBuffer();
2995 group.setErrorListener(errors);
2996 StringTemplate t = new StringTemplate(group,
2997 "begin\n" +
2998 "$duh.users:{name: $it$}; separator=\", \"$\n" +
2999 "end\n");
3000 t.setAttribute("duh", new Duh());
3001 String expecting="begin\nend\n";
3002 String result = t.toString();
3003 assertEquals(expecting, result);
3004 }
3005
3006 public void testNullListGetsNoOutput() throws Exception {
3007 StringTemplateGroup group =
3008 new StringTemplateGroup("test");
3009 StringTemplateErrorListener errors = new ErrorBuffer();
3010 group.setErrorListener(errors);
3011 StringTemplate t = new StringTemplate(group,
3012 "begin\n" +
3013 "$users:{name: $it$}; separator=\", \"$\n" +
3014 "end\n");
3015 //t.setAttribute("users", new Duh());
3016 String expecting="begin\nend\n";
3017 String result = t.toString();
3018 assertEquals(expecting, result);
3019 }
3020
3021 public void testEmptyListGetsNoOutput() throws Exception {
3022 StringTemplateGroup group =
3023 new StringTemplateGroup("test");
3024 StringTemplateErrorListener errors = new ErrorBuffer();
3025 group.setErrorListener(errors);
3026 StringTemplate t = new StringTemplate(group,
3027 "begin\n" +
3028 "$users:{name: $it$}; separator=\", \"$\n" +
3029 "end\n");
3030 t.setAttribute("users", new ArrayList());
3031 String expecting="begin\nend\n";
3032 String result = t.toString();
3033 assertEquals(expecting, result);
3034 }
3035
3036 public void testEmptyListNoIteratorGetsNoOutput() throws Exception {
3037 StringTemplateGroup group =
3038 new StringTemplateGroup("test");
3039 StringTemplateErrorListener errors = new ErrorBuffer();
3040 group.setErrorListener(errors);
3041 StringTemplate t = new StringTemplate(group,
3042 "begin\n" +
3043 "$users; separator=\", \"$\n" +
3044 "end\n");
3045 t.setAttribute("users", new ArrayList());
3046 String expecting="begin\nend\n";
3047 String result = t.toString();
3048 assertEquals(expecting, result);
3049 }
3050
3051 public void testEmptyExprAsFirstLineGetsNoOutput() throws Exception {
3052 StringTemplateGroup group =
3053 new StringTemplateGroup("test");
3054 StringTemplateErrorListener errors = new ErrorBuffer();
3055 group.setErrorListener(errors);
3056 group.defineTemplate("bold", "<b>$it$</b>");
3057 StringTemplate t = new StringTemplate(group,
3058 "$users$\n" +
3059 "end\n");
3060 String expecting="end\n";
3061 String result = t.toString();
3062 assertEquals(expecting, result);
3063 }
3064
3065 public void testSizeZeroOnLineByItselfGetsNoOutput() throws Exception {
3066 StringTemplateGroup group =
3067 new StringTemplateGroup("test");
3068 StringTemplateErrorListener errors = new ErrorBuffer();
3069 group.setErrorListener(errors);
3070 StringTemplate t = new StringTemplate(group,
3071 "begin\n"+
3072 "$name$\n"+
3073 "$users:{name: $it$}$\n"+
3074 "$users:{name: $it$}; separator=\", \"$\n"+
3075 "end\n");
3076 String expecting="begin\nend\n";
3077 String result = t.toString();
3078 assertEquals(expecting, result);
3079 }
3080
3081 public void testSizeZeroOnLineWithIndentGetsNoOutput() throws Exception {
3082 StringTemplateGroup group =
3083 new StringTemplateGroup("test");
3084 StringTemplateErrorListener errors = new ErrorBuffer();
3085 group.setErrorListener(errors);
3086 StringTemplate t = new StringTemplate(group,
3087 "begin\n"+
3088 " $name$\n"+
3089 " $users:{name: $it$}$\n"+
3090 " $users:{name: $it$$\\n$}$\n"+
3091 "end\n");
3092 String expecting="begin\nend\n";
3093 String result = t.toString();
3094 assertEquals(expecting, result);
3095 }
3096
3097 public void testSimpleAutoIndent() throws Exception {
3098 StringTemplate a = new StringTemplate(
3099 "$title$: {\n" +
3100 " $name; separator=\"\n\"$\n" +
3101 "}");
3102 a.setAttribute("title", "foo");
3103 a.setAttribute("name", "Terence");
3104 a.setAttribute("name", "Frank");
3105 String results = a.toString();
3106 //System.out.println(results);
3107 String expecting =
3108 "foo: {\n" +
3109 " Terence\n" +
3110 " Frank\n" +
3111 "}";
3112 assertEquals(results, expecting);
3113 }
3114
3115 public void testComputedPropertyName() throws Exception {
3116 StringTemplateGroup group =
3117 new StringTemplateGroup("test");
3118 StringTemplateErrorListener errors = new ErrorBuffer();
3119 group.setErrorListener(errors);
3120 StringTemplate t = new StringTemplate(group,
3121 "variable property $propName$=$v.(propName)$");
3122 t.setAttribute("v", new Decl("i","int"));
3123 t.setAttribute("propName", "type");
3124 String expecting="variable property type=int";
3125 String result = t.toString();
3126 assertEquals("", errors.toString());
3127 assertEquals(expecting, result);
3128 }
3129
3130 public void testNonNullButEmptyIteratorTestsFalse() throws Exception {
3131 StringTemplateGroup group =
3132 new StringTemplateGroup("test");
3133 StringTemplate t = new StringTemplate(group,
3134 "$if(users)$\n" +
3135 "Users: $users:{$it.name$ }$\n" +
3136 "$endif$");
3137 t.setAttribute("users", new LinkedList());
3138 String expecting="";
3139 String result = t.toString();
3140 assertEquals(expecting, result);
3141 }
3142
3143 public void testDoNotInheritAttributesThroughFormalArgs() throws Exception {
3144 String templates =
3145 "group test;" +newline+
3146 "method(name) ::= \"<stat()>\"" +newline+
3147 "stat(name) ::= \"x=y; // <name>\""+newline
3148 ;
3149 // name is not visible in stat because of the formal arg called name.
3150 // somehow, it must be set.
3151 StringTemplateGroup group =
3152 new StringTemplateGroup(new StringReader(templates));
3153 StringTemplate b = group.getInstanceOf("method");
3154 b.setAttribute("name", "foo");
3155 String expecting = "x=y; // ";
3156 String result = b.toString();
3157 //System.err.println("result='"+result+"'");
3158 assertEquals(expecting, result);
3159 }
3160
3161 public void testArgEvaluationContext() throws Exception {
3162 String templates =
3163 "group test;" +newline+
3164 "method(name) ::= \"<stat(name=name)>\"" +newline+
3165 "stat(name) ::= \"x=y; // <name>\""+newline
3166 ;
3167 // attribute name is not visible in stat because of the formal
3168 // arg called name in template stat. However, we can set it's value
3169 // with an explicit name=name. This looks weird, but makes total
3170 // sense as the rhs is evaluated in the context of method and the lhs
3171 // is evaluated in the context of stat's arg list.
3172 StringTemplateGroup group =
3173 new StringTemplateGroup(new StringReader(templates));
3174 StringTemplate b = group.getInstanceOf("method");
3175 b.setAttribute("name", "foo");
3176 String expecting = "x=y; // foo";
3177 String result = b.toString();
3178 //System.err.println("result='"+result+"'");
3179 assertEquals(expecting, result);
3180 }
3181
3182 public void testPassThroughAttributes() throws Exception {
3183 String templates =
3184 "group test;" +newline+
3185 "method(name) ::= \"<stat(...)>\"" +newline+
3186 "stat(name) ::= \"x=y; // <name>\""+newline
3187 ;
3188 StringTemplateGroup group =
3189 new StringTemplateGroup(new StringReader(templates));
3190 StringTemplate b = group.getInstanceOf("method");
3191 b.setAttribute("name", "foo");
3192 String expecting = "x=y; // foo";
3193 String result = b.toString();
3194 //System.err.println("result='"+result+"'");
3195 assertEquals(expecting, result);
3196 }
3197
3198 public void testPassThroughAttributes2() throws Exception {
3199 String templates =
3200 "group test;" +newline+
3201 "method(name) ::= <<"+newline+
3202 "<stat(value=\"34\",...)>" +newline+
3203 ">>"+newline+
3204 "stat(name,value) ::= \"x=<value>; // <name>\""+newline
3205 ;
3206 StringTemplateGroup group =
3207 new StringTemplateGroup(new StringReader(templates));
3208 StringTemplate b = group.getInstanceOf("method");
3209 b.setAttribute("name", "foo");
3210 String expecting = "x=34; // foo";
3211 String result = b.toString();
3212 //System.err.println("result='"+result+"'");
3213 assertEquals(expecting, result);
3214 }
3215
3216 public void testDefaultArgument() throws Exception {
3217 String templates =
3218 "group test;" +newline+
3219 "method(name) ::= <<"+newline+
3220 "<stat(...)>" +newline+
3221 ">>"+newline+
3222 "stat(name,value=\"99\") ::= \"x=<value>; // <name>\""+newline
3223 ;
3224 StringTemplateGroup group =
3225 new StringTemplateGroup(new StringReader(templates));
3226 StringTemplate b = group.getInstanceOf("method");
3227 b.setAttribute("name", "foo");
3228 String expecting = "x=99; // foo";
3229 String result = b.toString();
3230 //System.err.println("result='"+result+"'");
3231 assertEquals(expecting, result);
3232 }
3233
3234 public void testDefaultArgument2() throws Exception {
3235 String templates =
3236 "group test;" +newline+
3237 "stat(name,value=\"99\") ::= \"x=<value>; // <name>\""+newline
3238 ;
3239 StringTemplateGroup group =
3240 new StringTemplateGroup(new StringReader(templates));
3241 StringTemplate b = group.getInstanceOf("stat");
3242 b.setAttribute("name", "foo");
3243 String expecting = "x=99; // foo";
3244 String result = b.toString();
3245 //System.err.println("result='"+result+"'");
3246 assertEquals(expecting, result);
3247 }
3248
3249 public void testDefaultArgumentManuallySet() throws Exception {
3250 class Field {
3251 public String name = "parrt";
3252 public int n = 0;
3253 public String toString() {
3254 return "Field";
3255 }
3256 }
3257 String templates =
3258 "group test;" +newline+
3259 "method(fields) ::= <<"+newline+
3260 "<fields:{f | <stat(f=f)>}>" +newline+
3261 ">>"+newline+
3262 "stat(f,value={<f.name>}) ::= \"x=<value>; // <f.name>\""+newline
3263 ;
3264 StringTemplateGroup group =
3265 new StringTemplateGroup(new StringReader(templates));
3266 StringTemplate m = group.getInstanceOf("method");
3267 m.setAttribute("fields", new Field());
3268 String expecting = "x=parrt; // parrt";
3269 String result = m.toString();
3270 assertEquals(expecting, result);
3271 }
3272
3273 /** This fails because checkNullAttributeAgainstFormalArguments looks
3274 * for a formal argument at the current level not of the original embedded
3275 * template. We have defined it all the way in the embedded, but there is
3276 * no value so we try to look upwards ala dynamic scoping. When it reaches
3277 * the top, it doesn't find a value but it will miss the
3278 * formal argument down in the embedded.
3279 *
3280 * By definition, though, the formal parameter exists if we have
3281 * a default value. look up the value to see if it's null without
3282 * checking checkNullAttributeAgainstFormalArguments.
3283 */
3284 public void testDefaultArgumentImplicitlySet() throws Exception {
3285 class Field {
3286 public String name = "parrt";
3287 public int n = 0;
3288 public String toString() {
3289 return "Field";
3290 }
3291 }
3292 String templates =
3293 "group test;" +newline+
3294 "method(fields) ::= <<"+newline+
3295 "<fields:{f | <stat(...)>}>" +newline+
3296 ">>"+newline+
3297 "stat(f,value={<f.name>}) ::= \"x=<value>; // <f.name>\""+newline
3298 ;
3299 StringTemplateGroup group =
3300 new StringTemplateGroup(new StringReader(templates));
3301 StringTemplate m = group.getInstanceOf("method");
3302 m.setAttribute("fields", new Field());
3303 String expecting = "x=parrt; // parrt";
3304 String result = m.toString();
3305 assertEquals(expecting, result);
3306 }
3307
3308 /* FIX THIS
3309 public void testDefaultArgumentImplicitlySet2() throws Exception {
3310 class Field {
3311 public String name = "parrt";
3312 public int n = 0;
3313 public String toString() {
3314 return "Field";
3315 }
3316 }
3317 String templates =
3318 "group test;" +newline+
3319 "method(fields) ::= <<"+newline+
3320 "<fields:{f | <f:stat()>}>" +newline+ // THIS SHOULD BE ERROR; >1 arg?
3321 ">>"+newline+
3322 "stat(f,value={<f.name>}) ::= \"x=<value>; // <f.name>\""+newline
3323 ;
3324 StringTemplateGroup group =
3325 new StringTemplateGroup(new StringReader(templates));
3326 StringTemplate m = group.getInstanceOf("method");
3327 m.setAttribute("fields", new Field());
3328 String expecting = "x=parrt; // parrt";
3329 String result = m.toString();
3330 assertEquals(expecting, result);
3331 }
3332 */
3333
3334 public void testDefaultArgumentAsTemplate() throws Exception {
3335 String templates =
3336 "group test;" +newline+
3337 "method(name,size) ::= <<"+newline+
3338 "<stat(...)>" +newline+
3339 ">>"+newline+
3340 "stat(name,value={<name>}) ::= \"x=<value>; // <name>\""+newline
3341 ;
3342 StringTemplateGroup group =
3343 new StringTemplateGroup(new StringReader(templates));
3344 StringTemplate b = group.getInstanceOf("method");
3345 b.setAttribute("name", "foo");
3346 b.setAttribute("size", "2");
3347 String expecting = "x=foo; // foo";
3348 String result = b.toString();
3349 //System.err.println("result='"+result+"'");
3350 assertEquals(expecting, result);
3351 }
3352
3353 public void testDefaultArgumentAsTemplate2() throws Exception {
3354 String templates =
3355 "group test;" +newline+
3356 "method(name,size) ::= <<"+newline+
3357 "<stat(...)>" +newline+
3358 ">>"+newline+
3359 "stat(name,value={ [<name>] }) ::= \"x=<value>; // <name>\""+newline
3360 ;
3361 StringTemplateGroup group =
3362 new StringTemplateGroup(new StringReader(templates));
3363 StringTemplate b = group.getInstanceOf("method");
3364 b.setAttribute("name", "foo");
3365 b.setAttribute("size", "2");
3366 String expecting = "x= [foo] ; // foo";
3367 String result = b.toString();
3368 //System.err.println("result='"+result+"'");
3369 assertEquals(expecting, result);
3370 }
3371
3372 public void testDoNotUseDefaultArgument() throws Exception {
3373 String templates =
3374 "group test;" +newline+
3375 "method(name) ::= <<"+newline+
3376 "<stat(value=\"34\",...)>" +newline+
3377 ">>"+newline+
3378 "stat(name,value=\"99\") ::= \"x=<value>; // <name>\""+newline
3379 ;
3380 StringTemplateGroup group =
3381 new StringTemplateGroup(new StringReader(templates));
3382 StringTemplate b = group.getInstanceOf("method");
3383 b.setAttribute("name", "foo");
3384 String expecting = "x=34; // foo";
3385 String result = b.toString();
3386 assertEquals(expecting, result);
3387 }
3388
3389 public void testDefaultArgumentInParensToEvalEarly() throws Exception {
3390 class Counter {
3391 int n = 0;
3392 public String toString() { return String.valueOf(n++); }
3393 }
3394 String templates =
3395 "group test;" +newline+
3396 "A(x) ::= \"<B()>\""+newline+
3397 "B(y={<(x)>}) ::= \"<y> <x> <x> <y>\""+newline
3398 ;
3399 StringTemplateGroup group =
3400 new StringTemplateGroup(new StringReader(templates));
3401 StringTemplate b = group.getInstanceOf("A");
3402 b.setAttribute("x", new Counter());
3403 String expecting = "0 1 2 0";
3404 String result = b.toString();
3405 //System.err.println("result='"+result+"'");
3406 assertEquals(expecting, result);
3407 }
3408
3409 public void testArgumentsAsTemplates() throws Exception {
3410 String templates =
3411 "group test;" +newline+
3412 "method(name,size) ::= <<"+newline+
3413 "<stat(value={<size>})>" +newline+
3414 ">>"+newline+
3415 "stat(value) ::= \"x=<value>;\""+newline
3416 ;
3417 StringTemplateGroup group =
3418 new StringTemplateGroup(new StringReader(templates));
3419 StringTemplate b = group.getInstanceOf("method");
3420 b.setAttribute("name", "foo");
3421 b.setAttribute("size", "34");
3422 String expecting = "x=34;";
3423 String result = b.toString();
3424 assertEquals(expecting, result);
3425 }
3426
3427 public void testTemplateArgumentEvaluatedInSurroundingContext() throws Exception {
3428 String templates =
3429 "group test;" +newline+
3430 "file(m,size) ::= \"<m>\""+newline+
3431 "method(name) ::= <<"+newline+
3432 "<stat(value={<size>.0})>" +newline+
3433 ">>"+newline+
3434 "stat(value) ::= \"x=<value>;\""+newline
3435 ;
3436 StringTemplateGroup group =
3437 new StringTemplateGroup(new StringReader(templates));
3438 StringTemplate f = group.getInstanceOf("file");
3439 f.setAttribute("size", "34");
3440 StringTemplate m = group.getInstanceOf("method");
3441 m.setAttribute("name", "foo");
3442 f.setAttribute("m", m);
3443 String expecting = "x=34.0;";
3444 String result = m.toString();
3445 assertEquals(expecting, result);
3446 }
3447
3448 public void testArgumentsAsTemplatesDefaultDelimiters() throws Exception {
3449 String templates =
3450 "group test;" +newline+
3451 "method(name,size) ::= <<"+newline+
3452 "$stat(value={$size$})$" +newline+
3453 ">>"+newline+
3454 "stat(value) ::= \"x=$value$;\""+newline
3455 ;
3456 StringTemplateGroup group =
3457 new StringTemplateGroup(new StringReader(templates),
3458 DefaultTemplateLexer.class);
3459 StringTemplate b = group.getInstanceOf("method");
3460 b.setAttribute("name", "foo");
3461 b.setAttribute("size", "34");
3462 String expecting = "x=34;";
3463 String result = b.toString();
3464 assertEquals(expecting, result);
3465 }
3466
3467 public void testDefaultArgsWhenNotInvoked() throws Exception {
3468 String templates =
3469 "group test;" +newline+
3470 "b(name=\"foo\") ::= \".<name>.\""+newline
3471 ;
3472 StringTemplateGroup group =
3473 new StringTemplateGroup(new StringReader(templates));
3474 StringTemplate b = group.getInstanceOf("b");
3475 String expecting = ".foo.";
3476 String result = b.toString();
3477 assertEquals(expecting, result);
3478 }
3479
3480 public class DateRenderer implements AttributeRenderer {
3481 public String toString(Object o) {
3482 SimpleDateFormat f = new SimpleDateFormat ("yyyy.MM.dd");
3483 return f.format(((Calendar)o).getTime());
3484 }
3485 public String toString(Object o, String formatString) {
3486 return toString(o);
3487 }
3488 }
3489
3490 public class DateRenderer2 implements AttributeRenderer {
3491 public String toString(Object o) {
3492 SimpleDateFormat f = new SimpleDateFormat ("MM/dd/yyyy");
3493 return f.format(((Calendar)o).getTime());
3494 }
3495 public String toString(Object o, String formatString) {
3496 return toString(o);
3497 }
3498 }
3499
3500 public class DateRenderer3 implements AttributeRenderer {
3501 public String toString(Object o) {
3502 SimpleDateFormat f = new SimpleDateFormat ("MM/dd/yyyy");
3503 return f.format(((Calendar)o).getTime());
3504 }
3505 public String toString(Object o, String formatString) {
3506 SimpleDateFormat f = new SimpleDateFormat (formatString);
3507 return f.format(((Calendar)o).getTime());
3508 }
3509 }
3510
3511 public class StringRenderer implements AttributeRenderer {
3512 public String toString(Object o) {
3513 return (String)o;
3514 }
3515 public String toString(Object o, String formatString) {
3516 if ( formatString.equals("upper") ) {
3517 return ((String)o).toUpperCase();
3518 }
3519 return toString(o);
3520 }
3521 }
3522
3523 public void testRendererForST() throws Exception {
3524 StringTemplate st =new StringTemplate(
3525 "date: <created>",
3526 AngleBracketTemplateLexer.class);
3527 st.setAttribute("created",
3528 new GregorianCalendar(2005, 07-1, 05));
3529 st.registerRenderer(GregorianCalendar.class, new DateRenderer());
3530 String expecting = "date: 2005.07.05";
3531 String result = st.toString();
3532 assertEquals(expecting, result);
3533 }
3534
3535 public void testRendererWithFormat() throws Exception {
3536 StringTemplate st =new StringTemplate(
3537 "date: <created; format=\"yyyy.MM.dd\">",
3538 AngleBracketTemplateLexer.class);
3539 st.setAttribute("created",
3540 new GregorianCalendar(2005, 07-1, 05));
3541 st.registerRenderer(GregorianCalendar.class, new DateRenderer3());
3542 String expecting = "date: 2005.07.05";
3543 String result = st.toString();
3544 assertEquals(expecting, result);
3545 }
3546
3547 public void testRendererWithFormatAndList() throws Exception {
3548 StringTemplate st =new StringTemplate(
3549 "The names: <names; format=\"upper\">",
3550 AngleBracketTemplateLexer.class);
3551 st.setAttribute("names", "ter");
3552 st.setAttribute("names", "tom");
3553 st.setAttribute("names", "sriram");
3554 st.registerRenderer(String.class, new StringRenderer());
3555 String expecting = "The names: TERTOMSRIRAM";
3556 String result = st.toString();
3557 assertEquals(expecting, result);
3558 }
3559
3560 public void testRendererWithFormatAndSeparator() throws Exception {
3561 StringTemplate st =new StringTemplate(
3562 "The names: <names; separator=\" and \", format=\"upper\">",
3563 AngleBracketTemplateLexer.class);
3564 st.setAttribute("names", "ter");
3565 st.setAttribute("names", "tom");
3566 st.setAttribute("names", "sriram");
3567 st.registerRenderer(String.class, new StringRenderer());
3568 String expecting = "The names: TER and TOM and SRIRAM";
3569 String result = st.toString();
3570 assertEquals(expecting, result);
3571 }
3572
3573 public void testRendererWithFormatAndSeparatorAndNull() throws Exception {
3574 StringTemplate st =new StringTemplate(
3575 "The names: <names; separator=\" and \", null=\"n/a\", format=\"upper\">",
3576 AngleBracketTemplateLexer.class);
3577 List names = new ArrayList();
3578 names.add("ter");
3579 names.add(null);
3580 names.add("sriram");
3581 st.setAttribute("names", names);
3582 st.registerRenderer(String.class, new StringRenderer());
3583 String expecting = "The names: TER and N/A and SRIRAM";
3584 String result = st.toString();
3585 assertEquals(expecting, result);
3586 }
3587
3588 public void testEmbeddedRendererSeesEnclosing() throws Exception {
3589 // st is embedded in outer; set renderer on outer, st should
3590 // still see it.
3591 StringTemplate outer =new StringTemplate(
3592 "X: <x>",
3593 AngleBracketTemplateLexer.class);
3594 StringTemplate st =new StringTemplate(
3595 "date: <created>",
3596 AngleBracketTemplateLexer.class);
3597 st.setAttribute("created",
3598 new GregorianCalendar(2005, 07-1, 05));
3599 outer.setAttribute("x", st);
3600 outer.registerRenderer(GregorianCalendar.class, new DateRenderer());
3601 String expecting = "X: date: 2005.07.05";
3602 String result = outer.toString();
3603 assertEquals(expecting, result);
3604 }
3605
3606 public void testRendererForGroup() throws Exception {
3607 String templates =
3608 "group test;" +newline+
3609 "dateThing(created) ::= \"date: <created>\""+newline
3610 ;
3611 StringTemplateGroup group =
3612 new StringTemplateGroup(new StringReader(templates));
3613 StringTemplate st = group.getInstanceOf("dateThing");
3614 st.setAttribute("created",
3615 new GregorianCalendar(2005, 07-1, 05));
3616 group.registerRenderer(GregorianCalendar.class, new DateRenderer());
3617 String expecting = "date: 2005.07.05";
3618 String result = st.toString();
3619 assertEquals(expecting, result);
3620 }
3621
3622 public void testOverriddenRenderer() throws Exception {
3623 String templates =
3624 "group test;" +newline+
3625 "dateThing(created) ::= \"date: <created>\""+newline
3626 ;
3627 StringTemplateGroup group =
3628 new StringTemplateGroup(new StringReader(templates));
3629 StringTemplate st = group.getInstanceOf("dateThing");
3630 st.setAttribute("created",
3631 new GregorianCalendar(2005, 07-1, 05));
3632 group.registerRenderer(GregorianCalendar.class, new DateRenderer());
3633 st.registerRenderer(GregorianCalendar.class, new DateRenderer2());
3634 String expecting = "date: 07/05/2005";
3635 String result = st.toString();
3636 assertEquals(expecting, result);
3637 }
3638
3639 public void testMap() throws Exception {
3640 String templates =
3641 "group test;" +newline+
3642 "typeInit ::= [\"int\":\"0\", \"float\":\"0.0\"] "+newline+
3643 "var(type,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3644 ;
3645 StringTemplateGroup group =
3646 new StringTemplateGroup(new StringReader(templates));
3647 StringTemplate st = group.getInstanceOf("var");
3648 st.setAttribute("type", "int");
3649 st.setAttribute("name", "x");
3650 String expecting = "int x = 0;";
3651 String result = st.toString();
3652 assertEquals(expecting, result);
3653 }
3654
3655 public void testMapValuesAreTemplates() throws Exception {
3656 String templates =
3657 "group test;" +newline+
3658 "typeInit ::= [\"int\":\"0<w>\", \"float\":\"0.0<w>\"] "+newline+
3659 "var(type,w,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3660 ;
3661 StringTemplateGroup group =
3662 new StringTemplateGroup(new StringReader(templates));
3663 StringTemplate st = group.getInstanceOf("var");
3664 st.setAttribute("w", "L");
3665 st.setAttribute("type", "int");
3666 st.setAttribute("name", "x");
3667 String expecting = "int x = 0L;";
3668 String result = st.toString();
3669 assertEquals(expecting, result);
3670 }
3671
3672 public void testMapKeyLookupViaTemplate() throws Exception {
3673 // ST doesn't do a toString on .(key) values, it just uses the value
3674 // of key rather than key itself as the key. But, if you compute a
3675 // key via a template
3676 String templates =
3677 "group test;" +newline+
3678 "typeInit ::= [\"int\":\"0<w>\", \"float\":\"0.0<w>\"] "+newline+
3679 "var(type,w,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3680 ;
3681 StringTemplateGroup group =
3682 new StringTemplateGroup(new StringReader(templates));
3683 StringTemplate st = group.getInstanceOf("var");
3684 st.setAttribute("w", "L");
3685 st.setAttribute("type", new StringTemplate("int"));
3686 st.setAttribute("name", "x");
3687 String expecting = "int x = 0L;";
3688 String result = st.toString();
3689 assertEquals(expecting, result);
3690 }
3691
3692 public void testMapMissingDefaultValueIsEmpty() throws Exception {
3693 String templates =
3694 "group test;" +newline+
3695 "typeInit ::= [\"int\":\"0\", \"float\":\"0.0\"] "+newline+
3696 "var(type,w,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3697 ;
3698 StringTemplateGroup group =
3699 new StringTemplateGroup(new StringReader(templates));
3700 StringTemplate st = group.getInstanceOf("var");
3701 st.setAttribute("w", "L");
3702 st.setAttribute("type", "double"); // double not in typeInit map
3703 st.setAttribute("name", "x");
3704 String expecting = "double x = ;"; // weird, but tests default value is key
3705 String result = st.toString();
3706 assertEquals(expecting, result);
3707 }
3708
3709 public void testMapHiddenByFormalArg() throws Exception {
3710 String templates =
3711 "group test;" +newline+
3712 "typeInit ::= [\"int\":\"0\", \"float\":\"0.0\"] "+newline+
3713 "var(typeInit,type,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3714 ;
3715 StringTemplateGroup group =
3716 new StringTemplateGroup(new StringReader(templates));
3717 StringTemplate st = group.getInstanceOf("var");
3718 st.setAttribute("type", "int");
3719 st.setAttribute("name", "x");
3720 String expecting = "int x = ;";
3721 String result = st.toString();
3722 assertEquals(expecting, result);
3723 }
3724
3725 public void testMapEmptyValueAndAngleBracketStrings() throws Exception {
3726 String templates =
3727 "group test;" +newline+
3728 "typeInit ::= [\"int\":\"0\", \"float\":, \"double\":<<0.0L>>] "+newline+
3729 "var(type,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3730 ;
3731 StringTemplateGroup group =
3732 new StringTemplateGroup(new StringReader(templates));
3733 StringTemplate st = group.getInstanceOf("var");
3734 st.setAttribute("type", "float");
3735 st.setAttribute("name", "x");
3736 String expecting = "float x = ;";
3737 String result = st.toString();
3738 assertEquals(expecting, result);
3739 }
3740
3741 public void testMapDefaultValue() throws Exception {
3742 String templates =
3743 "group test;" +newline+
3744 "typeInit ::= [\"int\":\"0\", default:\"null\"] "+newline+
3745 "var(type,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3746 ;
3747 StringTemplateGroup group =
3748 new StringTemplateGroup(new StringReader(templates));
3749 StringTemplate st = group.getInstanceOf("var");
3750 st.setAttribute("type", "UserRecord");
3751 st.setAttribute("name", "x");
3752 String expecting = "UserRecord x = null;";
3753 String result = st.toString();
3754 assertEquals(expecting, result);
3755 }
3756
3757 public void testMapEmptyDefaultValue() throws Exception {
3758 String templates =
3759 "group test;" +newline+
3760 "typeInit ::= [\"int\":\"0\", default:] "+newline+
3761 "var(type,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3762 ;
3763 StringTemplateGroup group =
3764 new StringTemplateGroup(new StringReader(templates));
3765 StringTemplate st = group.getInstanceOf("var");
3766 st.setAttribute("type", "UserRecord");
3767 st.setAttribute("name", "x");
3768 String expecting = "UserRecord x = ;";
3769 String result = st.toString();
3770 assertEquals(expecting, result);
3771 }
3772
3773 public void testMapDefaultValueIsKey() throws Exception {
3774 String templates =
3775 "group test;" +newline+
3776 "typeInit ::= [\"int\":\"0\", default:key] "+newline+
3777 "var(type,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3778 ;
3779 StringTemplateGroup group =
3780 new StringTemplateGroup(new StringReader(templates));
3781 StringTemplate st = group.getInstanceOf("var");
3782 st.setAttribute("type", "UserRecord");
3783 st.setAttribute("name", "x");
3784 String expecting = "UserRecord x = UserRecord;";
3785 String result = st.toString();
3786 assertEquals(expecting, result);
3787 }
3788
3789 /**
3790 * Test that a map can have only the default entry.
3791 * <p>
3792 * Bug ref: JIRA bug ST-15 (Fixed)
3793 */
3794 public void testMapDefaultStringAsKey() throws Exception {
3795 String templates =
3796 "group test;" +newline+
3797 "typeInit ::= [\"default\":\"foo\"] "+newline+
3798 "var(type,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3799 ;
3800 StringTemplateGroup group =
3801 new StringTemplateGroup(new StringReader(templates));
3802 StringTemplate st = group.getInstanceOf("var");
3803 st.setAttribute("type", "default");
3804 st.setAttribute("name", "x");
3805 String expecting = "default x = foo;";
3806 String result = st.toString();
3807 assertEquals(expecting, result);
3808 }
3809
3810 /**
3811 * Test that a map can return a <b>string</b> with the word: default.
3812 * <p>
3813 * Bug ref: JIRA bug ST-15 (Fixed)
3814 */
3815 public void testMapDefaultIsDefaultString() throws Exception {
3816 String templates =
3817 "group test;" +newline+
3818 "map ::= [default: \"default\"] "+newline+
3819 "t1() ::= \"<map.(1)>\""+newline
3820 ;
3821 StringTemplateGroup group =
3822 new StringTemplateGroup(new StringReader(templates));
3823 StringTemplate st = group.getInstanceOf("t1");
3824 String expecting = "default";
3825 String result = st.toString();
3826 assertEquals(expecting, result);
3827 }
3828
3829 public void testMapViaEnclosingTemplates() throws Exception {
3830 String templates =
3831 "group test;" +newline+
3832 "typeInit ::= [\"int\":\"0\", \"float\":\"0.0\"] "+newline+
3833 "intermediate(type,name) ::= \"<var(...)>\""+newline+
3834 "var(type,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3835 ;
3836 StringTemplateGroup group =
3837 new StringTemplateGroup(new StringReader(templates));
3838 StringTemplate st = group.getInstanceOf("intermediate");
3839 st.setAttribute("type", "int");
3840 st.setAttribute("name", "x");
3841 String expecting = "int x = 0;";
3842 String result = st.toString();
3843 assertEquals(expecting, result);
3844 }
3845
3846 public void testMapViaEnclosingTemplates2() throws Exception {
3847 String templates =
3848 "group test;" +newline+
3849 "typeInit ::= [\"int\":\"0\", \"float\":\"0.0\"] "+newline+
3850 "intermediate(stuff) ::= \"<stuff>\""+newline+
3851 "var(type,name) ::= \"<type> <name> = <typeInit.(type)>;\""+newline
3852 ;
3853 StringTemplateGroup group =
3854 new StringTemplateGroup(new StringReader(templates));
3855 StringTemplate interm = group.getInstanceOf("intermediate");
3856 StringTemplate var = group.getInstanceOf("var");
3857 var.setAttribute("type", "int");
3858 var.setAttribute("name", "x");
3859 interm.setAttribute("stuff", var);
3860 String expecting = "int x = 0;";
3861 String result = interm.toString();
3862 assertEquals(expecting, result);
3863 }
3864
3865 public void testEmptyGroupTemplate() throws Exception {
3866 String templates =
3867 "group test;" +newline+
3868 "foo() ::= \"\""+newline
3869 ;
3870 StringTemplateGroup group =
3871 new StringTemplateGroup(new StringReader(templates));
3872 StringTemplate a = group.getInstanceOf("foo");
3873 String expecting = "";
3874 String result = a.toString();
3875 assertEquals(expecting, result);
3876 }
3877
3878 public void testEmptyStringAndEmptyAnonTemplateAsParameterUsingAngleBracketLexer() throws Exception {
3879 String templates =
3880 "group test;" +newline+
3881 "top() ::= <<<x(a=\"\", b={})\\>>>"+newline+
3882 "x(a,b) ::= \"a=<a>, b=<b>\""+newline;
3883 ;
3884 StringTemplateGroup group =
3885 new StringTemplateGroup(new StringReader(templates));
3886 StringTemplate a = group.getInstanceOf("top");
3887 String expecting = "a=, b=";
3888 String result = a.toString();
3889 assertEquals(expecting, result);
3890 }
3891
3892 public void testEmptyStringAndEmptyAnonTemplateAsParameterUsingDollarLexer() throws Exception {
3893 String templates =
3894 "group test;" +newline+
3895 "top() ::= <<$x(a=\"\", b={})$>>"+newline+
3896 "x(a,b) ::= \"a=$a$, b=$b$\""+newline;
3897 ;
3898 StringTemplateGroup group =
3899 new StringTemplateGroup(new StringReader(templates),
3900 DefaultTemplateLexer.class);
3901 StringTemplate a = group.getInstanceOf("top");
3902 String expecting = "a=, b=";
3903 String result = a.toString();
3904 assertEquals(expecting, result);
3905 }
3906
3907 /**
3908 * FIXME: Dannish does not work if typed directly in with default file
3909 * encoding on windows. The character needs to be escaped as bellow.
3910 * Please correct to escape the correct charcter.
3911 */
3912 public void test8BitEuroChars() throws Exception {
3913 StringTemplate e = new StringTemplate(
3914 "Danish: \u0143 char"
3915 );
3916 e = e.getInstanceOf();
3917 String expecting = "Danish: \u0143 char";
3918 assertEquals(expecting, e.toString());
3919 }
3920
3921 public void test16BitUnicodeChar() throws Exception {
3922 StringTemplate e = new StringTemplate(
3923 "DINGBAT CIRCLED SANS-SERIF DIGIT ONE: \u2780"
3924 );
3925 e = e.getInstanceOf();
3926 String expecting = "DINGBAT CIRCLED SANS-SERIF DIGIT ONE: \u2780";
3927 assertEquals(expecting, e.toString());
3928 }
3929
3930 public void testFirstOp() throws Exception {
3931 StringTemplate e = new StringTemplate(
3932 "$first(names)$"
3933 );
3934 e = e.getInstanceOf();
3935 e.setAttribute("names", "Ter");
3936 e.setAttribute("names", "Tom");
3937 e.setAttribute("names", "Sriram");
3938 String expecting = "Ter";
3939 assertEquals(expecting, e.toString());
3940 }
3941
3942 public void testTruncOp() throws Exception {
3943 StringTemplate e = new StringTemplate(
3944 "$trunc(names); separator=\", \"$"
3945 );
3946 e = e.getInstanceOf();
3947 e.setAttribute("names", "Ter");
3948 e.setAttribute("names", "Tom");
3949 e.setAttribute("names", "Sriram");
3950 String expecting = "Ter, Tom";
3951 assertEquals(expecting, e.toString());
3952 }
3953
3954 public void testRestOp() throws Exception {
3955 StringTemplate e = new StringTemplate(
3956 "$rest(names); separator=\", \"$"
3957 );
3958 e = e.getInstanceOf();
3959 e.setAttribute("names", "Ter");
3960 e.setAttribute("names", "Tom");
3961 e.setAttribute("names", "Sriram");
3962 String expecting = "Tom, Sriram";
3963 assertEquals(expecting, e.toString());
3964 }
3965
3966 public void testRestOpEmptyList() throws Exception {
3967 StringTemplate e = new StringTemplate(
3968 "$rest(names); separator=\", \"$"
3969 );
3970 e = e.getInstanceOf();
3971 e.setAttribute("names", new ArrayList());
3972 String expecting = "";
3973 assertEquals(expecting, e.toString());
3974 }
3975
3976 public void testReUseOfRestResult() throws Exception {
3977 String templates =
3978 "group test;" +newline+
3979 "a(names) ::= \"<b(rest(names))>\""+newline+
3980 "b(x) ::= \"<x>, <x>\""+newline
3981 ;
3982 StringTemplateGroup group =
3983 new StringTemplateGroup(new StringReader(templates));
3984 StringTemplate e = group.getInstanceOf("a");
3985 List names = new ArrayList();
3986 names.add("Ter");
3987 names.add("Tom");
3988 e.setAttribute("names", names);
3989 String expecting = "Tom, Tom";
3990 assertEquals(expecting, e.toString());
3991 }
3992
3993 public void testLastOp() throws Exception {
3994 StringTemplate e = new StringTemplate(
3995 "$last(names)$"
3996 );
3997 e = e.getInstanceOf();
3998 e.setAttribute("names", "Ter");
3999 e.setAttribute("names", "Tom");
4000 e.setAttribute("names", "Sriram");
4001 String expecting = "Sriram";
4002 assertEquals(expecting, e.toString());
4003 }
4004
4005 public void testCombinedOp() throws Exception {
4006 // replace first of yours with first of mine
4007 StringTemplate e = new StringTemplate(
4008 "$[first(mine),rest(yours)]; separator=\", \"$"
4009 );
4010 e = e.getInstanceOf();
4011 e.setAttribute("mine", "1");
4012 e.setAttribute("mine", "2");
4013 e.setAttribute("mine", "3");
4014 e.setAttribute("yours", "a");
4015 e.setAttribute("yours", "b");
4016 String expecting = "1, b";
4017 assertEquals(expecting, e.toString());
4018 }
4019
4020 public void testCatListAndSingleAttribute() throws Exception {
4021 // replace first of yours with first of mine
4022 StringTemplate e = new StringTemplate(
4023 "$[mine,yours]; separator=\", \"$"
4024 );
4025 e = e.getInstanceOf();
4026 e.setAttribute("mine", "1");
4027 e.setAttribute("mine", "2");
4028 e.setAttribute("mine", "3");
4029 e.setAttribute("yours", "a");
4030 String expecting = "1, 2, 3, a";
4031 assertEquals(expecting, e.toString());
4032 }
4033
4034 public void testReUseOfCat() throws Exception {
4035 String templates =
4036 "group test;" +newline+
4037 "a(mine,yours) ::= \"<b([mine,yours])>\""+newline+
4038 "b(x) ::= \"<x>, <x>\""+newline
4039 ;
4040 StringTemplateGroup group =
4041 new StringTemplateGroup(new StringReader(templates));
4042 StringTemplate e = group.getInstanceOf("a");
4043 List mine = new ArrayList();
4044 mine.add("Ter");
4045 mine.add("Tom");
4046 e.setAttribute("mine", mine);
4047 List yours = new ArrayList();
4048 yours.add("Foo");
4049 e.setAttribute("yours", yours);
4050 String expecting = "TerTomFoo, TerTomFoo";
4051 assertEquals(expecting, e.toString());
4052 }
4053
4054 public void testCatListAndEmptyAttributes() throws Exception {
4055 // + is overloaded to be cat strings and cat lists so the
4056 // two operands (from left to right) determine which way it
4057 // goes. In this case, x+mine is a list so everything from their
4058 // to the right becomes list cat.
4059 StringTemplate e = new StringTemplate(
4060 "$[x,mine,y,yours,z]; separator=\", \"$"
4061 );
4062 e = e.getInstanceOf();
4063 e.setAttribute("mine", "1");
4064 e.setAttribute("mine", "2");
4065 e.setAttribute("mine", "3");
4066 e.setAttribute("yours", "a");
4067 String expecting = "1, 2, 3, a";
4068 assertEquals(expecting, e.toString());
4069 }
4070
4071 public void testNestedOp() throws Exception {
4072 StringTemplate e = new StringTemplate(
4073 "$first(rest(names))$" // gets 2nd element
4074 );
4075 e = e.getInstanceOf();
4076 e.setAttribute("names", "Ter");
4077 e.setAttribute("names", "Tom");
4078 e.setAttribute("names", "Sriram");
4079 String expecting = "Tom";
4080 assertEquals(expecting, e.toString());
4081 }
4082
4083 public void testFirstWithOneAttributeOp() throws Exception {
4084 StringTemplate e = new StringTemplate(
4085 "$first(names)$"
4086 );
4087 e = e.getInstanceOf();
4088 e.setAttribute("names", "Ter");
4089 String expecting = "Ter";
4090 assertEquals(expecting, e.toString());
4091 }
4092
4093 public void testLastWithOneAttributeOp() throws Exception {
4094 StringTemplate e = new StringTemplate(
4095 "$last(names)$"
4096 );
4097 e = e.getInstanceOf();
4098 e.setAttribute("names", "Ter");
4099 String expecting = "Ter";
4100 assertEquals(expecting, e.toString());
4101 }
4102
4103 public void testLastWithLengthOneListAttributeOp() throws Exception {
4104 StringTemplate e = new StringTemplate(
4105 "$last(names)$"
4106 );
4107 e = e.getInstanceOf();
4108 e.setAttribute("names", new ArrayList() {{add("Ter");}});
4109 String expecting = "Ter";
4110 assertEquals(expecting, e.toString());
4111 }
4112
4113 public void testRestWithOneAttributeOp() throws Exception {
4114 StringTemplate e = new StringTemplate(
4115 "$rest(names)$"
4116 );
4117 e = e.getInstanceOf();
4118 e.setAttribute("names", "Ter");
4119 String expecting = "";
4120 assertEquals(expecting, e.toString());
4121 }
4122
4123 public void testRestWithLengthOneListAttributeOp() throws Exception {
4124 StringTemplate e = new StringTemplate(
4125 "$rest(names)$"
4126 );
4127 e = e.getInstanceOf();
4128 e.setAttribute("names", new ArrayList() {{add("Ter");}});
4129 String expecting = "";
4130 assertEquals(expecting, e.toString());
4131 }
4132
4133 public void testRepeatedRestOp() throws Exception {
4134 StringTemplate e = new StringTemplate(
4135 "$rest(names)$, $rest(names)$" // gets 2nd element
4136 );
4137 e = e.getInstanceOf();
4138 e.setAttribute("names", "Ter");
4139 e.setAttribute("names", "Tom");
4140 String expecting = "Tom, Tom";
4141 assertEquals(expecting, e.toString());
4142 }
4143
4144 /** If an iterator is sent into ST, it must be cannot be reset after each
4145 * use so repeated refs yield empty values. This would
4146 * work if we passed in a List not an iterator. Avoid sending in iterators
4147 * if you ref it twice.
4148 */
4149 public void testRepeatedIteratedAttrFromArg() throws Exception {
4150 String templates =
4151 "group test;" +newline+
4152 "root(names) ::= \"$other(names)$\""+newline+
4153 "other(x) ::= \"$x$, $x$\""+newline
4154 ;
4155 StringTemplateGroup group =
4156 new StringTemplateGroup(new StringReader(templates),
4157 DefaultTemplateLexer.class);
4158 StringTemplate e = group.getInstanceOf("root");
4159 List names = new ArrayList();
4160 names.add("Ter");
4161 names.add("Tom");
4162 e.setAttribute("names", names.iterator());
4163 String expecting = "TerTom, "; // This does not give TerTom twice!!
4164 assertEquals(expecting, e.toString());
4165 }
4166
4167 /** FIXME: BUG! Iterator is not reset from first to second $x$
4168 * Either reset the iterator or pass an attribute that knows to get
4169 * the iterator each time. Seems like first, tail do not
4170 * have same problem as they yield objects.
4171 *
4172 * Maybe make a RestIterator like I have CatIterator.
4173 */
4174 /*
4175 public void testRepeatedRestOpAsArg() throws Exception {
4176 String templates =
4177 "group test;" +newline+
4178 "root(names) ::= \"$other(rest(names))$\""+newline+
4179 "other(x) ::= \"$x$, $x$\""+newline
4180 ;
4181 StringTemplateGroup group =
4182 new StringTemplateGroup(new StringReader(templates),
4183 DefaultTemplateLexer.class);
4184 StringTemplate e = group.getInstanceOf("root");
4185 e.setAttribute("names", "Ter");
4186 e.setAttribute("names", "Tom");
4187 String expecting = "Tom, Tom";
4188 assertEquals(expecting, e.toString());
4189 }
4190 */
4191
4192 public void testIncomingLists() throws Exception {
4193 StringTemplate e = new StringTemplate(
4194 "$rest(names)$, $rest(names)$" // gets 2nd element
4195 );
4196 e = e.getInstanceOf();
4197 e.setAttribute("names", "Ter");
4198 e.setAttribute("names", "Tom");
4199 String expecting = "Tom, Tom";
4200 assertEquals(expecting, e.toString());
4201 }
4202
4203 public void testIncomingListsAreNotModified() throws Exception {
4204 StringTemplate e = new StringTemplate(
4205 "$names; separator=\", \"$" // gets 2nd element
4206 );
4207 e = e.getInstanceOf();
4208 List names = new ArrayList();
4209 names.add("Ter");
4210 names.add("Tom");
4211 e.setAttribute("names", names);
4212 e.setAttribute("names", "Sriram");
4213 String expecting = "Ter, Tom, Sriram";
4214 assertEquals(expecting, e.toString());
4215
4216 assertEquals(names.size(), 2);
4217 }
4218
4219 public void testIncomingListsAreNotModified2() throws Exception {
4220 StringTemplate e = new StringTemplate(
4221 "$names; separator=\", \"$" // gets 2nd element
4222 );
4223 e = e.getInstanceOf();
4224 List names = new ArrayList();
4225 names.add("Ter");
4226 names.add("Tom");
4227 e.setAttribute("names", "Sriram"); // single element first now
4228 e.setAttribute("names", names);
4229 String expecting = "Sriram, Ter, Tom";
4230 assertEquals(expecting, e.toString());
4231
4232 assertEquals(names.size(), 2);
4233 }
4234
4235 public void testIncomingArraysAreOk() throws Exception {
4236 StringTemplate e = new StringTemplate(
4237 "$names; separator=\", \"$" // gets 2nd element
4238 );
4239 e = e.getInstanceOf();
4240 e.setAttribute("names", new String[] {"Ter","Tom"});
4241 e.setAttribute("names", "Sriram");
4242 String expecting = "Ter, Tom, Sriram";
4243 assertEquals(expecting, e.toString());
4244 }
4245
4246 public void testMultipleRefsToListAttribute() throws Exception {
4247 String templates =
4248 "group test;" +newline+
4249 "f(x) ::= \"<x> <x>\""+newline
4250 ;
4251 StringTemplateGroup group =
4252 new StringTemplateGroup(new StringReader(templates));
4253 StringTemplate e = group.getInstanceOf("f");
4254 e.setAttribute("x", "Ter");
4255 e.setAttribute("x", "Tom");
4256 String expecting = "TerTom TerTom";
4257 assertEquals(expecting, e.toString());
4258 }
4259
4260 public void testApplyTemplateWithSingleFormalArgs() throws Exception {
4261 String templates =
4262 "group test;" +newline+
4263 "test(names) ::= <<<names:bold(item=it); separator=\", \"> >>"+newline+
4264 "bold(item) ::= <<*<item>*>>"+newline
4265 ;
4266 StringTemplateGroup group =
4267 new StringTemplateGroup(new StringReader(templates));
4268 StringTemplate e = group.getInstanceOf("test");
4269 e.setAttribute("names", "Ter");
4270 e.setAttribute("names", "Tom");
4271 String expecting = "*Ter*, *Tom* ";
4272 String result = e.toString();
4273 assertEquals(expecting, result);
4274 }
4275
4276 public void testApplyTemplateWithNoFormalArgs() throws Exception {
4277 String templates =
4278 "group test;" +newline+
4279 "test(names) ::= <<<names:bold(); separator=\", \"> >>"+newline+
4280 "bold() ::= <<*<it>*>>"+newline
4281 ;
4282 StringTemplateGroup group =
4283 new StringTemplateGroup(new StringReader(templates),
4284 AngleBracketTemplateLexer.class);
4285 StringTemplate e = group.getInstanceOf("test");
4286 e.setAttribute("names", "Ter");
4287 e.setAttribute("names", "Tom");
4288 String expecting = "*Ter*, *Tom* ";
4289 String result = e.toString();
4290 assertEquals(expecting, result);
4291 }
4292
4293 public void testAnonTemplateArgs() throws Exception {
4294 StringTemplate e = new StringTemplate(
4295 "$names:{n| $n$}; separator=\", \"$"
4296 );
4297 e = e.getInstanceOf();
4298 e.setAttribute("names", "Ter");
4299 e.setAttribute("names", "Tom");
4300 String expecting = "Ter, Tom";
4301 assertEquals(expecting, e.toString());
4302 }
4303
4304 public void testAnonTemplateWithArgHasNoITArg() throws Exception {
4305 StringTemplate e = new StringTemplate(
4306 "$names:{n| $n$:$it$}; separator=\", \"$"
4307 );
4308 e = e.getInstanceOf();
4309 e.setAttribute("names", "Ter");
4310 e.setAttribute("names", "Tom");
4311 String error = null;
4312 try {
4313 e.toString();
4314 }
4315 catch (NoSuchElementException nse) {
4316 error = nse.getMessage();
4317 }
4318 String expecting = "no such attribute: it in template context [anonymous anonymous]";
4319 assertEquals(error, expecting);
4320 }
4321
4322 public void testAnonTemplateArgs2() throws Exception {
4323 StringTemplate e = new StringTemplate(
4324 "$names:{n| .$n$.}:{ n | _$n$_}; separator=\", \"$"
4325 );
4326 e = e.getInstanceOf();
4327 e.setAttribute("names", "Ter");
4328 e.setAttribute("names", "Tom");
4329 String expecting = "_.Ter._, _.Tom._";
4330 assertEquals(expecting, e.toString());
4331 }
4332
4333 public void testFirstWithCatAttribute() throws Exception {
4334 StringTemplate e = new StringTemplate(
4335 "$first([names,phones])$"
4336 );
4337 e = e.getInstanceOf();
4338 e.setAttribute("names", "Ter");
4339 e.setAttribute("names", "Tom");
4340 e.setAttribute("phones", "1");
4341 e.setAttribute("phones", "2");
4342 String expecting = "Ter";
4343 assertEquals(expecting, e.toString());
4344 }
4345
4346 public void testFirstWithListOfMaps() throws Exception {
4347 StringTemplate e = new StringTemplate(
4348 "$first(maps).Ter$"
4349 );
4350 e = e.getInstanceOf();
4351 final Map m1 = new HashMap();
4352 final Map m2 = new HashMap();
4353 m1.put("Ter", "x5707");
4354 e.setAttribute("maps", m1);
4355 m2.put("Tom", "x5332");
4356 e.setAttribute("maps", m2);
4357 String expecting = "x5707";
4358 assertEquals(expecting, e.toString());
4359
4360 e = e.getInstanceOf();
4361 List list = new ArrayList() {{add(m1); add(m2);}};
4362 e.setAttribute("maps", list);
4363 expecting = "x5707";
4364 assertEquals(expecting, e.toString());
4365 }
4366
4367 // this FAILS!
4368 /*
4369 public void testFirstWithListOfMaps2() throws Exception {
4370 StringTemplate e = new StringTemplate(
4371 "$first(maps):{ m | $m.Ter$ }$"
4372 );
4373 final Map m1 = new HashMap();
4374 final Map m2 = new HashMap();
4375 m1.put("Ter", "x5707");
4376 e.setAttribute("maps", m1);
4377 m2.put("Tom", "x5332");
4378 e.setAttribute("maps", m2);
4379 String expecting = "x5707";
4380 assertEquals(expecting, e.toString());
4381
4382 e = e.getInstanceOf();
4383 List list = new ArrayList() {{add(m1); add(m2);}};
4384 e.setAttribute("maps", list);
4385 expecting = "x5707";
4386 assertEquals(expecting, e.toString());
4387 }
4388 */
4389 public void testJustCat() throws Exception {
4390 StringTemplate e = new StringTemplate(
4391 "$[names,phones]$"
4392 );
4393 e = e.getInstanceOf();
4394 e.setAttribute("names", "Ter");
4395 e.setAttribute("names", "Tom");
4396 e.setAttribute("phones", "1");
4397 e.setAttribute("phones", "2");
4398 String expecting = "TerTom12";
4399 assertEquals(expecting, e.toString());
4400 }
4401
4402 public void testCat2Attributes() throws Exception {
4403 StringTemplate e = new StringTemplate(
4404 "$[names,phones]; separator=\", \"$"
4405 );
4406 e = e.getInstanceOf();
4407 e.setAttribute("names", "Ter");
4408 e.setAttribute("names", "Tom");
4409 e.setAttribute("phones", "1");
4410 e.setAttribute("phones", "2");
4411 String expecting = "Ter, Tom, 1, 2";
4412 assertEquals(expecting, e.toString());
4413 }
4414
4415 public void testCat2AttributesWithApply() throws Exception {
4416 StringTemplate e = new StringTemplate(
4417 "$[names,phones]:{a|$a$.}$"
4418 );
4419 e = e.getInstanceOf();
4420 e.setAttribute("names", "Ter");
4421 e.setAttribute("names", "Tom");
4422 e.setAttribute("phones", "1");
4423 e.setAttribute("phones", "2");
4424 String expecting = "Ter.Tom.1.2.";
4425 assertEquals(expecting, e.toString());
4426 }
4427
4428 public void testCat3Attributes() throws Exception {
4429 StringTemplate e = new StringTemplate(
4430 "$[names,phones,salaries]; separator=\", \"$"
4431 );
4432 e = e.getInstanceOf();
4433 e.setAttribute("names", "Ter");
4434 e.setAttribute("names", "Tom");
4435 e.setAttribute("phones", "1");
4436 e.setAttribute("phones", "2");
4437 e.setAttribute("salaries", "big");
4438 e.setAttribute("salaries", "huge");
4439 String expecting = "Ter, Tom, 1, 2, big, huge";
4440 assertEquals(expecting, e.toString());
4441 }
4442
4443 public void testCatWithTemplateApplicationAsElement() throws Exception {
4444 StringTemplate e = new StringTemplate(
4445 "$[names:{$it$!},phones]; separator=\", \"$"
4446 );
4447 e = e.getInstanceOf();
4448 e.setAttribute("names", "Ter");
4449 e.setAttribute("names", "Tom");
4450 e.setAttribute("phones" , "1");
4451 e.setAttribute("phones", "2");
4452 String expecting = "Ter!, Tom!, 1, 2";
4453 assertEquals(expecting, e.toString());
4454 }
4455
4456 public void testCatWithIFAsElement() throws Exception {
4457 StringTemplate e = new StringTemplate(
4458 "$[{$if(names)$doh$endif$},phones]; separator=\", \"$"
4459 );
4460 e = e.getInstanceOf();
4461 e.setAttribute("names", "Ter");
4462 e.setAttribute("names", "Tom");
4463 e.setAttribute("phones" , "1");
4464 e.setAttribute("phones", "2");
4465 String expecting = "doh, 1, 2";
4466 assertEquals(expecting, e.toString());
4467 }
4468
4469 public void testCatWithNullTemplateApplicationAsElement() throws Exception {
4470 StringTemplate e = new StringTemplate(
4471 "$[names:{$it$!},\"foo\"]:{x}; separator=\", \"$"
4472 );
4473 e = e.getInstanceOf();
4474 e.setAttribute("phones", "1");
4475 e.setAttribute("phones", "2");
4476 String expecting = "x"; // only one since template application gives nothing
4477 assertEquals(expecting, e.toString());
4478 }
4479
4480 public void testCatWithNestedTemplateApplicationAsElement() throws Exception {
4481 StringTemplate e = new StringTemplate(
4482 "$[names, [\"foo\",\"bar\"]:{$it$!},phones]; separator=\", \"$"
4483 );
4484 e = e.getInstanceOf();
4485 e.setAttribute("names", "Ter");
4486 e.setAttribute("names", "Tom");
4487 e.setAttribute("phones", "1");
4488 e.setAttribute("phones", "2");
4489 String expecting = "Ter, Tom, foo!, bar!, 1, 2";
4490 assertEquals(expecting, e.toString());
4491 }
4492
4493 public void testListAsTemplateArgument() throws Exception {
4494 String templates =
4495 "group test;" +newline+
4496 "test(names,phones) ::= \"<foo([names,phones])>\""+newline+
4497 "foo(items) ::= \"<items:{a | *<a>*}>\""+newline
4498 ;
4499 StringTemplateGroup group =
4500 new StringTemplateGroup(new StringReader(templates),
4501 AngleBracketTemplateLexer.class);
4502 StringTemplate e = group.getInstanceOf("test");
4503 e.setAttribute("names", "Ter");
4504 e.setAttribute("names", "Tom");
4505 e.setAttribute("phones", "1");
4506 e.setAttribute("phones", "2");
4507 String expecting = "*Ter**Tom**1**2*";
4508 String result = e.toString();
4509 assertEquals(expecting, result);
4510 }
4511
4512 public void testSingleExprTemplateArgument() throws Exception {
4513 String templates =
4514 "group test;" +newline+
4515 "test(name) ::= \"<bold(name)>\""+newline+
4516 "bold(item) ::= \"*<item>*\""+newline
4517 ;
4518 StringTemplateGroup group =
4519 new StringTemplateGroup(new StringReader(templates),
4520 AngleBracketTemplateLexer.class);
4521 StringTemplate e = group.getInstanceOf("test");
4522 e.setAttribute("name", "Ter");
4523 String expecting = "*Ter*";
4524 String result = e.toString();
4525 assertEquals(expecting, result);
4526 }
4527
4528 public void testSingleExprTemplateArgumentInApply() throws Exception {
4529 // when you specify a single arg on a template application
4530 // it overrides the setting of the iterated value "it" to that
4531 // same single formal arg. Your arg hides the implicitly set "it".
4532 String templates =
4533 "group test;" +newline+
4534 "test(names,x) ::= \"<names:bold(x)>\""+newline+
4535 "bold(item) ::= \"*<item>*\""+newline
4536 ;
4537 StringTemplateGroup group =
4538 new StringTemplateGroup(new StringReader(templates),
4539 AngleBracketTemplateLexer.class);
4540 StringTemplate e = group.getInstanceOf("test");
4541 e.setAttribute("names", "Ter");
4542 e.setAttribute("names", "Tom");
4543 e.setAttribute("x", "ick");
4544 String expecting = "*ick**ick*";
4545 String result = e.toString();
4546 assertEquals(expecting, result);
4547 }
4548
4549 public void testSoleFormalTemplateArgumentInMultiApply() throws Exception {
4550 String templates =
4551 "group test;" +newline+
4552 "test(names) ::= \"<names:bold(),italics()>\""+newline+
4553 "bold(x) ::= \"*<x>*\""+newline+
4554 "italics(y) ::= \"_<y>_\""+newline
4555 ;
4556 StringTemplateGroup group =
4557 new StringTemplateGroup(new StringReader(templates),
4558 AngleBracketTemplateLexer.class);
4559 StringTemplate e = group.getInstanceOf("test");
4560 e.setAttribute("names", "Ter");
4561 e.setAttribute("names", "Tom");
4562 String expecting = "*Ter*_Tom_";
4563 String result = e.toString();
4564 assertEquals(expecting, result);
4565 }
4566
4567 public void testSingleExprTemplateArgumentError() throws Exception {
4568 String templates =
4569 "group test;" +newline+
4570 "test(name) ::= \"<bold(name)>\""+newline+
4571 "bold(item,ick) ::= \"*<item>*\""+newline
4572 ;
4573 StringTemplateErrorListener errors = new ErrorBuffer();
4574 StringTemplateGroup group =
4575 new StringTemplateGroup(new StringReader(templates),
4576 AngleBracketTemplateLexer.class, errors);
4577 StringTemplate e = group.getInstanceOf("test");
4578 e.setAttribute("name", "Ter");
4579 /*String result =*/ e.toString();
4580 String expecting = "template bold must have exactly one formal arg in template context [test <invoke bold arg context>]";
4581 assertEquals(errors.toString(), expecting);
4582 }
4583
4584 public void testInvokeIndirectTemplateWithSingleFormalArgs() throws Exception {
4585 String templates =
4586 "group test;" +newline+
4587 "test(templateName,arg) ::= \"<(templateName)(arg)>\""+newline+
4588 "bold(x) ::= <<*<x>*>>"+newline+
4589 "italics(y) ::= <<_<y>_>>"+newline
4590 ;
4591 StringTemplateGroup group =
4592 new StringTemplateGroup(new StringReader(templates));
4593 StringTemplate e = group.getInstanceOf("test");
4594 e.setAttribute("templateName", "italics");
4595 e.setAttribute("arg", "Ter");
4596 String expecting = "_Ter_";
4597 String result = e.toString();
4598 assertEquals(expecting, result);
4599 }
4600
4601 public void testParallelAttributeIteration() throws Exception {
4602 StringTemplate e = new StringTemplate(
4603 "$names,phones,salaries:{n,p,s | $n$@$p$: $s$\n}$"
4604 );
4605 e = e.getInstanceOf();
4606 e.setAttribute("names", "Ter");
4607 e.setAttribute("names", "Tom");
4608 e.setAttribute("phones", "1");
4609 e.setAttribute("phones", "2");
4610 e.setAttribute("salaries", "big");
4611 e.setAttribute("salaries", "huge");
4612 String expecting = "Ter@1: big"+newline+"Tom@2: huge"+newline;
4613 assertEquals(expecting, e.toString());
4614 }
4615
4616 public void testParallelAttributeIterationWithNullValue() throws Exception {
4617 StringTemplate e = new StringTemplate(
4618 "$names,phones,salaries:{n,p,s | $n$@$p$: $s$\n}$"
4619 );
4620 e = e.getInstanceOf();
4621 e.setAttribute("names", "Ter");
4622 e.setAttribute("names", "Tom");
4623 e.setAttribute("names", "Sriram");
4624 e.setAttribute("phones", new ArrayList() {{add("1"); add(null); add("3");}});
4625 e.setAttribute("salaries", "big");
4626 e.setAttribute("salaries", "huge");
4627 e.setAttribute("salaries", "enormous");
4628 String expecting = "Ter@1: big"+newline+
4629 "Tom@: huge"+newline+
4630 "Sriram@3: enormous"+newline;
4631 assertEquals(expecting, e.toString());
4632 }
4633
4634 public void testParallelAttributeIterationHasI() throws Exception {
4635 StringTemplate e = new StringTemplate(
4636 "$names,phones,salaries:{n,p,s | $i0$. $n$@$p$: $s$\n}$"
4637 );
4638 e = e.getInstanceOf();
4639 e.setAttribute("names", "Ter");
4640 e.setAttribute("names", "Tom");
4641 e.setAttribute("phones", "1");
4642 e.setAttribute("phones", "2");
4643 e.setAttribute("salaries", "big");
4644 e.setAttribute("salaries", "huge");
4645 String expecting = "0. Ter@1: big"+newline+"1. Tom@2: huge"+newline;
4646 assertEquals(expecting, e.toString());
4647 }
4648
4649 public void testParallelAttributeIterationWithDifferentSizes() throws Exception {
4650 StringTemplate e = new StringTemplate(
4651 "$names,phones,salaries:{n,p,s | $n$@$p$: $s$}; separator=\", \"$"
4652 );
4653 e = e.getInstanceOf();
4654 e.setAttribute("names", "Ter");
4655 e.setAttribute("names", "Tom");
4656 e.setAttribute("names", "Sriram");
4657 e.setAttribute("phones", "1");
4658 e.setAttribute("phones", "2");
4659 e.setAttribute("salaries", "big");
4660 String expecting = "Ter@1: big, Tom@2: , Sriram@: ";
4661 assertEquals(expecting, e.toString());
4662 }
4663
4664 public void testParallelAttributeIterationWithSingletons() throws Exception {
4665 StringTemplate e = new StringTemplate(
4666 "$names,phones,salaries:{n,p,s | $n$@$p$: $s$}; separator=\", \"$"
4667 );
4668 e = e.getInstanceOf();
4669 e.setAttribute("names", "Ter");
4670 e.setAttribute("phones", "1");
4671 e.setAttribute("salaries", "big");
4672 String expecting = "Ter@1: big";
4673 assertEquals(expecting, e.toString());
4674 }
4675
4676 public void testParallelAttributeIterationWithMismatchArgListSizes() throws Exception {
4677 StringTemplateErrorListener errors = new ErrorBuffer();
4678 StringTemplate e = new StringTemplate(
4679 "$names,phones,salaries:{n,p | $n$@$p$}; separator=\", \"$"
4680 );
4681 e.setErrorListener(errors);
4682 e = e.getInstanceOf();
4683 e.setAttribute("names", "Ter");
4684 e.setAttribute("names", "Tom");
4685 e.setAttribute("phones", "1");
4686 e.setAttribute("phones", "2");
4687 e.setAttribute("salaries", "big");
4688 String expecting = "Ter@1, Tom@2";
4689 assertEquals(expecting, e.toString());
4690 String errorExpecting = "number of arguments [n, p] mismatch between attribute list and anonymous template in context [anonymous]";
4691 assertEquals(errorExpecting, errors.toString());
4692 }
4693
4694 public void testParallelAttributeIterationWithMissingArgs() throws Exception {
4695 StringTemplateErrorListener errors = new ErrorBuffer();
4696 StringTemplate e = new StringTemplate(
4697 "$names,phones,salaries:{$n$@$p$}; separator=\", \"$"
4698 );
4699 e.setErrorListener(errors);
4700 e = e.getInstanceOf();
4701 e.setAttribute("names", "Tom");
4702 e.setAttribute("phones", "2");
4703 e.setAttribute("salaries", "big");
4704 e.toString(); // generate the error
4705 String errorExpecting = "missing arguments in anonymous template in context [anonymous]";
4706 assertEquals(errorExpecting, errors.toString());
4707 }
4708
4709 public void testParallelAttributeIterationWithDifferentSizesTemplateRefInsideToo() throws Exception {
4710 String templates =
4711 "group test;" +newline+
4712 "page(names,phones,salaries) ::= "+newline+
4713 " <<$names,phones,salaries:{n,p,s | $value(n)$@$value(p)$: $value(s)$}; separator=\", \"$>>"+newline +
4714 "value(x=\"n/a\") ::= \"$x$\"" +newline;
4715 StringTemplateGroup group =
4716 new StringTemplateGroup(new StringReader(templates),
4717 DefaultTemplateLexer.class);
4718 StringTemplate p = group.getInstanceOf("page");
4719 p.setAttribute("names", "Ter");
4720 p.setAttribute("names", "Tom");
4721 p.setAttribute("names", "Sriram");
4722 p.setAttribute("phones", "1");
4723 p.setAttribute("phones", "2");
4724 p.setAttribute("salaries", "big");
4725 String expecting = "Ter@1: big, Tom@2: n/a, Sriram@n/a: n/a";
4726 assertEquals(expecting, p.toString());
4727 }
4728
4729 public void testAnonTemplateOnLeftOfApply() throws Exception {
4730 StringTemplate e = new StringTemplate(
4731 "${foo}:{($it$)}$"
4732 );
4733 String expecting = "(foo)";
4734 assertEquals(expecting, e.toString());
4735 }
4736
4737 public void testOverrideThroughConditional() throws Exception {
4738 String templates =
4739 "group base;" +newline+
4740 "body(ick) ::= \"<if(ick)>ick<f()><else><f()><endif>\"" +
4741 "f() ::= \"foo\""+newline
4742 ;
4743 StringTemplateGroup group =
4744 new StringTemplateGroup(new StringReader(templates));
4745 String templates2 =
4746 "group sub;" +newline+
4747 "f() ::= \"bar\""+newline
4748 ;
4749 StringTemplateGroup subgroup =
4750 new StringTemplateGroup(new StringReader(templates2),
4751 AngleBracketTemplateLexer.class,
4752 null,
4753 group);
4754
4755 StringTemplate b = subgroup.getInstanceOf("body");
4756 String expecting ="bar";
4757 String result = b.toString();
4758 assertEquals(expecting, result);
4759 }
4760
4761 public static class NonPublicProperty {
4762
4763 }
4764
4765 public void testNonPublicPropertyAccess() throws Exception {
4766 StringTemplate st =
4767 new StringTemplate("$x.foo$:$x.bar$");
4768 Object o = new Object() {
4769 public int foo = 9;
4770 public int getBar() { return 34; }
4771 };
4772
4773 st.setAttribute("x", o);
4774 String expecting = "9:34";
4775 assertEquals(expecting, st.toString());
4776 }
4777
4778 public void testIndexVar() throws Exception {
4779 StringTemplateGroup group =
4780 new StringTemplateGroup("dummy", ".");
4781 StringTemplate t =
4782 new StringTemplate(
4783 group,
4784 "$A:{$i$. $it$}; separator=\"\\n\"$"
4785 );
4786 t.setAttribute("A", "parrt");
4787 t.setAttribute("A", "tombu");
4788 String expecting =
4789 "1. parrt" +newline+
4790 "2. tombu";
4791 assertEquals(expecting, t.toString());
4792 }
4793
4794 public void testIndex0Var() throws Exception {
4795 StringTemplateGroup group =
4796 new StringTemplateGroup("dummy", ".");
4797 StringTemplate t =
4798 new StringTemplate(
4799 group,
4800 "$A:{$i0$. $it$}; separator=\"\\n\"$"
4801 );
4802 t.setAttribute("A", "parrt");
4803 t.setAttribute("A", "tombu");
4804 String expecting =
4805 "0. parrt" +newline+
4806 "1. tombu";
4807 assertEquals(expecting, t.toString());
4808 }
4809
4810 public void testIndexVarWithMultipleExprs() throws Exception {
4811 StringTemplateGroup group =
4812 new StringTemplateGroup("dummy", ".");
4813 StringTemplate t =
4814 new StringTemplate(
4815 group,
4816 "$A,B:{a,b|$i$. $a$@$b$}; separator=\"\\n\"$"
4817 );
4818 t.setAttribute("A", "parrt");
4819 t.setAttribute("A", "tombu");
4820 t.setAttribute("B", "x5707");
4821 t.setAttribute("B", "x5000");
4822 String expecting =
4823 "1. parrt@x5707" +newline+
4824 "2. tombu@x5000";
4825 assertEquals(expecting, t.toString());
4826 }
4827
4828 public void testIndex0VarWithMultipleExprs() throws Exception {
4829 StringTemplateGroup group =
4830 new StringTemplateGroup("dummy", ".");
4831 StringTemplate t =
4832 new StringTemplate(
4833 group,
4834 "$A,B:{a,b|$i0$. $a$@$b$}; separator=\"\\n\"$"
4835 );
4836 t.setAttribute("A", "parrt");
4837 t.setAttribute("A", "tombu");
4838 t.setAttribute("B", "x5707");
4839 t.setAttribute("B", "x5000");
4840 String expecting =
4841 "0. parrt@x5707" +newline+
4842 "1. tombu@x5000";
4843 assertEquals(expecting, t.toString());
4844 }
4845
4846 public void testArgumentContext() throws Exception {
4847 // t is referenced within foo and so will be evaluated in that
4848 // context. it can therefore see name.
4849 StringTemplateGroup group =
4850 new StringTemplateGroup("test");
4851 StringTemplate main = group.defineTemplate("main", "$foo(t={Hi, $name$}, name=\"parrt\")$");
4852 /*StringTemplate foo =*/ group.defineTemplate("foo", "$t$");
4853 String expecting="Hi, parrt";
4854 assertEquals(expecting, main.toString());
4855 }
4856
4857 public void testNoDotsInAttributeNames() throws Exception {
4858 StringTemplateGroup group = new StringTemplateGroup("dummy", ".");
4859 StringTemplate t = new StringTemplate(group, "$user.Name$");
4860 String error=null;
4861 try {
4862 t.setAttribute("user.Name", "Kunle");
4863 }
4864 catch (IllegalArgumentException e) {
4865 error = e.getMessage();
4866 }
4867 String expecting = "cannot have '.' in attribute names";
4868 assertEquals(expecting,error);
4869 }
4870
4871 public void testNoDotsInTemplateNames() throws Exception {
4872 StringTemplateErrorListener errors = new ErrorBuffer();
4873 String templates =
4874 "group test;" +newline+
4875 "a.b() ::= <<foo>>"+newline;
4876
4877 /*StringTemplateGroup group =*/
4878 new StringTemplateGroup(new StringReader(templates),
4879 DefaultTemplateLexer.class,
4880 errors);
4881 String expecting = "template group parse error: line 2:1: unexpected token:";
4882 assertTrue(errors.toString().startsWith(expecting));
4883 }
4884
4885 public void testLineWrap() throws Exception {
4886 String templates =
4887 "group test;" +newline+
4888 "array(values) ::= <<int[] a = { <values; wrap=\"\\n\", separator=\",\"> };>>"+newline;
4889 StringTemplateGroup group =
4890 new StringTemplateGroup(new StringReader(templates));
4891
4892 StringTemplate a = group.getInstanceOf("array");
4893 a.setAttribute("values",
4894 new int[] {3,9,20,2,1,4,6,32,5,6,77,888,2,1,6,32,5,6,77,
4895 4,9,20,2,1,4,63,9,20,2,1,4,6,32,5,6,77,6,32,5,6,77,
4896 3,9,20,2,1,4,6,32,5,6,77,888,1,6,32,5});
4897 String expecting =
4898 "int[] a = { 3,9,20,2,1,4,6,32,5,6,77,888,\n" +
4899 "2,1,6,32,5,6,77,4,9,20,2,1,4,63,9,20,2,1,\n" +
4900 "4,6,32,5,6,77,6,32,5,6,77,3,9,20,2,1,4,6,\n" +
4901 "32,5,6,77,888,1,6,32,5 };";
4902 assertEquals(expecting,a.toString(40));
4903 }
4904
4905 public void testLineWrapWithNormalizedNewlines() throws Exception {
4906 String templates =
4907 "group test;" +newline+
4908 "array(values) ::= <<int[] a = { <values; wrap=\"\\r\\n\", separator=\",\"> };>>"+newline;
4909 StringTemplateGroup group =
4910 new StringTemplateGroup(new StringReader(templates));
4911
4912 StringTemplate a = group.getInstanceOf("array");
4913 a.setAttribute("values",
4914 new int[] {3,9,20,2,1,4,6,32,5,6,77,888,2,1,6,32,5,6,77,
4915 4,9,20,2,1,4,63,9,20,2,1,4,6,32,5,6,77,6,32,5,6,77,
4916 3,9,20,2,1,4,6,32,5,6,77,888,1,6,32,5});
4917 String expecting =
4918 "int[] a = { 3,9,20,2,1,4,6,32,5,6,77,888,\n" + // wrap is \r\n, normalize to \n
4919 "2,1,6,32,5,6,77,4,9,20,2,1,4,63,9,20,2,1,\n" +
4920 "4,6,32,5,6,77,6,32,5,6,77,3,9,20,2,1,4,6,\n" +
4921 "32,5,6,77,888,1,6,32,5 };";
4922
4923 StringWriter sw = new StringWriter();
4924 StringTemplateWriter stw = new AutoIndentWriter(sw,"\n"); // force \n as newline
4925 stw.setLineWidth(40);
4926 a.write(stw);
4927 String result = sw.toString();
4928 assertEquals(expecting, result);
4929 }
4930
4931 public void testLineWrapAnchored() throws Exception {
4932 String templates =
4933 "group test;" +newline+
4934 "array(values) ::= <<int[] a = { <values; anchor, wrap=\"\\n\", separator=\",\"> };>>"+newline;
4935 StringTemplateGroup group =
4936 new StringTemplateGroup(new StringReader(templates));
4937
4938 StringTemplate a = group.getInstanceOf("array");
4939 a.setAttribute("values",
4940 new int[] {3,9,20,2,1,4,6,32,5,6,77,888,2,1,6,32,5,6,77,
4941 4,9,20,2,1,4,63,9,20,2,1,4,6,32,5,6,77,6,32,5,6,77,
4942 3,9,20,2,1,4,6,32,5,6,77,888,1,6,32,5});
4943 String expecting =
4944 "int[] a = { 3,9,20,2,1,4,6,32,5,6,77,888,\n" +
4945 " 2,1,6,32,5,6,77,4,9,20,2,1,4,\n" +
4946 " 63,9,20,2,1,4,6,32,5,6,77,6,\n" +
4947 " 32,5,6,77,3,9,20,2,1,4,6,32,\n" +
4948 " 5,6,77,888,1,6,32,5 };";
4949 assertEquals(expecting, a.toString(40));
4950 }
4951
4952 public void testSubtemplatesAnchorToo() throws Exception {
4953 String templates =
4954 "group test;" +newline+
4955 "array(values) ::= <<{ <values; anchor, separator=\", \"> }>>"+newline;
4956 StringTemplateGroup group =
4957 new StringTemplateGroup(new StringReader(templates));
4958
4959 final StringTemplate x = new StringTemplate(group, "<\\n>{ <stuff; anchor, separator=\",\\n\"> }<\\n>");
4960 x.setAttribute("stuff", "1");
4961 x.setAttribute("stuff", "2");
4962 x.setAttribute("stuff", "3");
4963 StringTemplate a = group.getInstanceOf("array");
4964 a.setAttribute("values", new ArrayList() {{
4965 add("a"); add(x); add("b");
4966 }});
4967 String expecting =
4968 "{ a, \n" +
4969 " { 1,\n" +
4970 " 2,\n" +
4971 " 3 }\n" +
4972 " , b }";
4973 assertEquals(expecting, a.toString(40));
4974 }
4975
4976 public void testFortranLineWrap() throws Exception {
4977 String templates =
4978 "group test;" +newline+
4979 "func(args) ::= << FUNCTION line( <args; wrap=\"\\n c\", separator=\",\"> )>>"+newline;
4980 StringTemplateGroup group =
4981 new StringTemplateGroup(new StringReader(templates));
4982
4983 StringTemplate a = group.getInstanceOf("func");
4984 a.setAttribute("args",
4985 new String[] {"a","b","c","d","e","f"});
4986 String expecting =
4987 " FUNCTION line( a,b,c,d,\n" +
4988 " ce,f )";
4989 assertEquals(expecting, a.toString(30));
4990 }
4991
4992 public void testLineWrapWithDiffAnchor() throws Exception {
4993 String templates =
4994 "group test;" +newline+
4995 "array(values) ::= <<int[] a = { <{1,9,2,<values; wrap, separator=\",\">}; anchor> };>>"+newline;
4996 StringTemplateGroup group =
4997 new StringTemplateGroup(new StringReader(templates));
4998
4999 StringTemplate a = group.getInstanceOf("array");
5000 a.setAttribute("values",
5001 new int[] {3,9,20,2,1,4,6,32,5,6,77,888,2,1,6,32,5,6,77,
5002 4,9,20,2,1,4,63,9,20,2,1,4,6});
5003 String expecting =
5004 "int[] a = { 1,9,2,3,9,20,2,1,4,\n" +
5005 " 6,32,5,6,77,888,2,\n" +
5006 " 1,6,32,5,6,77,4,9,\n" +
5007 " 20,2,1,4,63,9,20,2,\n" +
5008 " 1,4,6 };";
5009 assertEquals(expecting, a.toString(30));
5010 }
5011
5012 public void testLineWrapEdgeCase() throws Exception {
5013 String templates =
5014 "group test;" +newline+
5015 "duh(chars) ::= <<<chars; wrap=\"\\n\"\\>>>"+newline;
5016 StringTemplateGroup group =
5017 new StringTemplateGroup(new StringReader(templates));
5018
5019 StringTemplate a = group.getInstanceOf("duh");
5020 a.setAttribute("chars", new String[] {"a","b","c","d","e"});
5021 // lineWidth==3 implies that we can have 3 characters at most
5022 String expecting =
5023 "abc\n"+
5024 "de";
5025 assertEquals(expecting, a.toString(3));
5026 }
5027
5028 public void testLineWrapLastCharIsNewline() throws Exception {
5029 String templates =
5030 "group test;" +newline+
5031 "duh(chars) ::= <<<chars; wrap=\"\\n\"\\>>>"+newline;
5032 StringTemplateGroup group =
5033 new StringTemplateGroup(new StringReader(templates));
5034
5035 StringTemplate a = group.getInstanceOf("duh");
5036 a.setAttribute("chars", new String[] {"a","b","\n","d","e"});
5037 // don't do \n if it's last element anyway
5038 String expecting =
5039 "ab\n"+
5040 "de";
5041 assertEquals(expecting,a.toString(3));
5042 }
5043
5044 public void testLineWrapCharAfterWrapIsNewline() throws Exception {
5045 String templates =
5046 "group test;" +newline+
5047 "duh(chars) ::= <<<chars; wrap=\"\\n\"\\>>>"+newline;
5048 StringTemplateGroup group =
5049 new StringTemplateGroup(new StringReader(templates));
5050
5051 StringTemplate a = group.getInstanceOf("duh");
5052 a.setAttribute("chars", new String[] {"a","b","c","\n","d","e"});
5053 // Once we wrap, we must dump chars as we see them. A newline right
5054 // after a wrap is just an "unfortunate" event. People will expect
5055 // a newline if it's in the data.
5056 String expecting =
5057 "abc\n" +
5058 "\n" +
5059 "de";
5060 assertEquals(expecting, a.toString(3));
5061 }
5062
5063 public void testLineWrapForAnonTemplate() throws Exception {
5064 String templates =
5065 "group test;" +newline+
5066 "duh(data) ::= <<!<data:{v|[<v>]}; wrap>!>>"+newline;
5067 StringTemplateGroup group =
5068 new StringTemplateGroup(new StringReader(templates));
5069
5070 StringTemplate a = group.getInstanceOf("duh");
5071 a.setAttribute("data", new int[] {1,2,3,4,5,6,7,8,9});
5072 String expecting =
5073 "![1][2][3]\n" + // width=9 is the 3 char; don't break til after ]
5074 "[4][5][6]\n" +
5075 "[7][8][9]!";
5076 assertEquals(expecting,a.toString(9));
5077 }
5078
5079 public void testLineWrapForAnonTemplateAnchored() throws Exception {
5080 String templates =
5081 "group test;" +newline+
5082 "duh(data) ::= <<!<data:{v|[<v>]}; anchor, wrap>!>>"+newline;
5083 StringTemplateGroup group =
5084 new StringTemplateGroup(new StringReader(templates));
5085
5086 StringTemplate a = group.getInstanceOf("duh");
5087 a.setAttribute("data", new int[] {1,2,3,4,5,6,7,8,9});
5088 String expecting =
5089 "![1][2][3]\n" +
5090 " [4][5][6]\n" +
5091 " [7][8][9]!";
5092 assertEquals(expecting, a.toString(9));
5093 }
5094
5095 public void testLineWrapForAnonTemplateComplicatedWrap() throws Exception {
5096 String templates =
5097 "group test;" +newline+
5098 "top(s) ::= << <s>.>>"+
5099 "str(data) ::= <<!<data:{v|[<v>]}; wrap=\"!+\\n!\">!>>"+newline;
5100 StringTemplateGroup group =
5101 new StringTemplateGroup(new StringReader(templates));
5102
5103 StringTemplate t = group.getInstanceOf("top");
5104 StringTemplate s = group.getInstanceOf("str");
5105 s.setAttribute("data", new int[] {1,2,3,4,5,6,7,8,9});
5106 t.setAttribute("s", s);
5107 String expecting =
5108 " ![1][2]!+\n" +
5109 " ![3][4]!+\n" +
5110 " ![5][6]!+\n" +
5111 " ![7][8]!+\n" +
5112 " ![9]!.";
5113 assertEquals(expecting,t.toString(9));
5114 }
5115
5116 public void testIndentBeyondLineWidth() throws Exception {
5117 String templates =
5118 "group test;" +newline+
5119 "duh(chars) ::= << <chars; wrap=\"\\n\"\\>>>"+newline;
5120 StringTemplateGroup group =
5121 new StringTemplateGroup(new StringReader(templates));
5122
5123 StringTemplate a = group.getInstanceOf("duh");
5124 a.setAttribute("chars", new String[] {"a","b","c","d","e"});
5125 //
5126 String expecting =
5127 " a\n" +
5128 " b\n" +
5129 " c\n" +
5130 " d\n" +
5131 " e";
5132 assertEquals(expecting, a.toString(2));
5133 }
5134
5135 public void testIndentedExpr() throws Exception {
5136 String templates =
5137 "group test;" +newline+
5138 "duh(chars) ::= << <chars; wrap=\"\\n\"\\>>>"+newline;
5139 StringTemplateGroup group =
5140 new StringTemplateGroup(new StringReader(templates));
5141
5142 StringTemplate a = group.getInstanceOf("duh");
5143 a.setAttribute("chars", new String[] {"a","b","c","d","e"});
5144 //
5145 String expecting =
5146 " ab\n" +
5147 " cd\n" +
5148 " e";
5149 // width=4 spaces + 2 char.
5150 assertEquals(expecting, a.toString(6));
5151 }
5152
5153 public void testNestedIndentedExpr() throws Exception {
5154 String templates =
5155 "group test;" +newline+
5156 "top(d) ::= << <d>!>>"+newline+
5157 "duh(chars) ::= << <chars; wrap=\"\\n\"\\>>>"+newline;
5158 StringTemplateGroup group =
5159 new StringTemplateGroup(new StringReader(templates));
5160
5161 StringTemplate top = group.getInstanceOf("top");
5162 StringTemplate duh = group.getInstanceOf("duh");
5163 duh.setAttribute("chars", new String[] {"a","b","c","d","e"});
5164 top.setAttribute("d", duh);
5165 String expecting =
5166 " ab\n" +
5167 " cd\n" +
5168 " e!";
5169 // width=4 spaces + 2 char.
5170 assertEquals(expecting, top.toString(6));
5171 }
5172
5173 public void testNestedWithIndentAndTrackStartOfExpr() throws Exception {
5174 String templates =
5175 "group test;" +newline+
5176 "top(d) ::= << <d>!>>"+newline+
5177 "duh(chars) ::= <<x: <chars; anchor, wrap=\"\\n\"\\>>>"+newline;
5178 StringTemplateGroup group =
5179 new StringTemplateGroup(new StringReader(templates));
5180
5181 StringTemplate top = group.getInstanceOf("top");
5182 StringTemplate duh = group.getInstanceOf("duh");
5183 duh.setAttribute("chars", new String[] {"a","b","c","d","e"});
5184 top.setAttribute("d", duh);
5185 //
5186 String expecting =
5187 " x: ab\n" +
5188 " cd\n" +
5189 " e!";
5190 assertEquals(expecting, top.toString(7));
5191 }
5192
5193 public void testLineDoesNotWrapDueToLiteral() throws Exception {
5194 String templates =
5195 "group test;" +newline+
5196 "m(args,body) ::= <<public void foo(<args; wrap=\"\\n\",separator=\", \">) throws Ick { <body> }>>"+newline;
5197 StringTemplateGroup group =
5198 new StringTemplateGroup(new StringReader(templates));
5199
5200 StringTemplate a = group.getInstanceOf("m");
5201 a.setAttribute("args",
5202 new String[] {"a", "b", "c"});
5203 a.setAttribute("body", "i=3;");
5204 // make it wrap because of ") throws Ick { " literal
5205 int n = "public void foo(a, b, c".length();
5206 String expecting =
5207 "public void foo(a, b, c) throws Ick { i=3; }";
5208 assertEquals(expecting, a.toString(n));
5209 }
5210
5211 public void testSingleValueWrap() throws Exception {
5212 String templates =
5213 "group test;" +newline+
5214 "m(args,body) ::= <<{ <body; anchor, wrap=\"\\n\"> }>>"+newline;
5215 StringTemplateGroup group =
5216 new StringTemplateGroup(new StringReader(templates));
5217
5218 StringTemplate m = group.getInstanceOf("m");
5219 m.setAttribute("body", "i=3;");
5220 // make it wrap because of ") throws Ick { " literal
5221 String expecting =
5222 "{ \n"+
5223 " i=3; }";
5224 assertEquals(expecting, m.toString(2));
5225 }
5226
5227 public void testLineWrapInNestedExpr() throws Exception {
5228 String templates =
5229 "group test;" +newline+
5230 "top(arrays) ::= <<Arrays: <arrays>done>>"+newline+
5231 "array(values) ::= <<int[] a = { <values; anchor, wrap=\"\\n\", separator=\",\"> };<\\n\\>>>"+newline;
5232 StringTemplateGroup group =
5233 new StringTemplateGroup(new StringReader(templates));
5234
5235 StringTemplate top = group.getInstanceOf("top");
5236 StringTemplate a = group.getInstanceOf("array");
5237 a.setAttribute("values",
5238 new int[] {3,9,20,2,1,4,6,32,5,6,77,888,2,1,6,32,5,6,77,
5239 4,9,20,2,1,4,63,9,20,2,1,4,6,32,5,6,77,6,32,5,6,77,
5240 3,9,20,2,1,4,6,32,5,6,77,888,1,6,32,5});
5241 top.setAttribute("arrays", a);
5242 top.setAttribute("arrays", a); // add twice
5243 String expecting =
5244 "Arrays: int[] a = { 3,9,20,2,1,4,6,32,5,\n" +
5245 " 6,77,888,2,1,6,32,5,\n" +
5246 " 6,77,4,9,20,2,1,4,63,\n" +
5247 " 9,20,2,1,4,6,32,5,6,\n" +
5248 " 77,6,32,5,6,77,3,9,20,\n" +
5249 " 2,1,4,6,32,5,6,77,888,\n" +
5250 " 1,6,32,5 };\n" +
5251 "int[] a = { 3,9,20,2,1,4,6,32,5,6,77,888,\n" +
5252 " 2,1,6,32,5,6,77,4,9,20,2,1,4,\n" +
5253 " 63,9,20,2,1,4,6,32,5,6,77,6,\n" +
5254 " 32,5,6,77,3,9,20,2,1,4,6,32,\n" +
5255 " 5,6,77,888,1,6,32,5 };\n" +
5256 "done";
5257 assertEquals(expecting, top.toString(40));
5258 }
5259
5260 public void testBackslash() throws Exception {
5261 StringTemplateGroup group =
5262 new StringTemplateGroup("test");
5263 StringTemplate t = group.defineTemplate("t", "\\");
5264 String expecting="\\";
5265 assertEquals(expecting, t.toString());
5266 }
5267
5268 public void testBackslash2() throws Exception {
5269 StringTemplateGroup group =
5270 new StringTemplateGroup("test");
5271 StringTemplate t = group.defineTemplate("t", "\\ ");
5272 String expecting="\\ ";
5273 assertEquals(expecting, t.toString());
5274 }
5275
5276 public void testEscapeEscape() throws Exception {
5277 StringTemplateGroup group =
5278 new StringTemplateGroup("test");
5279 StringTemplate t = group.defineTemplate("t", "\\\\$v$");
5280 t.setAttribute("v", "Joe");
5281 //System.out.println(t);
5282 String expecting="\\Joe";
5283 assertEquals(expecting, t.toString());
5284 }
5285
5286 public void testEscapeEscapeNestedAngle() throws Exception {
5287 StringTemplateGroup group =
5288 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5289 StringTemplate t = group.defineTemplate("t", "<v:{a|\\\\<a>}>");
5290 t.setAttribute("v", "Joe");
5291 //System.out.println(t);
5292 String expecting="\\Joe";
5293 assertEquals(expecting, t.toString());
5294 }
5295
5296 public void testListOfIntArrays() throws Exception {
5297 StringTemplateGroup group =
5298 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5299 StringTemplate t =
5300 group.defineTemplate("t", "<data:array()>");
5301 group.defineTemplate("array", "[<it:element(); separator=\",\">]");
5302 group.defineTemplate("element", "<it>");
5303 List data = new ArrayList();
5304 data.add(new int[] {1,2,3});
5305 data.add(new int[] {10,20,30});
5306 t.setAttribute("data", data);
5307 //System.out.println(t);
5308 String expecting="[1,2,3][10,20,30]";
5309 assertEquals(expecting, t.toString());
5310 }
5311
5312 // Test null option
5313
5314 public void testNullOptionSingleNullValue() throws Exception {
5315 StringTemplateGroup group =
5316 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5317 StringTemplate t =
5318 group.defineTemplate("t", "<data; null=\"0\">");
5319 //System.out.println(t);
5320 String expecting="0";
5321 assertEquals(expecting, t.toString());
5322 }
5323
5324 public void testNullOptionHasEmptyNullValue() throws Exception {
5325 StringTemplateGroup group =
5326 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5327 StringTemplate t =
5328 group.defineTemplate("t", "<data; null=\"\", separator=\", \">");
5329 List data = new ArrayList();
5330 data.add(null);
5331 data.add(new Integer(1));
5332 t.setAttribute("data", data);
5333 String expecting=", 1";
5334 assertEquals(expecting, t.toString());
5335 }
5336
5337 public void testNullOptionSingleNullValueInList() throws Exception {
5338 StringTemplateGroup group =
5339 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5340 StringTemplate t =
5341 group.defineTemplate("t", "<data; null=\"0\">");
5342 List data = new ArrayList();
5343 data.add(null);
5344 t.setAttribute("data", data);
5345 //System.out.println(t);
5346 String expecting="0";
5347 assertEquals(expecting, t.toString());
5348 }
5349
5350 public void testNullValueInList() throws Exception {
5351 StringTemplateGroup group =
5352 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5353 StringTemplate t =
5354 group.defineTemplate("t", "<data; null=\"-1\", separator=\", \">");
5355 List data = new ArrayList();
5356 data.add(null);
5357 data.add(new Integer(1));
5358 data.add(null);
5359 data.add(new Integer(3));
5360 data.add(new Integer(4));
5361 data.add(null);
5362 t.setAttribute("data", data);
5363 //System.out.println(t);
5364 String expecting="-1, 1, -1, 3, 4, -1";
5365 assertEquals(expecting, t.toString());
5366 }
5367
5368 public void testNullValueInListNoNullOption() throws Exception {
5369 StringTemplateGroup group =
5370 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5371 StringTemplate t =
5372 group.defineTemplate("t", "<data; separator=\", \">");
5373 List data = new ArrayList();
5374 data.add(null);
5375 data.add(new Integer(1));
5376 data.add(null);
5377 data.add(new Integer(3));
5378 data.add(new Integer(4));
5379 data.add(null);
5380 t.setAttribute("data", data);
5381 //System.out.println(t);
5382 String expecting="1, 3, 4";
5383 assertEquals(expecting, t.toString());
5384 }
5385
5386 public void testNullValueInListWithTemplateApply() throws Exception {
5387 StringTemplateGroup group =
5388 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5389 StringTemplate t =
5390 group.defineTemplate("t", "<data:array(); null=\"-1\", separator=\", \">");
5391 group.defineTemplate("array", "<it>");
5392 List data = new ArrayList();
5393 data.add(new Integer(0));
5394 data.add(null);
5395 data.add(new Integer(2));
5396 data.add(null);
5397 t.setAttribute("data", data);
5398 String expecting="0, -1, 2, -1";
5399 assertEquals(expecting, t.toString());
5400 }
5401
5402 public void testNullValueInListWithTemplateApplyNullFirstValue() throws Exception {
5403 StringTemplateGroup group =
5404 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5405 StringTemplate t =
5406 group.defineTemplate("t", "<data:array(); null=\"-1\", separator=\", \">");
5407 group.defineTemplate("array", "<it>");
5408 List data = new ArrayList();
5409 data.add(null);
5410 data.add(new Integer(0));
5411 data.add(null);
5412 data.add(new Integer(2));
5413 t.setAttribute("data", data);
5414 String expecting="-1, 0, -1, 2";
5415 assertEquals(expecting, t.toString());
5416 }
5417
5418 public void testNullSingleValueInListWithTemplateApply() throws Exception {
5419 StringTemplateGroup group =
5420 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5421 StringTemplate t =
5422 group.defineTemplate("t", "<data:array(); null=\"-1\", separator=\", \">");
5423 group.defineTemplate("array", "<it>");
5424 List data = new ArrayList();
5425 data.add(null);
5426 t.setAttribute("data", data);
5427 String expecting="-1";
5428 assertEquals(expecting, t.toString());
5429 }
5430
5431 public void testNullSingleValueWithTemplateApply() throws Exception {
5432 StringTemplateGroup group =
5433 new StringTemplateGroup("test", AngleBracketTemplateLexer.class);
5434 StringTemplate t =
5435 group.defineTemplate("t", "<data:array(); null=\"-1\", separator=\", \">");
5436 group.defineTemplate("array", "<it>");
5437 String expecting="-1";
5438 assertEquals(expecting, t.toString());
5439 }
5440
5441 public void testLengthOp() throws Exception {
5442 StringTemplate e = new StringTemplate(
5443 "$length(names)$"
5444 );
5445 e = e.getInstanceOf();
5446 e.setAttribute("names", "Ter");
5447 e.setAttribute("names", "Tom");
5448 e.setAttribute("names", "Sriram");
5449 String expecting = "3";
5450 assertEquals(expecting, e.toString());
5451 }
5452
5453 public void testLengthOpWithMap() throws Exception {
5454 StringTemplate e = new StringTemplate(
5455 "$length(names)$"
5456 );
5457 e = e.getInstanceOf();
5458 Map m = new HashMap();
5459 m.put("Tom", "foo");
5460 m.put("Sriram", "foo");
5461 m.put("Doug", "foo");
5462 e.setAttribute("names", m);
5463 String expecting = "3";
5464 assertEquals(expecting, e.toString());
5465 }
5466
5467 public void testLengthOpWithSet() throws Exception {
5468 StringTemplate e = new StringTemplate(
5469 "$length(names)$"
5470 );
5471 e = e.getInstanceOf();
5472 Set m = new HashSet();
5473 m.add("Tom");
5474 m.add("Sriram");
5475 m.add("Doug");
5476 e.setAttribute("names", m);
5477 String expecting = "3";
5478 assertEquals(expecting, e.toString());
5479 }
5480
5481 public void testLengthOpNull() throws Exception {
5482 StringTemplate e = new StringTemplate(
5483 "$length(names)$"
5484 );
5485 e = e.getInstanceOf();
5486 e.setAttribute("names", null);
5487 String expecting = "0";
5488 assertEquals(expecting, e.toString());
5489 }
5490
5491 public void testLengthOpSingleValue() throws Exception {
5492 StringTemplate e = new StringTemplate(
5493 "$length(names)$"
5494 );
5495 e = e.getInstanceOf();
5496 e.setAttribute("names", "Ter");
5497 String expecting = "1";
5498 assertEquals(expecting, e.toString());
5499 }
5500
5501 public void testLengthOpPrimitive() throws Exception {
5502 StringTemplate e = new StringTemplate(
5503 "$length(ints)$"
5504 );
5505 e = e.getInstanceOf();
5506 e.setAttribute("ints", new int[] {1,2,3,4} );
5507 String expecting = "4";
5508 assertEquals(expecting, e.toString());
5509 }
5510
5511 public void testLengthOpOfListWithNulls() throws Exception {
5512 StringTemplate e = new StringTemplate(
5513 "$length(data)$"
5514 );
5515 e = e.getInstanceOf();
5516 List data = new ArrayList();
5517 data.add("Hi");
5518 data.add(null);
5519 data.add("mom");
5520 data.add(null);
5521 e.setAttribute("data", data);
5522 String expecting = "4"; // nulls are counted
5523 assertEquals(expecting, e.toString());
5524 }
5525
5526 public void testStripOpOfListWithNulls() throws Exception {
5527 StringTemplate e = new StringTemplate(
5528 "$strip(data)$"
5529 );
5530 e = e.getInstanceOf();
5531 List data = new ArrayList();
5532 data.add("Hi");
5533 data.add(null);
5534 data.add("mom");
5535 data.add(null);
5536 e.setAttribute("data", data);
5537 String expecting = "Himom"; // nulls are skipped
5538 assertEquals(expecting, e.toString());
5539 }
5540
5541 public void testStripOpOfListOfListsWithNulls() throws Exception {
5542 StringTemplate e = new StringTemplate(
5543 "$strip(data):{list | $strip(list)$}; separator=\",\"$"
5544 );
5545 e = e.getInstanceOf();
5546 List data = new ArrayList();
5547 List dataOne = new ArrayList();
5548 dataOne.add("Hi");
5549 dataOne.add("mom");
5550 data.add(dataOne);
5551 data.add(null);
5552 List dataTwo = new ArrayList();
5553 dataTwo.add("Hi");
5554 dataTwo.add(null);
5555 dataTwo.add("dad");
5556 dataTwo.add(null);
5557 data.add(dataTwo);
5558 e.setAttribute("data", data);
5559 String expecting = "Himom,Hidad"; // nulls are skipped
5560 assertEquals(expecting, e.toString());
5561 }
5562
5563 public void testStripOpOfSingleAlt() throws Exception {
5564 StringTemplate e = new StringTemplate(
5565 "$strip(data)$"
5566 );
5567 e = e.getInstanceOf();
5568 e.setAttribute("data", "hi");
5569 String expecting = "hi"; // nulls are skipped
5570 assertEquals(expecting, e.toString());
5571 }
5572
5573 public void testStripOpOfNull() throws Exception {
5574 StringTemplate e = new StringTemplate(
5575 "$strip(data)$"
5576 );
5577 e = e.getInstanceOf();
5578 String expecting = ""; // nulls are skipped
5579 assertEquals(expecting, e.toString());
5580 }
5581
5582 public void testReUseOfStripResult() throws Exception {
5583 String templates =
5584 "group test;" +newline+
5585 "a(names) ::= \"<b(strip(names))>\""+newline+
5586 "b(x) ::= \"<x>, <x>\""+newline
5587 ;
5588 StringTemplateGroup group =
5589 new StringTemplateGroup(new StringReader(templates));
5590 StringTemplate e = group.getInstanceOf("a");
5591 List names = new ArrayList();
5592 names.add("Ter");
5593 names.add(null);
5594 names.add("Tom");
5595 e.setAttribute("names", names);
5596 String expecting = "TerTom, TerTom";
5597 assertEquals(expecting, e.toString());
5598 }
5599
5600 public void testLengthOpOfStrippedListWithNulls() throws Exception {
5601 StringTemplate e = new StringTemplate(
5602 "$length(strip(data))$"
5603 );
5604 e = e.getInstanceOf();
5605 List data = new ArrayList();
5606 data.add("Hi");
5607 data.add(null);
5608 data.add("mom");
5609 data.add(null);
5610 e.setAttribute("data", data);
5611 String expecting = "2"; // nulls are counted
5612 assertEquals(expecting, e.toString());
5613 }
5614
5615 public void testLengthOpOfStrippedListWithNullsFrontAndBack() throws Exception {
5616 StringTemplate e = new StringTemplate(
5617 "$length(strip(data))$"
5618 );
5619 e = e.getInstanceOf();
5620 List data = new ArrayList();
5621 data.add(null);
5622 data.add(null);
5623 data.add(null);
5624 data.add("Hi");
5625 data.add(null);
5626 data.add(null);
5627 data.add(null);
5628 data.add("mom");
5629 data.add(null);
5630 data.add(null);
5631 data.add(null);
5632 e.setAttribute("data", data);
5633 String expecting = "2"; // nulls are counted
5634 assertEquals(expecting, e.toString());
5635 }
5636
5637 public void testMapKeys() throws Exception {
5638 StringTemplateGroup group =
5639 new StringTemplateGroup("dummy", ".", AngleBracketTemplateLexer.class);
5640 StringTemplate t =
5641 new StringTemplate(group,
5642 "<aMap.keys:{k|<k>:<aMap.(k)>}; separator=\", \">");
5643 HashMap map = new LinkedHashMap();
5644 map.put("int","0");
5645 map.put("float","0.0");
5646 t.setAttribute("aMap", map);
5647 assertEquals("int:0, float:0.0",t.toString());
5648 }
5649
5650 public void testMapValues() throws Exception {
5651 StringTemplateGroup group =
5652 new StringTemplateGroup("dummy", ".", AngleBracketTemplateLexer.class);
5653 StringTemplate t =
5654 new StringTemplate(group,
5655 "<aMap.values; separator=\", \"> <aMap.(\"i\"+\"nt\")>");
5656 HashMap map = new LinkedHashMap();
5657 map.put("int","0");
5658 map.put("float","0.0");
5659 t.setAttribute("aMap", map);
5660 assertEquals("0, 0.0 0", t.toString());
5661 }
5662
5663 public void testMapKeysWithIntegerType() throws Exception {
5664 // must get back an Integer from keys not a toString()'d version
5665 StringTemplateGroup group =
5666 new StringTemplateGroup("dummy", ".", AngleBracketTemplateLexer.class);
5667 StringTemplate t =
5668 new StringTemplate(group,
5669 "<aMap.keys:{k|<k>:<aMap.(k)>}; separator=\", \">");
5670 Map map = new HashMap();
5671 map.put(new Integer(1),new ArrayList(){{add("ick"); add("foo");}});
5672 map.put(new Integer(2),new ArrayList(){{add("x"); add("y");}});
5673 t.setAttribute("aMap", map);
5674
5675 String res = t.toString();
5676 boolean passed = false;
5677 if (res.equals("2:xy, 1:ickfoo") || res.equals("1:ickfoo, 2:xy")) {
5678 passed = true;
5679 }
5680
5681 assertTrue("Map traversal did not return expected strings", passed);
5682
5683 }
5684
5685 /** Use when super.attr name is implemented
5686 public void testArgumentContext2() throws Exception {
5687 // t is referenced within foo and so will be evaluated in that
5688 // context. it can therefore see name.
5689 StringTemplateGroup group =
5690 new StringTemplateGroup("test");
5691 StringTemplate main = group.defineTemplate("main", "$foo(t={Hi, $super.name$}, name=\"parrt\")$");
5692 main.setAttribute("name", "tombu");
5693 StringTemplate foo = group.defineTemplate("foo", "$t$");
5694 String expecting="Hi, parrt";
5695 assertEquals(expecting, main.toString());
5696 }
5697 */
5698
5699 /**
5700 * Check what happens when a semicolon is appended to a single line template
5701 * Should fail with a parse error(?) and not a missing template error.
5702 * FIXME: This should generate a warning or error about that semi colon.
5703 * <p>
5704 * Bug ref: JIRA bug ST-2
5705 */
5706 /*
5707 public void testGroupTrailingSemiColon() throws Exception {
5708 //try {
5709 String templates =
5710 "group test;" +newline+
5711 "t1()::=\"R1\"; "+newline+
5712 "t2() ::= \"R2\""+newline
5713 ;
5714 StringTemplateGroup group =
5715 new StringTemplateGroup(new StringReader(templates));
5716
5717 StringTemplate st = group.getInstanceOf("t1");
5718 assertEquals("R1", st.toString());
5719
5720 st = group.getInstanceOf("t2");
5721 assertEquals("R2", st.toString());
5722
5723 fail("A parse error should have been generated");
5724 //} catch (ParseError??) {
5725 //}
5726 }
5727 */
5728 public void testSuperReferenceInIfClause() throws Exception {
5729 String superGroupString =
5730 "group super;" + newline +
5731 "a(x) ::= \"super.a\"" + newline +
5732 "b(x) ::= \"<c()>super.b\"" + newline +
5733 "c() ::= \"super.c\""
5734 ;
5735 StringTemplateGroup superGroup = new StringTemplateGroup(
5736 new StringReader(superGroupString), AngleBracketTemplateLexer.class);
5737 String subGroupString =
5738 "group sub;\n" +
5739 "a(x) ::= \"<if(x)><super.a()><endif>\"" + newline +
5740 "b(x) ::= \"<if(x)><else><super.b()><endif>\"" + newline +
5741 "c() ::= \"sub.c\""
5742 ;
5743 StringTemplateGroup subGroup = new StringTemplateGroup(
5744 new StringReader(subGroupString), AngleBracketTemplateLexer.class);
5745 subGroup.setSuperGroup(superGroup);
5746 StringTemplate a = subGroup.getInstanceOf("a");
5747 a.setAttribute("x", "foo");
5748 assertEquals("super.a", a.toString());
5749 StringTemplate b = subGroup.getInstanceOf("b");
5750 assertEquals("sub.csuper.b", b.toString());
5751 StringTemplate c = subGroup.getInstanceOf("c");
5752 assertEquals("sub.c", c.toString());
5753 }
5754
5755 /** Added feature for ST-21 */
5756 public void testListLiteralWithEmptyElements() throws Exception {
5757 StringTemplate e = new StringTemplate(
5758 "$[\"Ter\",,\"Jesse\"]:{n | $i$:$n$}; separator=\", \", null=\"\"$"
5759 );
5760 e = e.getInstanceOf();
5761 e.setAttribute("names", "Ter");
5762 e.setAttribute("phones", "1");
5763 e.setAttribute("salaries", "big");
5764 String expecting = "1:Ter, 2:, 3:Jesse";
5765 assertEquals(expecting, e.toString());
5766 }
5767
5768 public void testTemplateApplicationAsOptionValue() throws Exception {
5769 StringTemplate st =new StringTemplate(
5770 "Tokens : <rules; separator=names:{<it>}> ;",
5771 AngleBracketTemplateLexer.class);
5772 st.setAttribute("rules", "A");
5773 st.setAttribute("rules", "B");
5774 st.setAttribute("names", "Ter");
5775 st.setAttribute("names", "Tom");
5776 String expecting = "Tokens : ATerTomB ;";
5777 assertEquals(expecting, st.toString());
5778 }
5779
5780 public static void writeFile(String dir, String fileName, String content) {
5781 try {
5782 File f = new File(dir, fileName);
5783 FileWriter w = new FileWriter(f);
5784 BufferedWriter bw = new BufferedWriter(w);
5785 bw.write(content);
5786 bw.close();
5787 w.close();
5788 }
5789 catch (IOException ioe) {
5790 System.err.println("can't write file");
5791 ioe.printStackTrace(System.err);
5792 }
5793 }
5794
5795 }
0 // start of a body
1 <statements; separator="\n">
2 // end of a body
0 <visibility> <returnType> <name>(<args>) {
1 <org/antlr/stringtemplate/test/body()>
2 }
0 $it.firstName$ $it.email$
1
0 $users:org/antlr/stringtemplate/test/row()$