parser.java

来自「精通tomcat书籍原代码,希望大家共同学习」· Java 代码 · 共 1,859 行 · 第 1/5 页

JAVA
1,859
字号
                text = parseScriptText(reader.getText(start, stop));
                new Node.Expression(text, start, parent);
                if (reader.matches("![CDATA[")) {
                    start = reader.mark();
                    stop = reader.skipUntil("]]>");
                    if (stop == null) {
                        err.jspError(start, "jsp.error.unterminated", "CDATA");
                    }
                    text = parseScriptText(reader.getText(start, stop));
                    new Node.Expression(text, start, parent);
                }
                else {
                    break;
                }
            }
            if (!reader.matchesETagWithoutLessThan( "jsp:expression" )) {
                err.jspError(start, "jsp.error.unterminated",
                    "<jsp:expression>");
            }
        }
    }

    /*
     * ELExpressionBody
     * (following "${" to first unquoted "}")
     * // XXX add formal production and confirm implementation against it,
     * //     once it's decided
     */
    private void parseELExpression(Node parent) throws JasperException {
        start = reader.mark();
        Mark last = null;
        boolean singleQuoted = false, doubleQuoted = false;
        int currentChar;
        do {
            // XXX could move this logic to JspReader
            last = reader.mark();               // XXX somewhat wasteful
            currentChar = reader.nextChar();
            if (currentChar == '\\' && (singleQuoted || doubleQuoted)) {
                // skip character following '\' within quotes
                reader.nextChar();
                currentChar = reader.nextChar();
            }
            if (currentChar == -1)
                err.jspError(start, "jsp.error.unterminated", "${");
            if (currentChar == '"')
                doubleQuoted = !doubleQuoted;
            if (currentChar == '\'')
                singleQuoted = !singleQuoted;
        } while (currentChar != '}' || (singleQuoted || doubleQuoted));

        new Node.ELExpression(reader.getText(start, last), start, parent);
    }

    /*
     * ScriptletBody ::= (Char* - (char* '%>')) '%>'
     */
    private void parseScriptlet(Node parent) throws JasperException {
	start = reader.mark();
	Mark stop = reader.skipUntil("%>");
	if (stop == null) {
	    err.jspError(start, "jsp.error.unterminated", "<%");
	}

	new Node.Scriptlet(parseScriptText(reader.getText(start, stop)),
			   start, parent);
    }

    /*
     * XMLScriptletBody ::=   ( S? '/>' )
     *                      | ( S? '>' (Char* - (char* '<')) CDSect?)* ETag )
     *                      | <TRANSLATION_ERROR>
     */
    private void parseXMLScriptlet(Node parent) throws JasperException {
        reader.skipSpaces();
        if( !reader.matches( "/>" ) ) {
            if( !reader.matches( ">" ) ) {
                err.jspError(start, "jsp.error.unterminated",
                    "&lt;jsp:scriptlet&gt;");
            }
            Mark stop;
            String text;
            while (true) {
                start = reader.mark();
                stop = reader.skipUntil("<");
                if (stop == null) {
                    err.jspError(start, "jsp.error.unterminated",
                        "&lt;jsp:scriptlet&gt;");
                }
                text = parseScriptText(reader.getText(start, stop));
                new Node.Scriptlet(text, start, parent);
                if (reader.matches("![CDATA[")) {
                    start = reader.mark();
                    stop = reader.skipUntil("]]>");
                    if (stop == null) {
                        err.jspError(start, "jsp.error.unterminated", "CDATA");
                    }
                    text = parseScriptText(reader.getText(start, stop));
                    new Node.Scriptlet(text, start, parent);
                }
                else {
                    break;
                }
            }

            if (!reader.matchesETagWithoutLessThan( "jsp:scriptlet" )) {
                err.jspError(start, "jsp.error.unterminated",
                    "&lt;jsp:scriptlet&gt;");
            }
        }
    }
	
    /**
     * Param ::= '<jsp:param' S Attributes S? EmptyBody S?
     */
    private void parseParam(Node parent) throws JasperException {
	if (!reader.matches("<jsp:param")) {
	    err.jspError(reader.mark(), "jsp.error.paramexpected");
	}
	Attributes attrs = parseAttributes();
	reader.skipSpaces();
        
        Node paramActionNode = new Node.ParamAction( attrs, start, parent );
        
        parseEmptyBody( paramActionNode, "jsp:param" );
        
        reader.skipSpaces();
    }

    /*
     * For Include:
     * StdActionContent ::= Attributes ParamBody
     *
     * ParamBody ::=   EmptyBody
     *               | ( '>' S? ( '<jsp:attribute' NamedAttributes )?
     *                   '<jsp:body'
     *                   (JspBodyParam | <TRANSLATION_ERROR> )
     *                   S? ETag
     *                 )
     *               | ( '>' S? Param* ETag )
     *
     * EmptyBody ::=   '/>'
     *               | ( '>' ETag )
     *               | ( '>' S? '<jsp:attribute' NamedAttributes ETag )
     *
     * JspBodyParam ::= S? '>' Param* '</jsp:body>'
     */
    private void parseInclude(Node parent) throws JasperException {
	Attributes attrs = parseAttributes();
	reader.skipSpaces();

        Node includeNode = new Node.IncludeAction( attrs, start, parent );
        
        parseOptionalBody(includeNode, "jsp:include", 
			  JAVAX_BODY_CONTENT_PARAM);
    }

    /*
     * For Forward:
     * StdActionContent ::= Attributes ParamBody
     */
    private void parseForward(Node parent) throws JasperException {
	Attributes attrs = parseAttributes();
	reader.skipSpaces();

        Node forwardNode = new Node.ForwardAction( attrs, start, parent );
        
        parseOptionalBody(forwardNode, "jsp:forward",
			  JAVAX_BODY_CONTENT_PARAM);
    }

    private void parseInvoke(Node parent) throws JasperException {
	Attributes attrs = parseAttributes();
	reader.skipSpaces();

        Node invokeNode = new Node.InvokeAction(attrs, start, parent);
        
        parseEmptyBody(invokeNode, "jsp:invoke");
    }

    private void parseDoBody(Node parent) throws JasperException {
	Attributes attrs = parseAttributes();
	reader.skipSpaces();

        Node doBodyNode = new Node.DoBodyAction(attrs, start, parent);
        
        parseEmptyBody(doBodyNode, "jsp:doBody");
    }

    private void parseElement(Node parent) throws JasperException {
	Attributes attrs = parseAttributes();
	reader.skipSpaces();

        Node elementNode = new Node.JspElement(attrs, start, parent);
        
        parseOptionalBody( elementNode, "jsp:element", 
            TagInfo.BODY_CONTENT_JSP );
    }

    /*
     * For GetProperty:
     * StdActionContent ::= Attributes EmptyBody
     */
    private void parseGetProperty(Node parent) throws JasperException {
	Attributes attrs = parseAttributes();
	reader.skipSpaces();

        Node getPropertyNode = new Node.GetProperty( attrs, start, parent );
        
        parseOptionalBody(getPropertyNode, "jsp:getProperty",
			  TagInfo.BODY_CONTENT_EMPTY);
    }

    /*
     * For SetProperty:
     * StdActionContent ::= Attributes EmptyBody
     */
    private void parseSetProperty(Node parent) throws JasperException {
	Attributes attrs = parseAttributes();
	reader.skipSpaces();

        Node setPropertyNode = new Node.SetProperty( attrs, start, parent );
        
        parseOptionalBody(setPropertyNode, "jsp:setProperty",
			  TagInfo.BODY_CONTENT_EMPTY);
    }

    /*
     * EmptyBody ::=   '/>'
     *               | ( '>' ETag )
     *               | ( '>' S? '<jsp:attribute' NamedAttributes ETag )
     */
    private void parseEmptyBody( Node parent, String tag ) 
        throws JasperException
    {
	if( reader.matches("/>") ) {
            // Done
        }
        else if( reader.matches( ">" ) ) {
            if( reader.matchesETag( tag ) ) {
                // Done
            }
            else if( reader.matchesOptionalSpacesFollowedBy(
                "<jsp:attribute" ) )
            {
                // Parse the one or more named attribute nodes
                parseNamedAttributes( parent );
                if( !reader.matchesETag( tag ) ) {
                    // Body not allowed
                    err.jspError(reader.mark(),
                        "jsp.error.jspbody.emptybody.only",
                        "&lt;" + tag );
                }
            }
            else {
                err.jspError(reader.mark(), "jsp.error.jspbody.emptybody.only",
                    "&lt;" + tag );
            }
        }
        else {
	    err.jspError(reader.mark(), "jsp.error.unterminated",
                "&lt;" + tag );
        }
    }

    /*
     * For UseBean:
     * StdActionContent ::= Attributes OptionalBody
     */
    private void parseUseBean(Node parent) throws JasperException {
	Attributes attrs = parseAttributes();
	reader.skipSpaces();
        
        Node useBeanNode = new Node.UseBean( attrs, start, parent );
        
        parseOptionalBody( useBeanNode, "jsp:useBean", 
            TagInfo.BODY_CONTENT_JSP );
    }

    /*
     * Parses OptionalBody, but also reused to parse bodies for plugin
     * and param since the syntax is identical (the only thing that
     * differs substantially is how to process the body, and thus
     * we accept the body type as a parameter).
     *
     * OptionalBody ::= EmptyBody | ActionBody
     *
     * ScriptlessOptionalBody ::= EmptyBody | ScriptlessActionBody
     *
     * TagDependentOptionalBody ::= EmptyBody | TagDependentActionBody
     *
     * EmptyBody ::=   '/>'
     *               | ( '>' ETag )
     *               | ( '>' S? '<jsp:attribute' NamedAttributes ETag )
     *
     * ActionBody ::=   JspAttributeAndBody
     *                | ( '>' Body ETag )
     *
     * ScriptlessActionBody ::=   JspAttributeAndBody 
     *                          | ( '>' ScriptlessBody ETag )
     * 
     * TagDependentActionBody ::=   JspAttributeAndBody
     *                            | ( '>' TagDependentBody ETag )
     *
     */
    private void parseOptionalBody( Node parent, String tag, String bodyType ) 
        throws JasperException 
    {
	if (reader.matches("/>")) {
	    // EmptyBody
	    return;
	}

	if (!reader.matches(">")) {
	    err.jspError(reader.mark(), "jsp.error.unterminated",
			 "&lt;" + tag );
	}
        
        if( reader.matchesETag( tag ) ) {
            // EmptyBody
            return;
        }
        
        if( !parseJspAttributeAndBody( parent, tag, bodyType ) ) {
            // Must be ( '>' # Body ETag )
            parseBody(parent, tag, bodyType );
        }
    }
    
    /**
     * Attempts to parse 'JspAttributeAndBody' production.  Returns true if
     * it matched, or false if not.  Assumes EmptyBody is okay as well.
     *
     * JspAttributeAndBody ::=
     *                  ( '>' # S? ( '<jsp:attribute' NamedAttributes )?
     *                    '<jsp:body'
     *                    ( JspBodyBody | <TRANSLATION_ERROR> )
     *                    S? ETag
     *                  )
     */
    private boolean parseJspAttributeAndBody( Node parent, String tag, 
        String bodyType ) 
        throws JasperException
    {
        boolean result = false;
        
        if( reader.matchesOptionalSpacesFollowedBy( "<jsp:attribute" ) ) {
            // May be an EmptyBody, depending on whether
            // There's a "<jsp:body" before the ETag
            
            // First, parse <jsp:attribute> elements:
            parseNamedAttributes( parent );
            
            result = true;
        }
        
        if( reader.matchesOptionalSpacesFollowedBy( "<jsp:body" ) ) {
            // ActionBody
            parseJspBody( parent, bodyType );
            reader.skipSpaces();
            if( !reader.matchesETag( tag ) ) {
                err.jspError(reader.mark(), "jsp.error.unterminated", 
                    "&lt;" + tag );
            }
            
            result = true;
        }
        else if( result && !reader.matchesETag( tag ) ) {
            // If we have <jsp:attribute> but something other than
            // <jsp:body> or the end tag, translation error.
            err.jspError(reader.mark(), "jsp.error.jspbody.required", 
                "&lt;" + tag );
        }

⌨️ 快捷键说明

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