|
|
|
|
|
*/ |
|
/* |
|
* 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. |
|
*/ |
|
/* |
|
* $Id: AttributeValueTemplate.java,v 1.2.4.1 2005/09/01 10:26:57 pvedula Exp $ |
|
*/ |
|
|
|
package com.sun.org.apache.xalan.internal.xsltc.compiler; |
|
|
|
import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; |
|
import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL; |
|
import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; |
|
import com.sun.org.apache.bcel.internal.generic.Instruction; |
|
import com.sun.org.apache.bcel.internal.generic.InstructionList; |
|
import com.sun.org.apache.bcel.internal.generic.NEW; |
|
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; |
|
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; |
|
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; |
|
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; |
|
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; |
|
import java.util.Iterator; |
|
import java.util.List; |
|
import java.util.NoSuchElementException; |
|
import java.util.StringTokenizer; |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
final class AttributeValueTemplate extends AttributeValue { |
|
|
|
final static int OUT_EXPR = 0; |
|
final static int IN_EXPR = 1; |
|
final static int IN_EXPR_SQUOTES = 2; |
|
final static int IN_EXPR_DQUOTES = 3; |
|
final static String DELIMITER = "\uFFFE"; |
|
|
|
public AttributeValueTemplate(String value, Parser parser, |
|
SyntaxTreeNode parent) |
|
{ |
|
setParent(parent); |
|
setParser(parser); |
|
|
|
try { |
|
parseAVTemplate(value, parser); |
|
} |
|
catch (NoSuchElementException e) { |
|
reportError(parent, parser, |
|
ErrorMsg.ATTR_VAL_TEMPLATE_ERR, value); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private void parseAVTemplate(String text, Parser parser) { |
|
StringTokenizer tokenizer = |
|
new StringTokenizer(text, "{}\"\'", true); |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
String t = null; |
|
String lookahead = null; |
|
StringBuilder buffer = new StringBuilder(); |
|
int state = OUT_EXPR; |
|
|
|
while (tokenizer.hasMoreTokens()) { |
|
|
|
if (lookahead != null) { |
|
t = lookahead; |
|
lookahead = null; |
|
} |
|
else { |
|
t = tokenizer.nextToken(); |
|
} |
|
|
|
if (t.length() == 1) { |
|
switch (t.charAt(0)) { |
|
case '{': |
|
switch (state) { |
|
case OUT_EXPR: |
|
lookahead = tokenizer.nextToken(); |
|
if (lookahead.equals("{")) { |
|
buffer.append(lookahead); |
|
lookahead = null; |
|
} |
|
else { |
|
buffer.append(DELIMITER); |
|
state = IN_EXPR; |
|
} |
|
break; |
|
case IN_EXPR: |
|
case IN_EXPR_SQUOTES: |
|
case IN_EXPR_DQUOTES: |
|
reportError(getParent(), parser, |
|
ErrorMsg.ATTR_VAL_TEMPLATE_ERR, text); |
|
break; |
|
} |
|
break; |
|
case '}': |
|
switch (state) { |
|
case OUT_EXPR: |
|
lookahead = tokenizer.nextToken(); |
|
if (lookahead.equals("}")) { |
|
buffer.append(lookahead); |
|
lookahead = null; |
|
} |
|
else { |
|
reportError(getParent(), parser, |
|
ErrorMsg.ATTR_VAL_TEMPLATE_ERR, text); |
|
} |
|
break; |
|
case IN_EXPR: |
|
buffer.append(DELIMITER); |
|
state = OUT_EXPR; |
|
break; |
|
case IN_EXPR_SQUOTES: |
|
case IN_EXPR_DQUOTES: |
|
buffer.append(t); |
|
break; |
|
} |
|
break; |
|
case '\'': |
|
switch (state) { |
|
case IN_EXPR: |
|
state = IN_EXPR_SQUOTES; |
|
break; |
|
case IN_EXPR_SQUOTES: |
|
state = IN_EXPR; |
|
break; |
|
case OUT_EXPR: |
|
case IN_EXPR_DQUOTES: |
|
break; |
|
} |
|
buffer.append(t); |
|
break; |
|
case '\"': |
|
switch (state) { |
|
case IN_EXPR: |
|
state = IN_EXPR_DQUOTES; |
|
break; |
|
case IN_EXPR_DQUOTES: |
|
state = IN_EXPR; |
|
break; |
|
case OUT_EXPR: |
|
case IN_EXPR_SQUOTES: |
|
break; |
|
} |
|
buffer.append(t); |
|
break; |
|
default: |
|
buffer.append(t); |
|
break; |
|
} |
|
} |
|
else { |
|
buffer.append(t); |
|
} |
|
} |
|
|
|
|
|
if (state != OUT_EXPR) { |
|
reportError(getParent(), parser, |
|
ErrorMsg.ATTR_VAL_TEMPLATE_ERR, text); |
|
} |
|
|
|
|
|
|
|
*/ |
|
tokenizer = new StringTokenizer(buffer.toString(), DELIMITER, true); |
|
|
|
while (tokenizer.hasMoreTokens()) { |
|
t = tokenizer.nextToken(); |
|
|
|
if (t.equals(DELIMITER)) { |
|
addElement(parser.parseExpression(this, tokenizer.nextToken())); |
|
tokenizer.nextToken(); |
|
} |
|
else { |
|
addElement(new LiteralExpr(t)); |
|
} |
|
} |
|
} |
|
|
|
public Type typeCheck(SymbolTable stable) throws TypeCheckError { |
|
final List<SyntaxTreeNode> contents = getContents(); |
|
final int n = contents.size(); |
|
for (int i = 0; i < n; i++) { |
|
final Expression exp = (Expression)contents.get(i); |
|
if (!exp.typeCheck(stable).identicalTo(Type.String)) { |
|
contents.set(i, new CastExpr(exp, Type.String)); |
|
} |
|
} |
|
return _type = Type.String; |
|
} |
|
|
|
public String toString() { |
|
final StringBuilder buffer = new StringBuilder("AVT:["); |
|
final int count = elementCount(); |
|
for (int i = 0; i < count; i++) { |
|
buffer.append(elementAt(i).toString()); |
|
if (i < count - 1) |
|
buffer.append(' '); |
|
} |
|
return buffer.append(']').toString(); |
|
} |
|
|
|
public void translate(ClassGenerator classGen, MethodGenerator methodGen) { |
|
if (elementCount() == 1) { |
|
final Expression exp = (Expression)elementAt(0); |
|
exp.translate(classGen, methodGen); |
|
} |
|
else { |
|
final ConstantPoolGen cpg = classGen.getConstantPool(); |
|
final InstructionList il = methodGen.getInstructionList(); |
|
final int initBuffer = cpg.addMethodref(STRING_BUFFER_CLASS, |
|
"<init>", "()V"); |
|
final Instruction append = |
|
new INVOKEVIRTUAL(cpg.addMethodref(STRING_BUFFER_CLASS, |
|
"append", |
|
"(" + STRING_SIG + ")" |
|
+ STRING_BUFFER_SIG)); |
|
|
|
final int toString = cpg.addMethodref(STRING_BUFFER_CLASS, |
|
"toString", |
|
"()"+STRING_SIG); |
|
il.append(new NEW(cpg.addClass(STRING_BUFFER_CLASS))); |
|
il.append(DUP); |
|
il.append(new INVOKESPECIAL(initBuffer)); |
|
|
|
final Iterator<SyntaxTreeNode> elements = elements(); |
|
while (elements.hasNext()) { |
|
final Expression exp = (Expression)elements.next(); |
|
exp.translate(classGen, methodGen); |
|
il.append(append); |
|
} |
|
il.append(new INVOKEVIRTUAL(toString)); |
|
} |
|
} |
|
} |