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

📄 parser.java

📁 velocity 的脚本语言的全部代码集合
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/* Generated By:JJTree&JavaCC: Do not edit this line. Parser.java */
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.java,v 1.74 2002/04/27 19:33:30 geirm Exp $
*/
public class Parser/*@bgen(jjtree)*/implements ParserTreeConstants, ParserConstants {/*@bgen(jjtree)*/
  protected JJTParserState jjtree = new JJTParserState();/**
     *  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 );
    }

/**
 * This method is what starts the whole parsing
 * process. After the parsing is complete and
 * the template has been turned into an AST,
 * this method returns the root of AST which
 * can subsequently be traversed by a visitor
 * which implements the ParserVisitor interface
 * which is generated automatically by JavaCC
 */
  final public SimpleNode process() throws ParseException {
                        /*@bgen(jjtree) process */
  ASTprocess jjtn000 = new ASTprocess(this, JJTPROCESS);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
    try {
      label_1:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case LPAREN:
        case RPAREN:
        case ESCAPE_DIRECTIVE:
        case SET_DIRECTIVE:
        case DOUBLE_ESCAPE:
        case ESCAPE:
        case TEXT:
        case SINGLE_LINE_COMMENT:
        case FORMAL_COMMENT:
        case MULTI_LINE_COMMENT:
        case STRING_LITERAL:
        case IF_DIRECTIVE:
        case STOP_DIRECTIVE:
        case NUMBER_LITERAL:
        case WORD:
        case IDENTIFIER:
        case DOT:
        case LCURLY:
        case RCURLY:
          ;
          break;
        default:
          jj_la1[0] = jj_gen;
          break label_1;
        }
        Statement();
      }
      jj_consume_token(0);
     jjtree.closeNodeScope(jjtn000, true);
     jjtc000 = false;
     {if (true) return jjtn000;}
    } catch (Throwable jjte000) {
     if (jjtc000) {
       jjtree.clearNodeScope(jjtn000);
       jjtc000 = false;
     } else {
       jjtree.popNode();
     }
     if (jjte000 instanceof RuntimeException) {
       {if (true) throw (RuntimeException)jjte000;}
     }
     if (jjte000 instanceof ParseException) {
       {if (true) throw (ParseException)jjte000;}
     }
     {if (true) throw (Error)jjte000;}
    } finally {
     if (jjtc000) {
       jjtree.closeNodeScope(jjtn000, true);
     }
    }
    throw new Error("Missing return statement in function");
  }

/**
 * These are the types of statements that
 * are acceptable in Velocity templates.
 */
  final public void Statement() throws ParseException {
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case IF_DIRECTIVE:
      IfStatement();
      break;
    case STOP_DIRECTIVE:
      StopStatement();
      break;
    default:
      jj_la1[1] = jj_gen;
      if (jj_2_1(2)) {
        Reference();
      } else {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case SINGLE_LINE_COMMENT:
        case FORMAL_COMMENT:
        case MULTI_LINE_COMMENT:
          Comment();
          break;
        case SET_DIRECTIVE:
          SetDirective();
          break;
        case ESCAPE_DIRECTIVE:
          EscapedDirective();
          break;
        case DOUBLE_ESCAPE:
          Escape();
          break;
        case WORD:
          Directive();
          break;
        case LPAREN:
        case RPAREN:
        case ESCAPE:
        case TEXT:
        case STRING_LITERAL:
        case NUMBER_LITERAL:
        case DOT:
        case LCURLY:
        case RCURLY:
          Text();
          break;
        default:
          jj_la1[2] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
      }
    }
  }

/**
 *  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.
 */
  final public void EscapedDirective() throws ParseException {
                           /*@bgen(jjtree) EscapedDirective */
  ASTEscapedDirective jjtn000 = new ASTEscapedDirective(this, JJTESCAPEDDIRECTIVE);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
    try {
        Token t = null;
      t = jj_consume_token(ESCAPE_DIRECTIVE);
      jjtree.closeNodeScope(jjtn000, true);
      jjtc000 = false;
        /*
         *  churn and burn..
         */
        t.image = escapedDirective( t.image );
    } finally {
      if (jjtc000) {
        jjtree.closeNodeScope(jjtn000, true);
      }
    }
  }

/**
 *  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
 */
  final public void Escape() throws ParseException {
                 /*@bgen(jjtree) Escape */
  ASTEscape jjtn000 = new ASTEscape(this, JJTESCAPE);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
    try {
        Token t = null;
        int count = 0;
        boolean control = false;
      label_2:
      while (true) {
        t = jj_consume_token(DOUBLE_ESCAPE);
        count++;
        if (jj_2_2(2)) {
          ;
        } else {
          break label_2;
        }
      }
      jjtree.closeNodeScope(jjtn000, true);
      jjtc000 = false;
        /*
         * 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 ? "\\" : "\\\\");
    } finally {
      if (jjtc000) {
        jjtree.closeNodeScope(jjtn000, true);
      }
    }
  }

  final public void Comment() throws ParseException {
                  /*@bgen(jjtree) Comment */
  ASTComment jjtn000 = new ASTComment(this, JJTCOMMENT);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);

⌨️ 快捷键说明

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