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

📄 parser.jjt

📁 velocity 的脚本语言的全部代码集合
💻 JJT
📖 第 1 页 / 共 3 页
字号:
/* * Copyright 2001-2002,2004 The Apache Software Foundation. *  * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *  *      http://www.apache.org/licenses/LICENSE-2.0 *  * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* *  NOTE : please see documentation at bottom of this file. (It was placed there its tiring *    to always have to page past it... :) */options{    /** The default package for this parser kit */    NODE_PACKAGE="org.apache.velocity.runtime.parser";    /** A source file will be generated for each non-terminal */    MULTI=true;    /**     * Each node will have access to the parser, I did this so     * some global information can be shared via the parser. I     * think this will come in handly keeping track of     * context, and being able to push changes back into     * the context when nodes make modifications to the     * context by setting properties, variables and     * what not.     */    NODE_USES_PARSER=true;    /**     * The parser must be non-static in order for the     * above option to work, otherwise the parser value     * is passed in as null, which isn't all the useful ;)     */    STATIC=false;    /**     * Enables the use of a visitor that each of nodes     * will accept. This way we can separate the logic     * of node processing in a visitor and out of the     * nodes themselves. If processing changes then     * the nothing has to change in the node code.     */    VISITOR=true;    /**     * Declare that we are accepting unicode input and     * that we are using a custom character stream class     * Note that the char stream class is really a slightly     * modified ASCII_CharStream, as it appears we are safe     * because we only deal with pre-encoding-converted     * Readers rather than raw input streams.     */    UNICODE_INPUT=true;    USER_CHAR_STREAM=true;    /**     *  for debugging purposes.  Keep false     */    DEBUG_PARSER=false;    DEBUG_TOKEN_MANAGER=false;}PARSER_BEGIN(Parser)package org.apache.velocity.runtime.parser;import java.io.*;import java.util.*;import org.apache.velocity.runtime.RuntimeServices;import org.apache.velocity.runtime.parser.node.*;import org.apache.velocity.runtime.directive.Directive;import org.apache.velocity.runtime.directive.Macro;import org.apache.velocity.runtime.directive.MacroParseException;import org.apache.velocity.util.StringUtils;/** * This class is responsible for parsing a Velocity * template. This class was generated by JavaCC using * the JJTree extension to produce an Abstract * Syntax Tree (AST) of the template. * * Please look at the Parser.jjt file which is * what controls the generation of this class. * * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a> * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a> * @version $Id: Parser.jjt,v 1.75.4.1 2004/03/03 23:22:58 geirm Exp $*/public class Parser{    /**     *  This Hashtable contains a list of all of the dynamic directives.     */    private Hashtable directives = new Hashtable(0);    /**     *  Name of current template we are parsing.  Passed to us in parse()     */    String currentTemplateName = "";    VelocityCharStream velcharstream = null;    private RuntimeServices rsvc = null;    /**     * This constructor was added to allow the re-use of parsers.     * The normal constructor takes a single argument which     * an InputStream. This simply creates a re-usable parser     * object, we satisfy the requirement of an InputStream     * by using a newline character as an input stream.     */    public Parser( RuntimeServices rs)    {        /*         * need to call the CTOR first thing.         */        this(   new VelocityCharStream(                new ByteArrayInputStream("\n".getBytes()), 1, 1 ));        /*         * now setup a VCS for later use         */        velcharstream = new VelocityCharStream(                new ByteArrayInputStream("\n".getBytes()), 1, 1 );        /*         *  and save the RuntimeServices         */        rsvc = rs;    }    /**     * This was also added to allow parsers to be     * re-usable. Normal JavaCC use entails passing an     * input stream to the constructor and the parsing     * process is carried out once. We want to be able     * to re-use parsers: we do this by adding this     * method and re-initializing the lexer with     * the new stream that we want parsed.     */    public SimpleNode parse( Reader reader, String templateName )        throws ParseException    {        SimpleNode sn = null;        currentTemplateName = templateName;        try        {            token_source.clearStateVars();            /*             *  reinitialize the VelocityCharStream             *  with the new reader             */            velcharstream.ReInit( reader, 1, 1 );            /*             * now reinit the Parser with this CharStream             */            ReInit( velcharstream  );            /*             *  do that voodoo...             */            sn = process();        }        catch (MacroParseException mee)        {            /*             *  thrown by the Macro class when something is amiss in the             *  Macro specification             */            rsvc.error ("Parser Error:  #macro() : " + templateName + " : " + StringUtils.stackTrace(mee));            throw new ParseException(mee.getMessage());        }        catch (ParseException pe)        {            rsvc.error ("Parser Exception: " + templateName + " : " + StringUtils.stackTrace(pe));            throw new ParseException (pe.currentToken,                pe.expectedTokenSequences, pe.tokenImage);        }        catch (TokenMgrError tme)        {            throw new ParseException("Lexical error: " + tme.toString());        }        catch (Exception e)        {            rsvc.error ("Parser Error: " + templateName + " : " + StringUtils.stackTrace(e));        }        currentTemplateName = "";        return sn;    }    /**     *  This method sets the directives Hashtable     */    public void setDirectives(Hashtable directives)    {        this.directives = directives;    }    /**     *  This method gets a Directive from the directives Hashtable     */    public Directive getDirective(String directive)    {        return (Directive) directives.get(directive);    }    /**     *  This method finds out of the directive exists in the directives     *  Hashtable.     */    public boolean isDirective(String directive)    {        if (directives.containsKey(directive))            return true;        else            return false;    }    /**     * Produces a processed output for an escaped control or     * pluggable directive     */    private String escapedDirective( String strImage )    {        int iLast = strImage.lastIndexOf("\\");        String strDirective = strImage.substring(iLast + 1);        boolean bRecognizedDirective = false;        /*         *  is this a PD or a control directive?         */        if ( isDirective( strDirective.substring(1)))        {           bRecognizedDirective = true;        }        else if ( rsvc.isVelocimacro( strDirective.substring(1), currentTemplateName))        {            bRecognizedDirective = true;        }        else        {            /* order for speed? */            if ( strDirective.substring(1).equals("if")                || strDirective.substring(1).equals("end")                || strDirective.substring(1).equals("set")                || strDirective.substring(1).equals("else")                || strDirective.substring(1).equals("elseif")                || strDirective.substring(1).equals("stop")            )            {                bRecognizedDirective = true;            }        }        /*         *  if so, make the proper prefix string (let the escapes do their thing..)         *  otherwise, just return what it is..         */        if (bRecognizedDirective)            return ( strImage.substring(0,iLast/2) + strDirective);        else            return ( strImage );    }}PARSER_END(Parser)TOKEN_MGR_DECLS:{    private int fileDepth = 0;    private int lparen = 0;    private int rparen = 0;    Stack stateStack = new Stack();    public boolean debugPrint = false;    private boolean inReference;    public boolean inDirective;    private boolean inComment;    public  boolean inSet;    /**     *  pushes the current state onto the 'state stack',     *  and maintains the parens counts     *  public because we need it in PD & VM handling     *     *  @return boolean : success.  It can fail if the state machine     *     gets messed up (do don't mess it up :)     */    public boolean stateStackPop()    {        Hashtable h;        try        {            h = (Hashtable) stateStack.pop();        }        catch( EmptyStackException e)        {            lparen=0;            SwitchTo(DEFAULT);            return false;        }        if( debugPrint )            System.out.println(                " stack pop (" + stateStack.size() + ") : lparen=" +                    ( (Integer) h.get("lparen")).intValue() +                        " newstate=" + ( (Integer) h.get("lexstate")).intValue() );        lparen = ( (Integer) h.get("lparen")).intValue();        rparen = ( (Integer) h.get("rparen")).intValue();        SwitchTo( ( (Integer) h.get("lexstate")).intValue() );        return true;    }    /**     *  pops a state off the stack, and restores paren counts     *     *  @return boolean : success of operation     */    public boolean stateStackPush()    {        if( debugPrint )            System.out.println(" (" + stateStack.size() + ") pushing cur state : " +                curLexState );        Hashtable h = new Hashtable();        h.put("lexstate", new Integer( curLexState ) );        h.put("lparen", new Integer( lparen ));        h.put("rparen", new Integer( rparen ));        lparen = 0;        stateStack.push( h );        return true;    }    /**     *  Clears all state variables, resets to     *  start values, clears stateStack.  Call     *  before parsing.     *  @return void     */    public void clearStateVars()    {        stateStack.clear();        lparen = 0;        rparen = 0;        inReference = false;        inDirective = false;        inComment = false;        inSet = false;        return;    }    /**     *  handles the dropdown logic when encountering a RPAREN     */    private void RPARENHandler()    {        /*         *  Ultimately, we want to drop down to the state below         *  the one that has an open (if we hit bottom (DEFAULT),         *  that's fine. It's just text schmoo.         */        boolean closed = false;        if (inComment)            closed = true;        while( !closed )        {            /*             * look at current state.  If we haven't seen a lparen             * in this state then we drop a state, because this             * lparen clearly closes our state             */            if( lparen > 0)            {                /*                 *  if rparen + 1 == lparen, then this state is closed.                 * Otherwise, increment and keep parsing                 */                 if( lparen == rparen + 1)                 {                       stateStackPop();                 }                else                {                    rparen++;                }                 closed = true;            }            else            {                /*                 * now, drop a state                 */                if(!stateStackPop())                    break;            }        }    }}/* ------------------------------------------------------------------------ * * Tokens * *  Note : we now have another state, REFMODIFIER.  This is sort of a *  type of REFERENCE state, simply use to use the DIRECTIVE token *  set when we are processing a $foo.bar() construct * * ------------------------------------------------------------------------- */<DIRECTIVE,REFMOD2>TOKEN:{    <LBRACKET: "[">|   <RBRACKET: "]">|   <COMMA:",">}<DIRECTIVE, REFMOD2>TOKEN:{  <DOUBLEDOT : ".." >}<DIRECTIVE,REFMODIFIER>TOKEN:{    <LPAREN: "(">    {        if (!inComment)            lparen++;        /*         * If in REFERENCE and we have seen the dot, then move         * to REFMOD2 -> Modifier()         */        if (curLexState == REFMODIFIER )            SwitchTo( REFMOD2 );    }}/* * we never will see a ')' in anything but DIRECTIVE and REFMOD2. * Each have their own */<DIRECTIVE>TOKEN:{    /*     *  We will eat any whitespace upto and including a newline for directives     */    <RPAREN: ")" ( ( " " | "\t" )* ( "\n" | "\r" | "\r\n" ))?>    {       RPARENHandler();    }}<REFMOD2>TOKEN:{    /*     * in REFMOD2, we don't want to bind the whitespace and \n like we     * do when closing a directive.     */    <REFMOD2_RPAREN: ")">    {        /*         * need to simply switch back to REFERENCE, not drop down the stack         * because we can (infinitely) chain, ala         * $foo.bar().blargh().woogie().doogie()         */        SwitchTo( REFERENCE );    }}/*---------------------------------------------- * *  escape "\\" handling for the built-in directives * *--------------------------------------------- */TOKEN:{    /*     *  We have to do this, because we want these to be a Text node, and     *  whatever follows to be peer to this text in the tree.     *     *  We need to touch the ASTs for these, because we want an even # of \'s     *  to render properly in front of the block     *     *  This is really simplistic.  I actually would prefer to find them in     *  grammatical context, but I am neither smart nor rested, a receipe     *  for disaster, another long night with Mr. Parser, or both.     */    <ESCAPE_DIRECTIVE :  (<DOUBLE_ESCAPE>)* "\\#" <WORD> >}/* * needed because #set is so wacky in it's desired behavior.  We want set * to eat any preceeding whitespace so it is invisible in formatting. * (As it should be.)  If this works well, I am going to chuck the whole MORE: * token abomination. */TOKEN:{  <SET_DIRECTIVE: (" "|"\t")*  "#set" (" ")* "(">    {        if (! inComment)        {            inDirective = true;            if ( debugPrint )                System.out.print("#set :  going to " + DIRECTIVE );            stateStackPush();            inSet = true;            SwitchTo(DIRECTIVE);        }        /*         *  need the LPAREN action         */

⌨️ 快捷键说明

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