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",
"<jsp:scriptlet>");
}
Mark stop;
String text;
while (true) {
start = reader.mark();
stop = reader.skipUntil("<");
if (stop == null) {
err.jspError(start, "jsp.error.unterminated",
"<jsp:scriptlet>");
}
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",
"<jsp:scriptlet>");
}
}
}
/**
* 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",
"<" + tag );
}
}
else {
err.jspError(reader.mark(), "jsp.error.jspbody.emptybody.only",
"<" + tag );
}
}
else {
err.jspError(reader.mark(), "jsp.error.unterminated",
"<" + 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",
"<" + 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",
"<" + 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",
"<" + tag );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?