KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xalan > internal > xsltc > compiler > AttributeValueTemplate


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: AttributeValueTemplate.java,v 1.10 2004/02/16 22:24:29 minchau Exp $
18  */

19
20 package com.sun.org.apache.xalan.internal.xsltc.compiler;
21
22 import java.util.Enumeration JavaDoc;
23 import java.util.Vector JavaDoc;
24 import java.util.StringTokenizer JavaDoc;
25 import java.util.NoSuchElementException JavaDoc;
26
27
28 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
29 import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL;
30 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
31 import com.sun.org.apache.bcel.internal.generic.Instruction;
32 import com.sun.org.apache.bcel.internal.generic.InstructionList;
33 import com.sun.org.apache.bcel.internal.generic.NEW;
34 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
35 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
36 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
37 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
38 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
39
40 /**
41  * @author Jacek Ambroziak
42  * @author Santiago Pericas-Geertsen
43  */

44 final class AttributeValueTemplate extends AttributeValue {
45     
46     final static int OUT_EXPR = 0;
47     final static int IN_EXPR = 1;
48     final static int IN_EXPR_SQUOTES = 2;
49     final static int IN_EXPR_DQUOTES = 3;
50     final static String JavaDoc DELIMITER = "\uFFFE"; // A Unicode nonchar
51

52     public AttributeValueTemplate(String JavaDoc value, Parser parser,
53     SyntaxTreeNode parent)
54     {
55     setParent(parent);
56     setParser(parser);
57         
58         try {
59             parseAVTemplate(value, parser);
60         }
61         catch (NoSuchElementException JavaDoc e) {
62             reportError(parent, parser,
63                         ErrorMsg.ATTR_VAL_TEMPLATE_ERR, value);
64         }
65     }
66
67     /**
68      * Two-pass parsing of ATVs. In the first pass, double curly braces are
69      * replaced by one, and expressions are delimited using DELIMITER. The
70      * second pass splits up the resulting buffer into literal and non-literal
71      * expressions. Errors are reported during the first pass.
72      */

73     private void parseAVTemplate(String JavaDoc text, Parser parser) {
74         StringTokenizer JavaDoc tokenizer =
75             new StringTokenizer JavaDoc(text, "{}\"\'", true);
76         
77         /*
78           * First pass: replace double curly braces and delimit expressions
79           * Simple automaton to parse ATVs, delimit expressions and report
80           * errors.
81           */

82         String JavaDoc t = null;
83         String JavaDoc lookahead = null;
84         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
85         int state = OUT_EXPR;
86         
87         while (tokenizer.hasMoreTokens()) {
88             // Use lookahead if available
89
if (lookahead != null) {
90                 t = lookahead;
91                 lookahead = null;
92             }
93             else {
94                 t = tokenizer.nextToken();
95             }
96             
97             if (t.length() == 1) {
98                 switch (t.charAt(0)) {
99                     case '{':
100                         switch (state) {
101                             case OUT_EXPR:
102                                 lookahead = tokenizer.nextToken();
103                                 if (lookahead.equals("{")) {
104                                     buffer.append(lookahead); // replace {{ by {
105
lookahead = null;
106                                 }
107                                 else {
108                                     buffer.append(DELIMITER);
109                                     state = IN_EXPR;
110                                 }
111                                 break;
112                             case IN_EXPR:
113                             case IN_EXPR_SQUOTES:
114                             case IN_EXPR_DQUOTES:
115                                 reportError(getParent(), parser,
116                                             ErrorMsg.ATTR_VAL_TEMPLATE_ERR, text);
117                                 break;
118                         }
119                         break;
120                     case '}':
121                         switch (state) {
122                             case OUT_EXPR:
123                                 lookahead = tokenizer.nextToken();
124                                 if (lookahead.equals("}")) {
125                                     buffer.append(lookahead); // replace }} by }
126
lookahead = null;
127                                 }
128                                 else {
129                                     reportError(getParent(), parser,
130                                             ErrorMsg.ATTR_VAL_TEMPLATE_ERR, text);
131                                 }
132                                 break;
133                             case IN_EXPR:
134                                 buffer.append(DELIMITER);
135                                 state = OUT_EXPR;
136                                 break;
137                             case IN_EXPR_SQUOTES:
138                             case IN_EXPR_DQUOTES:
139                                 buffer.append(t);
140                                 break;
141                         }
142                         break;
143                     case '\'':
144                         switch (state) {
145                             case IN_EXPR:
146                                 state = IN_EXPR_SQUOTES;
147                                 break;
148                             case IN_EXPR_SQUOTES:
149                                 state = IN_EXPR;
150                                 break;
151                             case OUT_EXPR:
152                             case IN_EXPR_DQUOTES:
153                                 break;
154                         }
155                         buffer.append(t);
156                         break;
157                     case '\"':
158                         switch (state) {
159                             case IN_EXPR:
160                                 state = IN_EXPR_DQUOTES;
161                                 break;
162                             case IN_EXPR_DQUOTES:
163                                 state = IN_EXPR;
164                                 break;
165                             case OUT_EXPR:
166                             case IN_EXPR_SQUOTES:
167                                 break;
168                         }
169                         buffer.append(t);
170                         break;
171                     default:
172                         buffer.append(t);
173                         break;
174                 }
175             }
176             else {
177                 buffer.append(t);
178             }
179         }
180
181         // Must be in OUT_EXPR at the end of parsing
182
if (state != OUT_EXPR) {
183             reportError(getParent(), parser,
184                         ErrorMsg.ATTR_VAL_TEMPLATE_ERR, text);
185         }
186         
187         /*
188           * Second pass: split up buffer into literal and non-literal expressions.
189           */

190         tokenizer = new StringTokenizer JavaDoc(buffer.toString(), DELIMITER, true);
191         
192         while (tokenizer.hasMoreTokens()) {
193             t = tokenizer.nextToken();
194             
195             if (t.equals(DELIMITER)) {
196         addElement(parser.parseExpression(this, tokenizer.nextToken()));
197                 tokenizer.nextToken(); // consume other delimiter
198
}
199             else {
200         addElement(new LiteralExpr(t));
201             }
202         }
203     }
204
205     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
206     final Vector JavaDoc contents = getContents();
207     final int n = contents.size();
208     for (int i = 0; i < n; i++) {
209         final Expression exp = (Expression)contents.elementAt(i);
210         if (!exp.typeCheck(stable).identicalTo(Type.String)) {
211         contents.setElementAt(new CastExpr(exp, Type.String), i);
212         }
213     }
214     return _type = Type.String;
215     }
216
217     public String JavaDoc toString() {
218     final StringBuffer JavaDoc buffer = new StringBuffer JavaDoc("AVT:[");
219     final int count = elementCount();
220     for (int i = 0; i < count; i++) {
221         buffer.append(elementAt(i).toString());
222         if (i < count - 1)
223         buffer.append(' ');
224     }
225     return buffer.append(']').toString();
226     }
227         
228     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
229     if (elementCount() == 1) {
230         final Expression exp = (Expression)elementAt(0);
231         exp.translate(classGen, methodGen);
232     }
233     else {
234         final ConstantPoolGen cpg = classGen.getConstantPool();
235         final InstructionList il = methodGen.getInstructionList();
236         final int initBuffer = cpg.addMethodref(STRING_BUFFER_CLASS,
237                             "<init>", "()V");
238         final Instruction append =
239         new INVOKEVIRTUAL(cpg.addMethodref(STRING_BUFFER_CLASS,
240                            "append",
241                            "(" + STRING_SIG + ")"
242                            + STRING_BUFFER_SIG));
243         
244         final int toString = cpg.addMethodref(STRING_BUFFER_CLASS,
245                           "toString",
246                           "()"+STRING_SIG);
247         il.append(new NEW(cpg.addClass(STRING_BUFFER_CLASS)));
248         il.append(DUP);
249         il.append(new INVOKESPECIAL(initBuffer));
250         // StringBuffer is on the stack
251
final Enumeration JavaDoc elements = elements();
252         while (elements.hasMoreElements()) {
253         final Expression exp = (Expression)elements.nextElement();
254         exp.translate(classGen, methodGen);
255         il.append(append);
256         }
257         il.append(new INVOKEVIRTUAL(toString));
258     }
259     }
260
261 }
262
Popular Tags