📄 parser.jj
字号:
*/SimpleNode process() : {/*@bgen(jjtree) process */ ASTprocess jjtn000 = new ASTprocess(this, JJTPROCESS); boolean jjtc000 = true; jjtree.openNodeScope(jjtn000);/*@egen*/}{/*@bgen(jjtree) process */ try {/*@egen*/ ( Statement() )* <EOF>/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn000, true); jjtc000 = false; }/*@egen*/ { return jjtn000; }/*@bgen(jjtree)*/ } catch (Throwable jjte000) { if (jjtc000) { jjtree.clearNodeScope(jjtn000); jjtc000 = false; } else { jjtree.popNode(); } if (jjte000 instanceof RuntimeException) { throw (RuntimeException)jjte000; } if (jjte000 instanceof ParseException) { throw (ParseException)jjte000; } throw (Error)jjte000; } finally { if (jjtc000) { jjtree.closeNodeScope(jjtn000, true); } }/*@egen*/}/** * These are the types of statements that * are acceptable in Velocity templates. */void Statement() : {}{ IfStatement()| StopStatement()| LOOKAHEAD(2) Reference()| Comment()| SetDirective()| EscapedDirective()| Escape()| Directive()| Text()}/** * used to separate the notion of a valid directive that has been * escaped, versus something that looks like a directive and * is just schmoo. This is important to do as a separate production * that creates a node, because we want this, in either case, to stop * the further parsing of the Directive() tree. */void EscapedDirective() : {/*@bgen(jjtree) EscapedDirective */ ASTEscapedDirective jjtn000 = new ASTEscapedDirective(this, JJTESCAPEDDIRECTIVE); boolean jjtc000 = true; jjtree.openNodeScope(jjtn000);/*@egen*/}{/*@bgen(jjtree) EscapedDirective */ try {/*@egen*/ { Token t = null; } t = <ESCAPE_DIRECTIVE>/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn000, true); jjtc000 = false; }/*@egen*/ { /* * churn and burn.. */ t.image = escapedDirective( t.image ); }/*@bgen(jjtree)*/ } finally { if (jjtc000) { jjtree.closeNodeScope(jjtn000, true); } }/*@egen*/}/** * Used to catch and process escape sequences in grammatical constructs * as escapes outside of VTL are just characters. Right now we have both * this and the EscapeDirective() construction because in the EscapeDirective() * case, we want to suck in the #<directive> and here we don't. We just want * the escapes to render correctly */void Escape() : {/*@bgen(jjtree) Escape */ ASTEscape jjtn000 = new ASTEscape(this, JJTESCAPE); boolean jjtc000 = true; jjtree.openNodeScope(jjtn000);/*@egen*/}{/*@bgen(jjtree) Escape */ try {/*@egen*/ { Token t = null; int count = 0; boolean control = false; } ( LOOKAHEAD(2) t = <DOUBLE_ESCAPE> { count++; } )+/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn000, true); jjtc000 = false; }/*@egen*/ { /* * first, check to see if we have a control directive */ switch(t.next.kind ) { case IF_DIRECTIVE : case ELSE_DIRECTIVE : case ELSEIF_DIRECTIVE : case END : case STOP_DIRECTIVE : control = true; break; } /* * if that failed, lets lookahead to see if we matched a PD or a VM */ if ( isDirective( t.next.image.substring(1))) control = true; else if ( rsvc.isVelocimacro( t.next.image.substring(1), currentTemplateName)) control = true; jjtn000.val = ""; for( int i = 0; i < count; i++) jjtn000.val += ( control ? "\\" : "\\\\"); }/*@bgen(jjtree)*/ } finally { if (jjtc000) { jjtree.closeNodeScope(jjtn000, true); } }/*@egen*/}void Comment() : {/*@bgen(jjtree) Comment */ ASTComment jjtn000 = new ASTComment(this, JJTCOMMENT); boolean jjtc000 = true; jjtree.openNodeScope(jjtn000);/*@egen*/}{/*@bgen(jjtree) Comment */ try {/*@egen*/ <SINGLE_LINE_COMMENT>| <MULTI_LINE_COMMENT>| <FORMAL_COMMENT>/*@bgen(jjtree)*/ } finally { if (jjtc000) { jjtree.closeNodeScope(jjtn000, true); } }/*@egen*/}void NumberLiteral() : {/*@bgen(jjtree) NumberLiteral */ ASTNumberLiteral jjtn000 = new ASTNumberLiteral(this, JJTNUMBERLITERAL); boolean jjtc000 = true; jjtree.openNodeScope(jjtn000);/*@egen*/}{/*@bgen(jjtree) NumberLiteral */ try {/*@egen*/ <NUMBER_LITERAL>/*@bgen(jjtree)*/ } finally { if (jjtc000) { jjtree.closeNodeScope(jjtn000, true); } }/*@egen*/}void StringLiteral() : {/*@bgen(jjtree) StringLiteral */ ASTStringLiteral jjtn000 = new ASTStringLiteral(this, JJTSTRINGLITERAL); boolean jjtc000 = true; jjtree.openNodeScope(jjtn000);/*@egen*/}{/*@bgen(jjtree) StringLiteral */ try {/*@egen*/ <STRING_LITERAL>/*@bgen(jjtree)*/ } finally { if (jjtc000) { jjtree.closeNodeScope(jjtn000, true); } }/*@egen*/}/** * This method corresponds to variable * references in Velocity templates. * The following are examples of variable * references that may be found in a * template: * * $foo * $bar * */void Identifier() : {/*@bgen(jjtree) Identifier */ ASTIdentifier jjtn000 = new ASTIdentifier(this, JJTIDENTIFIER); boolean jjtc000 = true; jjtree.openNodeScope(jjtn000);/*@egen*/}{/*@bgen(jjtree) Identifier */ try {/*@egen*/ <IDENTIFIER>/*@bgen(jjtree)*/ } finally { if (jjtc000) { jjtree.closeNodeScope(jjtn000, true); } }/*@egen*/}void Word() : {/*@bgen(jjtree) Word */ ASTWord jjtn000 = new ASTWord(this, JJTWORD); boolean jjtc000 = true; jjtree.openNodeScope(jjtn000);/*@egen*/}{/*@bgen(jjtree) Word */ try {/*@egen*/ <WORD>/*@bgen(jjtree)*/ } finally { if (jjtc000) { jjtree.closeNodeScope(jjtn000, true); } }/*@egen*/}/** * Supports the arguments for the Pluggable Directives * We add whitespace in here as a token so the VMs can * easily reconstruct a macro body from the token stream * See Directive() */int DirectiveArg() : {}{ Reference() { return ParserTreeConstants.JJTREFERENCE; }| Word() { return ParserTreeConstants.JJTWORD; }| StringLiteral() { return ParserTreeConstants.JJTSTRINGLITERAL; }| NumberLiteral()| LOOKAHEAD( <LBRACKET> [<WHITESPACE>] ( Reference() | NumberLiteral()) [<WHITESPACE>] <DOUBLEDOT> ) IntegerRange() { return ParserTreeConstants.JJTINTEGERRANGE; }| ObjectArray() { return ParserTreeConstants.JJTOBJECTARRAY; }| True() { return ParserTreeConstants.JJTTRUE; }| False() { return ParserTreeConstants.JJTFALSE; }}/** * Supports the Pluggable Directives * #foo( arg+ ) */SimpleNode Directive() :{/*@bgen(jjtree) Directive */ ASTDirective jjtn000 = new ASTDirective(this, JJTDIRECTIVE); boolean jjtc000 = true; jjtree.openNodeScope(jjtn000);/*@egen*/ Token t = null; int argType; int argPos = 0; Directive d; int directiveType; boolean isVM = false; boolean doItNow = false;}{/*@bgen(jjtree) Directive */ try {/*@egen*/ /* * note that if we were escaped, that is now handled by * EscapedDirective() */ t = <WORD> { String directiveName = t.image.substring(1); d = (Directive) directives.get(directiveName); /* * Velocimacro support : if the directive is macro directive * then set the flag so after the block parsing, we add the VM * right then. (So available if used w/in the current template ) */ if (directiveName.equals("macro")) { doItNow = true; } /* * set the directive name from here. No reason for the thing to know * about parser tokens */ jjtn000.setDirectiveName(directiveName); if ( d == null) { /* * if null, then not a real directive, but maybe a Velocimacro */ isVM = rsvc.isVelocimacro(directiveName, currentTemplateName); if (!isVM) { token_source.stateStackPop(); token_source.inDirective = false; return jjtn000; } /* * Currently, all VMs are LINE directives */ directiveType = Directive.LINE; } else { directiveType = d.getType(); } /* * now, switch us out of PRE_DIRECTIVE */ token_source.SwitchTo(DIRECTIVE); argPos = 0; } /* * if this is indeed a token, match the #foo ( arg ) pattern */ [<WHITESPACE>] <LPAREN> ( LOOKAHEAD(2) [<WHITESPACE>] argType = DirectiveArg() { if (argType == ParserTreeConstants.JJTWORD) { if (doItNow && argPos == 0) { /* if a VM and it's the 0th arg... ok */ ; } else if( t.image.equals("#foreach") && argPos == 1) { /* if a foreach and it's the 2nd arg ok */ ; } else { throw new MacroParseException("Invalid arg #" + argPos + " in " + (isVM ? "VM " : "directive " ) + t.image + " at line " + t.beginLine + ", column " + t.beginColumn + " in template " + currentTemplateName); } } else { if (doItNow && argPos == 0) { /* if a VM and it's the 0th arg, not ok */ throw new MacroParseException("Invalid first arg " + " in #macro() directive - must be a" + " word token (no \' or \" surrounding)" + " at line " + t.beginLine + ", column " + t.beginColumn + " in template " + currentTemplateName); } } argPos++; } )* [<WHITESPACE>] <RPAREN> { if (directiveType == Directive.LINE) { return jjtn000; } }/*@bgen(jjtree) Block */ { ASTBlock jjtn001 = new ASTBlock(this, JJTBLOCK); boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); } try {/*@egen*/ /* * and the following block if the PD needs it */ ( Statement() )+/*@bgen(jjtree)*/ } catch (Throwable jjte001) { if (jjtc001) { jjtree.clearNodeScope(jjtn001); jjtc001 = false; } else { jjtree.popNode(); } if (jjte001 instanceof RuntimeException) { throw (RuntimeException)jjte001; } if (jjte001 instanceof ParseException) { throw (ParseException)jjte001; } throw (Error)jjte001; } finally { if (jjtc001) { jjtree.closeNodeScope(jjtn001, true); } }/*@egen*/ <END>/*@bgen(jjtree)*/ { jjtree.closeNodeScope(jjtn000, true); jjtc000 = false; }/*@egen*/ { /* * VM : if we are processing a #macro directive, we need to * process the block. In truth, I can just register the name
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -