⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parser.jjt

📁 velocity 的脚本语言的全部代码集合
💻 JJT
📖 第 1 页 / 共 3 页
字号:
 *   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() #void : {}{    Reference()    {        return ParserTreeConstants.JJTREFERENCE;    }|   Word()    {        return ParserTreeConstants.JJTWORD;    }|   StringLiteral()    {        return ParserTreeConstants.JJTSTRINGLITERAL;    }|   NumberLiteral()    {        return ParserTreeConstants.JJTNUMBERLITERAL;    }|   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() :{    Token t = null;    int argType;    int argPos = 0;    Directive d;    int directiveType;    boolean isVM = false;    boolean doItNow = false;}{    /*     * 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         */        jjtThis.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 jjtThis;            }            /*             *  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 jjtThis;        }    }    /*     *  and the following block if the PD needs it     */    ( Statement() )+ #Block    <END>    {        /*         *  VM : if we are processing a #macro directive, we need to         *     process the block.  In truth, I can just register the name         *     and do the work later when init-ing.  That would work         *     as long as things were always defined before use.  This way         *     we don't have to worry about forward references and such...         */        if (doItNow)        {            Macro.processAndRegister(rsvc, jjtThis, currentTemplateName);        }        /*         *  VM : end         */        return jjtThis;    }}void ObjectArray() : {}{    <LBRACKET> [ Parameter() ( <COMMA> Parameter() )* ] <RBRACKET>}/** *  supports the [n..m] vector generator for use in *  the #foreach() to generate measured ranges w/o *  needing explicit support from the app/servlet */void IntegerRange() : {}{    <LBRACKET> [<WHITESPACE>]    ( Reference() | NumberLiteral())    [<WHITESPACE>] <DOUBLEDOT> [<WHITESPACE>]    (Reference() | NumberLiteral())    [<WHITESPACE>] <RBRACKET>}/** * This method has yet to be fully implemented * but will allow arbitrarily nested method * calls */void Parameter() #void: {}{    [<WHITESPACE>]    (        StringLiteral()        | LOOKAHEAD(  <LBRACKET> [<WHITESPACE>]    ( Reference() | NumberLiteral())     [<WHITESPACE>] <DOUBLEDOT> ) IntegerRange()        | ObjectArray()        | True()        | False()        | Reference()        | NumberLiteral()        )    [ <WHITESPACE>]}/** * This method has yet to be fully implemented * but will allow arbitrarily nested method * calls */void Method() : {}{   Identifier() <LPAREN> [ Parameter() ( <COMMA> Parameter() )* ] <REFMOD2_RPAREN>}void Reference() : {}{    /*     *  A reference is either ${<FOO>} or  $<FOO>     */      (         <IDENTIFIER>         (LOOKAHEAD(2) <DOT> (LOOKAHEAD(3) Method() | Identifier() ))*      )      |      (         <LCURLY>         <IDENTIFIER>         (LOOKAHEAD(2) <DOT> (LOOKAHEAD(3) Method() | Identifier() ))*         <RCURLY>      )}void True() : {}{    <TRUE>}void False() : {}{    <FALSE>}/** * This method is responsible for allowing * all non-grammar text to pass through * unscathed. */void Text() : {}{    <TEXT>|   <DOT>|   <RPAREN>|   <LPAREN>|   <NUMBER_LITERAL>|   <STRING_LITERAL>|   <ESCAPE>|   <LCURLY>|   <RCURLY>}/* ----------------------------------------------------------------------- * *  Defined Directive Syntax * * ----------------------------------------------------------------------*/void IfStatement() : {}{    <IF_DIRECTIVE> [<WHITESPACE>] <LPAREN> Expression() <RPAREN>    ( Statement() )+ #Block    [ LOOKAHEAD(1) ( ElseIfStatement() )+ ]    [ LOOKAHEAD(1) ElseStatement() ]    <END>}void ElseStatement() : {}{   <ELSE_DIRECTIVE>    ( Statement() )+ #Block}void ElseIfStatement() : {}{    <ELSEIF_DIRECTIVE> [<WHITESPACE>]    <LPAREN> Expression() <RPAREN>    ( Statement() )+ #Block}/** *  Currently support both types of set : *   #set( expr ) *   #set expr */void SetDirective() : {}{    <SET_DIRECTIVE>([<WHITESPACE>] Reference() [<WHITESPACE>] <EQUALS>  Expression() <RPAREN>    {        /*         * ensure that inSet is false.  Leads to some amusing bugs...         */        token_source.inSet = false;    }    [<NEWLINE>] )}/** * This method corresponds to the #stop * directive which just simulates and EOF * so that parsing stops. The #stop directive * is useful for end-user debugging * purposes. */void StopStatement() #void: {}{    <STOP_DIRECTIVE>}/* ----------------------------------------------------------------------- * *  Expression Syntax * * ----------------------------------------------------------------------*/void Expression() : {}{//    LOOKAHEAD( PrimaryExpression() <EQUALS>  ) Assignment()//|ConditionalOrExpression()}void Assignment() #Assignment(2) : {}{    PrimaryExpression() <EQUALS>  Expression()}void ConditionalOrExpression() #void : {}{  ConditionalAndExpression()  (  <LOGICAL_OR>  ConditionalAndExpression() #OrNode(2) )*}void ConditionalAndExpression() #void : {}{  EqualityExpression()  ( <LOGICAL_AND> EqualityExpression() #AndNode(2) )*}void EqualityExpression() #void : {}{    RelationalExpression()    (       <LOGICAL_EQUALS> RelationalExpression()     #EQNode(2)     | <LOGICAL_NOT_EQUALS> RelationalExpression() #NENode(2)    )*}void RelationalExpression() #void : {}{    AdditiveExpression()    (        <LOGICAL_LT>  AdditiveExpression() #LTNode(2)      | <LOGICAL_GT>  AdditiveExpression() #GTNode(2)      | <LOGICAL_LE>  AdditiveExpression() #LENode(2)      | <LOGICAL_GE>  AdditiveExpression() #GENode(2)    )*}void AdditiveExpression() #void : {}{    MultiplicativeExpression()    (        <PLUS>  MultiplicativeExpression() #AddNode(2)      | <MINUS> MultiplicativeExpression() #SubtractNode(2)    )*}void MultiplicativeExpression() #void : {}{    UnaryExpression()    (            <MULTIPLY>  UnaryExpression() #MulNode(2)          | <DIVIDE>  UnaryExpression() #DivNode(2)          | <MODULUS>  UnaryExpression() #ModNode(2)    )*}void UnaryExpression() #void : {}{     LOOKAHEAD(2)  [<WHITESPACE>]  <LOGICAL_NOT>  UnaryExpression() #NotNode(1)|   PrimaryExpression()}void PrimaryExpression() #void : {}{    [<WHITESPACE>]    (     StringLiteral()    | NumberLiteral()    | Reference()    | LOOKAHEAD(  <LBRACKET> [<WHITESPACE>]    ( Reference() | NumberLiteral())     [<WHITESPACE>] <DOUBLEDOT> ) IntegerRange()    | ObjectArray()    | True()    | False()    | <LPAREN>  Expression()  <RPAREN>     )    [<WHITESPACE>]}/* ======================================================================   Notes   -----    template == the input stream for this parser, contains 'VTL'    mixed in with 'schmoo'    VTL == Velocity Template Language : the references, directives, etc    shmoo == the non-VTL component of a template    reference == VTL entity that represents data within the context. ex. $foo    directive == VTL entity that denotes 'action' (#set, #foreach, #if )    defined directive (DD) == VTL directive entity that is expressed    explicitly w/in this grammar    pluggable directive (PD) == VTL directive entity that is defined outside of the    grammar.  PD's allow VTL to be easily expandable w/o parser modification.    The problem with parsing VTL is that an input stream consists generally of    little bits of VTL mixed in with 'other stuff, referred to as 'schmoo'.    Unlike other languages, like C or Java, where the parser can punt whenever    it encounters input that doesn't conform to the grammar, the VTL parser can't do    that. It must simply output the schmoo and keep going.    There are a few things that we do here :     - define a set of parser states (DEFAULT, DIRECTIVE, REFERENCE, etc)     - define for each parser state a set of tokens for each state     - define the VTL grammar, expressed (mostly) in the productions such as Text(),     SetStatement(), etc.    It is clear that this expression of the VTL grammar (the contents    of this .jjt file) is maturing and evolving as we learn more about    how to parse VTL ( and as I learn about parsing...), so in the event    this documentation is in disagreement w/ the source, the source    takes precedence. :)    Parser States    -------------    DEFAULT :  This is the base or starting state, and strangely enough, the    default state.    PRE_DIRECTIVE : State immediately following '#' before we figure out which    defined or pluggable directive (or neither) we are working with.    DIRECTIVE : This state is triggered by the a match of a DD or a PD.    REFERENCE : Triggered by '$'. Analagous to PRE_DIRECTIVE.    REFMODIFIER : Triggered by .<alpha> when in REFERENCE.    REFMOD2 : Triggered by ( when in REFMODIFIER    (cont)    Escape Sequences    ----------------    The escape processing in VTL is very simple.  The '\' character acts    only as an escape when :        1) On or more touch a VTL element.    A VTL element is either :        1) It preceeds a reference that is in the context.        2) It preceeds a defined directive (#set, #if, #end, etc) or a valid        pluggable directive, such as #foreach    In all other cases the '\' is just another piece of text.  The purpose of this    is to allow the non-VTL parts of a template (the 'schmoo') to not have to be    altered for processing by Velocity.    So if in the context $foo and $bar were defined and $woogie was not        \$foo  \$bar \$woogie    would output        $foo  $bar  \$woogie    Further, you can stack them and they affect left to right, just like convention    escape characters in other languages.        \$foo = $foo        \\$foo = \<foo>        \\\$foo = \$foo    What You Expect    ---------------    The recent versions of the parser are trying to support precise output to    support general template use. The directives do not render trailing    whitespace and newlines if followed by a newline.  They will render    preceeding whitespace. The only exception is #set, which also eats    preceeding whitespace.    So, with a template :        ------        #set $foo="foo"        #if($foo)        \$foo = $foo        #end        ------    it will render precisely :        ------        $foo = foo        ------*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -