KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > velocity > runtime > parser > Parser


1 /* Generated By:JJTree&JavaCC: Do not edit this line. Parser.java */
2 package org.apache.velocity.runtime.parser;
3
4 import java.io.*;
5 import java.util.*;
6
7 import org.apache.velocity.runtime.RuntimeServices;
8 import org.apache.velocity.runtime.parser.node.*;
9 import org.apache.velocity.runtime.directive.Directive;
10 import org.apache.velocity.runtime.directive.Macro;
11 import org.apache.velocity.runtime.directive.MacroParseException;
12 import org.apache.velocity.util.StringUtils;
13
14 /**
15  * This class is responsible for parsing a Velocity
16  * template. This class was generated by JavaCC using
17  * the JJTree extension to produce an Abstract
18  * Syntax Tree (AST) of the template.
19  *
20  * Please look at the Parser.jjt file which is
21  * what controls the generation of this class.
22  *
23  * @author <a HREF="mailto:jvanzyl@apache.org">Jason van Zyl</a>
24  * @author <a HREF="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
25  * @version $Id: Parser.java,v 1.74 2002/04/27 19:33:30 geirm Exp $
26 */

27 public class Parser/*@bgen(jjtree)*/implements ParserTreeConstants, ParserConstants {/*@bgen(jjtree)*/
28   protected JJTParserState jjtree = new JJTParserState();/**
29      * This Hashtable contains a list of all of the dynamic directives.
30      */

31     private Hashtable directives = new Hashtable(0);
32
33     /**
34      * Name of current template we are parsing. Passed to us in parse()
35      */

36     String currentTemplateName = "";
37
38     VelocityCharStream velcharstream = null;
39
40     private RuntimeServices rsvc = null;
41
42     /**
43      * This constructor was added to allow the re-use of parsers.
44      * The normal constructor takes a single argument which
45      * an InputStream. This simply creates a re-usable parser
46      * object, we satisfy the requirement of an InputStream
47      * by using a newline character as an input stream.
48      */

49     public Parser( RuntimeServices rs)
50     {
51         /*
52          * need to call the CTOR first thing.
53          */

54
55         this( new VelocityCharStream(
56                 new ByteArrayInputStream("\n".getBytes()), 1, 1 ));
57
58         /*
59          * now setup a VCS for later use
60          */

61         velcharstream = new VelocityCharStream(
62                 new ByteArrayInputStream("\n".getBytes()), 1, 1 );
63
64         /*
65          * and save the RuntimeServices
66          */

67         rsvc = rs;
68     }
69
70     /**
71      * This was also added to allow parsers to be
72      * re-usable. Normal JavaCC use entails passing an
73      * input stream to the constructor and the parsing
74      * process is carried out once. We want to be able
75      * to re-use parsers: we do this by adding this
76      * method and re-initializing the lexer with
77      * the new stream that we want parsed.
78      */

79     public SimpleNode parse( Reader reader, String templateName )
80         throws ParseException
81     {
82         SimpleNode sn = null;
83
84         currentTemplateName = templateName;
85
86         try
87         {
88             token_source.clearStateVars();
89
90             /*
91              * reinitialize the VelocityCharStream
92              * with the new reader
93              */

94             velcharstream.ReInit( reader, 1, 1 );
95
96             /*
97              * now reinit the Parser with this CharStream
98              */

99             ReInit( velcharstream );
100
101             /*
102              * do that voodoo...
103              */

104             sn = process();
105         }
106         catch (MacroParseException mee)
107         {
108             /*
109              * thrown by the Macro class when something is amiss in the
110              * Macro specification
111              */

112             rsvc.error ("Parser Error: #macro() : " + templateName + " : " + StringUtils.stackTrace(mee));
113             throw new ParseException(mee.getMessage());
114         }
115         catch (ParseException pe)
116         {
117             rsvc.error ("Parser Exception: " + templateName + " : " + StringUtils.stackTrace(pe));
118             throw new ParseException (pe.currentToken,
119                 pe.expectedTokenSequences, pe.tokenImage);
120         }
121         catch (TokenMgrError tme)
122         {
123             throw new ParseException("Lexical error: " + tme.toString());
124         }
125         catch (Exception e)
126         {
127             rsvc.error ("Parser Error: " + templateName + " : " + StringUtils.stackTrace(e));
128         }
129
130         currentTemplateName = "";
131
132         return sn;
133     }
134
135     /**
136      * This method sets the directives Hashtable
137      */

138     public void setDirectives(Hashtable directives)
139     {
140         this.directives = directives;
141     }
142
143     /**
144      * This method gets a Directive from the directives Hashtable
145      */

146     public Directive getDirective(String directive)
147     {
148         return (Directive) directives.get(directive);
149     }
150
151     /**
152      * This method finds out of the directive exists in the directives
153      * Hashtable.
154      */

155     public boolean isDirective(String directive)
156     {
157         if (directives.containsKey(directive))
158             return true;
159         else
160             return false;
161     }
162
163
164     /**
165      * Produces a processed output for an escaped control or
166      * pluggable directive
167      */

168     private String escapedDirective( String strImage )
169     {
170         int iLast = strImage.lastIndexOf("\\");
171
172         String strDirective = strImage.substring(iLast + 1);
173
174         boolean bRecognizedDirective = false;
175
176         /*
177          * is this a PD or a control directive?
178          */

179
180         if ( isDirective( strDirective.substring(1)))
181         {
182            bRecognizedDirective = true;
183         }
184         else if ( rsvc.isVelocimacro( strDirective.substring(1), currentTemplateName))
185         {
186             bRecognizedDirective = true;
187         }
188         else
189         {
190             /* order for speed? */
191
192             if ( strDirective.substring(1).equals("if")
193                 || strDirective.substring(1).equals("end")
194                 || strDirective.substring(1).equals("set")
195                 || strDirective.substring(1).equals("else")
196                 || strDirective.substring(1).equals("elseif")
197                 || strDirective.substring(1).equals("stop")
198             )
199             {
200                 bRecognizedDirective = true;
201             }
202         }
203
204         /*
205          * if so, make the proper prefix string (let the escapes do their thing..)
206          * otherwise, just return what it is..
207          */

208
209         if (bRecognizedDirective)
210             return ( strImage.substring(0,iLast/2) + strDirective);
211         else
212             return ( strImage );
213     }
214
215 /**
216  * This method is what starts the whole parsing
217  * process. After the parsing is complete and
218  * the template has been turned into an AST,
219  * this method returns the root of AST which
220  * can subsequently be traversed by a visitor
221  * which implements the ParserVisitor interface
222  * which is generated automatically by JavaCC
223  */

224   final public SimpleNode process() throws ParseException {
225                         /*@bgen(jjtree) process */
226   ASTprocess jjtn000 = new ASTprocess(this, JJTPROCESS);
227   boolean jjtc000 = true;
228   jjtree.openNodeScope(jjtn000);
229     try {
230       label_1:
231       while (true) {
232         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
233         case LPAREN:
234         case RPAREN:
235         case ESCAPE_DIRECTIVE:
236         case SET_DIRECTIVE:
237         case DOUBLE_ESCAPE:
238         case ESCAPE:
239         case TEXT:
240         case SINGLE_LINE_COMMENT:
241         case FORMAL_COMMENT:
242         case MULTI_LINE_COMMENT:
243         case STRING_LITERAL:
244         case IF_DIRECTIVE:
245         case STOP_DIRECTIVE:
246         case NUMBER_LITERAL:
247         case WORD:
248         case IDENTIFIER:
249         case DOT:
250         case LCURLY:
251         case RCURLY:
252           ;
253           break;
254         default:
255           jj_la1[0] = jj_gen;
256           break label_1;
257         }
258         Statement();
259       }
260       jj_consume_token(0);
261      jjtree.closeNodeScope(jjtn000, true);
262      jjtc000 = false;
263      {if (true) return jjtn000;}
264     } catch (Throwable jjte000) {
265      if (jjtc000) {
266        jjtree.clearNodeScope(jjtn000);
267        jjtc000 = false;
268      } else {
269        jjtree.popNode();
270      }
271      if (jjte000 instanceof RuntimeException) {
272        {if (true) throw (RuntimeException)jjte000;}
273      }
274      if (jjte000 instanceof ParseException) {
275        {if (true) throw (ParseException)jjte000;}
276      }
277      {if (true) throw (Error)jjte000;}
278     } finally {
279      if (jjtc000) {
280        jjtree.closeNodeScope(jjtn000, true);
281      }
282     }
283     throw new Error("Missing return statement in function");
284   }
285
286 /**
287  * These are the types of statements that
288  * are acceptable in Velocity templates.
289  */

290   final public void Statement() throws ParseException {
291     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
292     case IF_DIRECTIVE:
293       IfStatement();
294       break;
295     case STOP_DIRECTIVE:
296       StopStatement();
297       break;
298     default:
299       jj_la1[1] = jj_gen;
300       if (jj_2_1(2)) {
301         Reference();
302       } else {
303         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
304         case SINGLE_LINE_COMMENT:
305         case FORMAL_COMMENT:
306         case MULTI_LINE_COMMENT:
307           Comment();
308           break;
309         case SET_DIRECTIVE:
310           SetDirective();
311           break;
312         case ESCAPE_DIRECTIVE:
313           EscapedDirective();
314           break;
315         case DOUBLE_ESCAPE:
316           Escape();
317           break;
318         case WORD:
319           Directive();
320           break;
321         case LPAREN:
322         case RPAREN:
323         case ESCAPE:
324         case TEXT:
325         case STRING_LITERAL:
326         case NUMBER_LITERAL:
327         case DOT:
328         case LCURLY:
329         case RCURLY:
330           Text();
331           break;
332         default:
333           jj_la1[2] = jj_gen;
334           jj_consume_token(-1);
335           throw new ParseException();
336         }
337       }
338     }
339   }
340
341 /**
342  * used to separate the notion of a valid directive that has been
343  * escaped, versus something that looks like a directive and
344  * is just schmoo. This is important to do as a separate production
345  * that creates a node, because we want this, in either case, to stop
346  * the further parsing of the Directive() tree.
347  */

348   final public void EscapedDirective() throws ParseException {
349                            /*@bgen(jjtree) EscapedDirective */
350   ASTEscapedDirective jjtn000 = new ASTEscapedDirective(this, JJTESCAPEDDIRECTIVE);
351   boolean jjtc000 = true;
352   jjtree.openNodeScope(jjtn000);
353     try {
354         Token t = null;
355       t = jj_consume_token(ESCAPE_DIRECTIVE);
356       jjtree.closeNodeScope(jjtn000, true);
357       jjtc000 = false;
358         /*
359          * churn and burn..
360          */

361         t.image = escapedDirective( t.image );
362     } finally {
363       if (jjtc000) {
364         jjtree.closeNodeScope(jjtn000, true);
365       }
366     }
367   }
368
369 /**
370  * Used to catch and process escape sequences in grammatical constructs
371  * as escapes outside of VTL are just characters. Right now we have both
372  * this and the EscapeDirective() construction because in the EscapeDirective()
373  * case, we want to suck in the #<directive> and here we don't. We just want
374  * the escapes to render correctly
375  */

376   final public void Escape() throws ParseException {
377                  /*@bgen(jjtree) Escape */
378   ASTEscape jjtn000 = new ASTEscape(this, JJTESCAPE);
379   boolean jjtc000 = true;
380   jjtree.openNodeScope(jjtn000);
381     try {
382         Token t = null;
383         int count = 0;
384         boolean control = false;
385       label_2:
386       while (true) {
387         t = jj_consume_token(DOUBLE_ESCAPE);
388         count++;
389         if (jj_2_2(2)) {
390           ;
391         } else {
392           break label_2;
393         }
394       }
395       jjtree.closeNodeScope(jjtn000, true);
396       jjtc000 = false;
397         /*
398          * first, check to see if we have a control directive
399          */

400         switch(t.next.kind ) {
401             case IF_DIRECTIVE :
402             case ELSE_DIRECTIVE :
403             case ELSEIF_DIRECTIVE :
404             case END :
405             case STOP_DIRECTIVE :
406                 control = true;
407                 break;
408         }
409
410         /*
411          * if that failed, lets lookahead to see if we matched a PD or a VM
412          */

413
414         if ( isDirective( t.next.image.substring(1)))
415             control = true;
416         else if ( rsvc.isVelocimacro( t.next.image.substring(1), currentTemplateName))
417             control = true;
418
419         jjtn000.val = "";
420
421         for( int i = 0; i < count; i++)
422             jjtn000.val += ( control ? "\\" : "\\\\");
423     } finally {
424       if (jjtc000) {
425         jjtree.closeNodeScope(jjtn000, true);
426       }
427     }
428   }
429
430   final public void Comment() throws ParseException {
431                   /*@bgen(jjtree) Comment */
432   ASTComment jjtn000 = new ASTComment(this, JJTCOMMENT);
433   boolean jjtc000 = true;
434   jjtree.openNodeScope(jjtn000);
435     try {
436       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
437       case SINGLE_LINE_COMMENT:
438         jj_consume_token(SINGLE_LINE_COMMENT);
439         break;
440       case MULTI_LINE_COMMENT:
441         jj_consume_token(MULTI_LINE_COMMENT);
442         break;
443       case FORMAL_COMMENT:
444         jj_consume_token(FORMAL_COMMENT);
445         break;
446       default:
447         jj_la1[3] = jj_gen;
448         jj_consume_token(-1);
449         throw new ParseException();
450       }
451     } finally {
452       if (jjtc000) {
453         jjtree.closeNodeScope(jjtn000, true);
454       }
455     }
456   }
457
458   final public void NumberLiteral() throws ParseException {
459                         /*@bgen(jjtree) NumberLiteral */
460   ASTNumberLiteral jjtn000 = new ASTNumberLiteral(this, JJTNUMBERLITERAL);
461   boolean jjtc000 = true;
462   jjtree.openNodeScope(jjtn000);
463     try {
464       jj_consume_token(NUMBER_LITERAL);
465     } finally {
466       if (jjtc000) {
467         jjtree.closeNodeScope(jjtn000, true);
468       }
469     }
470   }
471
472   final public void StringLiteral() throws ParseException {
473                         /*@bgen(jjtree) StringLiteral */
474   ASTStringLiteral jjtn000 = new ASTStringLiteral(this, JJTSTRINGLITERAL);
475   boolean jjtc000 = true;
476   jjtree.openNodeScope(jjtn000);
477     try {
478       jj_consume_token(STRING_LITERAL);
479     } finally {
480       if (jjtc000) {
481         jjtree.closeNodeScope(jjtn000, true);
482       }
483     }
484   }
485
486 /**
487  * This method corresponds to variable
488  * references in Velocity templates.
489  * The following are examples of variable
490  * references that may be found in a
491  * template:
492  *
493  * $foo
494  * $bar
495  *
496  */

497   final public void Identifier() throws ParseException {
498                      /*@bgen(jjtree) Identifier */
499   ASTIdentifier jjtn000 = new ASTIdentifier(this, JJTIDENTIFIER);
500   boolean jjtc000 = true;
501   jjtree.openNodeScope(jjtn000);
502     try {
503       jj_consume_token(IDENTIFIER);
504     } finally {
505       if (jjtc000) {
506         jjtree.closeNodeScope(jjtn000, true);
507       }
508     }
509   }
510
511   final public void Word() throws ParseException {
512                /*@bgen(jjtree) Word */
513   ASTWord jjtn000 = new ASTWord(this, JJTWORD);
514   boolean jjtc000 = true;
515   jjtree.openNodeScope(jjtn000);
516     try {
517       jj_consume_token(WORD);
518     } finally {
519       if (jjtc000) {
520         jjtree.closeNodeScope(jjtn000, true);
521       }
522     }
523   }
524
525 /**
526  * Supports the arguments for the Pluggable Directives
527  * We add whitespace in here as a token so the VMs can
528  * easily reconstruct a macro body from the token stream
529  * See Directive()
530  */

531   final public int DirectiveArg() throws ParseException {
532     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
533     case IDENTIFIER:
534     case LCURLY:
535       Reference();
536         {if (true) return ParserTreeConstants.JJTREFERENCE;}
537       break;
538     case WORD:
539       Word();
540         {if (true) return ParserTreeConstants.JJTWORD;}
541       break;
542     case STRING_LITERAL:
543       StringLiteral();
544         {if (true) return ParserTreeConstants.JJTSTRINGLITERAL;}
545       break;
546     case NUMBER_LITERAL:
547       NumberLiteral();
548         {if (true) return ParserTreeConstants.JJTNUMBERLITERAL;}
549       break;
550     default:
551       jj_la1[4] = jj_gen;
552       if (jj_2_3(2147483647)) {
553         IntegerRange();
554         {if (true) return ParserTreeConstants.JJTINTEGERRANGE;}
555       } else {
556         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
557         case LBRACKET:
558           ObjectArray();
559         {if (true) return ParserTreeConstants.JJTOBJECTARRAY;}
560           break;
561         case TRUE:
562           True();
563         {if (true) return ParserTreeConstants.JJTTRUE;}
564           break;
565         case FALSE:
566           False();
567         {if (true) return ParserTreeConstants.JJTFALSE;}
568           break;
569         default:
570           jj_la1[5] = jj_gen;
571           jj_consume_token(-1);
572           throw new ParseException();
573         }
574       }
575     }
576     throw new Error("Missing return statement in function");
577   }
578
579 /**
580  * Supports the Pluggable Directives
581  * #foo( arg+ )
582  */

583   final public SimpleNode Directive() throws ParseException {
584  /*@bgen(jjtree) Directive */
585     ASTDirective jjtn000 = new ASTDirective(this, JJTDIRECTIVE);
586     boolean jjtc000 = true;
587     jjtree.openNodeScope(jjtn000);Token t = null;
588     int argType;
589     int argPos = 0;
590     Directive d;
591     int directiveType;
592     boolean isVM = false;
593     boolean doItNow = false;
594     try {
595       /*
596            * note that if we were escaped, that is now handled by
597            * EscapedDirective()
598            */

599           t = jj_consume_token(WORD);
600         String directiveName = t.image.substring(1);
601
602         d = (Directive) directives.get(directiveName);
603
604         /*
605          * Velocimacro support : if the directive is macro directive
606          * then set the flag so after the block parsing, we add the VM
607          * right then. (So available if used w/in the current template )
608          */

609
610         if (directiveName.equals("macro"))
611         {
612              doItNow = true;
613         }
614
615         /*
616          * set the directive name from here. No reason for the thing to know
617          * about parser tokens
618          */

619
620         jjtn000.setDirectiveName(directiveName);
621
622         if ( d == null)
623         {
624             /*
625              * if null, then not a real directive, but maybe a Velocimacro
626              */

627
628             isVM = rsvc.isVelocimacro(directiveName, currentTemplateName);
629
630             if (!isVM)
631             {
632                 token_source.stateStackPop();
633                 token_source.inDirective = false;
634                 {if (true) return jjtn000;}
635             }
636
637
638             /*
639              * Currently, all VMs are LINE directives
640              */

641
642             directiveType = Directive.LINE;
643         }
644         else
645         {
646             directiveType = d.getType();
647         }
648
649         /*
650          * now, switch us out of PRE_DIRECTIVE
651          */

652
653         token_source.SwitchTo(DIRECTIVE);
654
655         argPos = 0;
656       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
657       case WHITESPACE:
658         jj_consume_token(WHITESPACE);
659         break;
660       default:
661         jj_la1[6] = jj_gen;
662         ;
663       }
664       jj_consume_token(LPAREN);
665       label_3:
666       while (true) {
667         if (jj_2_4(2)) {
668           ;
669         } else {
670           break label_3;
671         }
672         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
673         case WHITESPACE:
674           jj_consume_token(WHITESPACE);
675           break;
676         default:
677           jj_la1[7] = jj_gen;
678           ;
679         }
680         argType = DirectiveArg();
681                 if (argType == ParserTreeConstants.JJTWORD)
682                 {
683                     if (doItNow && argPos == 0)
684                     {
685                         /* if a VM and it's the 0th arg... ok */
686                         ;
687                     }
688                     else if( t.image.equals("#foreach") && argPos == 1)
689                     {
690                         /* if a foreach and it's the 2nd arg ok */
691                         ;
692                     }
693                     else
694                     {
695                         {if (true) throw new MacroParseException("Invalid arg #"
696                             + argPos + " in "
697                             + (isVM ? "VM " : "directive " )
698                             + t.image
699                             + " at line " + t.beginLine + ", column "
700                             + t.beginColumn
701                             + " in template " + currentTemplateName);}
702                     }
703                 }
704                 else
705                 {
706                     if (doItNow && argPos == 0)
707                     {
708                         /* if a VM and it's the 0th arg, not ok */
709
710                         {if (true) throw new MacroParseException("Invalid first arg "
711                             + " in #macro() directive - must be a"
712                             + " word token (no \' or \" surrounding)"
713                             + " at line " + t.beginLine + ", column "
714                             + t.beginColumn
715                             + " in template " + currentTemplateName);}
716                     }
717                 }
718
719                 argPos++;
720       }
721       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
722       case WHITESPACE:
723         jj_consume_token(WHITESPACE);
724         break;
725       default:
726         jj_la1[8] = jj_gen;
727         ;
728       }
729       jj_consume_token(RPAREN);
730         if (directiveType == Directive.LINE)
731         {
732             {if (true) return jjtn000;}
733         }
734       ASTBlock jjtn001 = new ASTBlock(this, JJTBLOCK);
735       boolean jjtc001 = true;
736       jjtree.openNodeScope(jjtn001);
737       try {
738         label_4:
739         while (true) {
740           Statement();
741           switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
742           case LPAREN:
743           case RPAREN:
744           case ESCAPE_DIRECTIVE:
745           case SET_DIRECTIVE:
746           case DOUBLE_ESCAPE:
747           case ESCAPE:
748           case TEXT:
749           case SINGLE_LINE_COMMENT:
750           case FORMAL_COMMENT:
751           case MULTI_LINE_COMMENT:
752           case STRING_LITERAL:
753           case IF_DIRECTIVE:
754           case STOP_DIRECTIVE:
755           case NUMBER_LITERAL:
756           case WORD:
757           case IDENTIFIER:
758           case DOT:
759           case LCURLY:
760           case RCURLY:
761             ;
762             break;
763           default:
764             jj_la1[9] = jj_gen;
765             break label_4;
766           }
767         }
768       } catch (Throwable jjte001) {
769       if (jjtc001) {
770         jjtree.clearNodeScope(jjtn001);
771         jjtc001 = false;
772       } else {
773         jjtree.popNode();
774       }
775       if (jjte001 instanceof RuntimeException) {
776         {if (true) throw (RuntimeException)jjte001;}
777       }
778       if (jjte001 instanceof ParseException) {
779         {if (true) throw (ParseException)jjte001;}
780       }
781       {if (true) throw (Error)jjte001;}
782       } finally {
783       if (jjtc001) {
784         jjtree.closeNodeScope(jjtn001, true);
785       }
786       }
787       jj_consume_token(END);
788       jjtree.closeNodeScope(jjtn000, true);
789       jjtc000 = false;
790         /*
791          * VM : if we are processing a #macro directive, we need to
792          * process the block. In truth, I can just register the name
793          * and do the work later when init-ing. That would work
794          * as long as things were always defined before use. This way
795          * we don't have to worry about forward references and such...
796          */

797
798         if (doItNow)
799         {
800             Macro.processAndRegister(rsvc, jjtn000, currentTemplateName);
801         }
802
803         /*
804          * VM : end
805          */

806
807         {if (true) return jjtn000;}
808     } catch (Throwable jjte000) {
809       if (jjtc000) {
810         jjtree.clearNodeScope(jjtn000);
811         jjtc000 = false;
812       } else {
813         jjtree.popNode();
814       }
815       if (jjte000 instanceof RuntimeException) {
816         {if (true) throw (RuntimeException)jjte000;}
817       }
818       if (jjte000 instanceof ParseException) {
819         {if (true) throw (ParseException)jjte000;}
820       }
821       {if (true) throw (Error)jjte000;}
822     } finally {
823       if (jjtc000) {
824         jjtree.closeNodeScope(jjtn000, true);
825       }
826     }
827     throw new Error("Missing return statement in function");
828   }
829
830   final public void ObjectArray() throws ParseException {
831                       /*@bgen(jjtree) ObjectArray */
832   ASTObjectArray jjtn000 = new ASTObjectArray(this, JJTOBJECTARRAY);
833   boolean jjtc000 = true;
834   jjtree.openNodeScope(jjtn000);
835     try {
836       jj_consume_token(LBRACKET);
837       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
838       case LBRACKET:
839       case WHITESPACE:
840       case STRING_LITERAL:
841       case TRUE:
842       case FALSE:
843       case NUMBER_LITERAL:
844       case IDENTIFIER:
845       case LCURLY:
846         Parameter();
847         label_5:
848         while (true) {
849           switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
850           case COMMA:
851             ;
852             break;
853           default:
854             jj_la1[10] = jj_gen;
855             break label_5;
856           }
857           jj_consume_token(COMMA);
858           Parameter();
859         }
860         break;
861       default:
862         jj_la1[11] = jj_gen;
863         ;
864       }
865       jj_consume_token(RBRACKET);
866     } catch (Throwable jjte000) {
867       if (jjtc000) {
868         jjtree.clearNodeScope(jjtn000);
869         jjtc000 = false;
870       } else {
871         jjtree.popNode();
872       }
873       if (jjte000 instanceof RuntimeException) {
874         {if (true) throw (RuntimeException)jjte000;}
875       }
876       if (jjte000 instanceof ParseException) {
877         {if (true) throw (ParseException)jjte000;}
878       }
879       {if (true) throw (Error)jjte000;}
880     } finally {
881       if (jjtc000) {
882         jjtree.closeNodeScope(jjtn000, true);
883       }
884     }
885   }
886
887 /**
888  * supports the [n..m] vector generator for use in
889  * the #foreach() to generate measured ranges w/o
890  * needing explicit support from the app/servlet
891  */

892   final public void IntegerRange() throws ParseException {
893                        /*@bgen(jjtree) IntegerRange */
894   ASTIntegerRange jjtn000 = new ASTIntegerRange(this, JJTINTEGERRANGE);
895   boolean jjtc000 = true;
896   jjtree.openNodeScope(jjtn000);
897     try {
898       jj_consume_token(LBRACKET);
899       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
900       case WHITESPACE:
901         jj_consume_token(WHITESPACE);
902         break;
903       default:
904         jj_la1[12] = jj_gen;
905         ;
906       }
907       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
908       case IDENTIFIER:
909       case LCURLY:
910         Reference();
911