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

📄 parser.jj

📁 velocity官方工具包 包括各种JAR包 示例 文档等
💻 JJ
📖 第 1 页 / 共 5 页
字号:
/*@bgen(jjtree) Generated By:JJTree: Do not edit this line. /Users/hgschmie/scratch/velocity/engine/src/java/org/apache/velocity/runtime/parser/Parser.jj */
/*@egen*//*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 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;

    /**
     * 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>
 * @author <a href="hps@intermeta.de">Henning P. Schmiedehausen</a>
 * @version $Id: Parser.jj 463419 2006-10-12 20:39:49Z henning $
*/
public class Parser/*@bgen(jjtree)*/implements ParserTreeConstants/*@egen*/
{/*@bgen(jjtree)*/
  protected JJTParserState jjtree = new JJTParserState();

/*@egen*/
    /**
     *  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.getLog().error("Parser Error: #macro() : " + templateName, mee);
            throw mee;
        }
        catch (ParseException pe)
        {
            rsvc.getLog().error("Parser Exception: " + templateName, pe);
            throw new TemplateParseException (pe.currentToken,
				pe.expectedTokenSequences, pe.tokenImage, currentTemplateName);
		}
        catch (TokenMgrError tme)
        {
            throw new ParseException("Lexical error: " + tme.toString());
        }
        catch (Exception e)
        {
            rsvc.getLog().error("Parser Error: " + templateName, 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)
    {
        return directives.containsKey(directive);
    }


    /**
     * 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, REFMOD2>
TOKEN:
{
  <COLON : ":" >
}

<DIRECTIVE, REFMOD2>
TOKEN :
{
    <LEFT_CURLEY : "{" >
  | <RIGHT_CURLEY : "}" >
}

<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" ))?>

⌨️ 快捷键说明

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