KickJava   Java API By Example, From Geeks To Geeks.

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


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: AncestorPattern.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 com.sun.org.apache.bcel.internal.generic.BranchHandle;
23 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
24 import com.sun.org.apache.bcel.internal.generic.GOTO;
25 import com.sun.org.apache.bcel.internal.generic.IFLT;
26 import com.sun.org.apache.bcel.internal.generic.ILOAD;
27 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
28 import com.sun.org.apache.bcel.internal.generic.ISTORE;
29 import com.sun.org.apache.bcel.internal.generic.InstructionHandle;
30 import com.sun.org.apache.bcel.internal.generic.InstructionList;
31 import com.sun.org.apache.bcel.internal.generic.LocalVariableGen;
32 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
33 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
34 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
35 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
36 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
37
38 /**
39  * @author Jacek Ambroziak
40  * @author Santiago Pericas-Geertsen
41  * @author Erwin Bolwidt <ejb@klomp.org>
42  */

43 final class AncestorPattern extends RelativePathPattern {
44
45     private final Pattern _left; // may be null
46
private final RelativePathPattern _right;
47     private InstructionHandle _loop;
48         
49     public AncestorPattern(RelativePathPattern right) {
50     this(null, right);
51     }
52
53     public AncestorPattern(Pattern left, RelativePathPattern right) {
54     _left = left;
55     (_right = right).setParent(this);
56     if (left != null) {
57         left.setParent(this);
58     }
59     }
60     
61     public InstructionHandle getLoopHandle() {
62     return _loop;
63     }
64
65     public void setParser(Parser parser) {
66     super.setParser(parser);
67     if (_left != null) {
68         _left.setParser(parser);
69     }
70     _right.setParser(parser);
71     }
72     
73     public boolean isWildcard() {
74     //!!! can be wildcard
75
return false;
76     }
77     
78     public StepPattern getKernelPattern() {
79     return _right.getKernelPattern();
80     }
81
82     public void reduceKernelPattern() {
83     _right.reduceKernelPattern();
84     }
85     
86     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
87     if (_left != null) {
88         _left.typeCheck(stable);
89     }
90     return _right.typeCheck(stable);
91     }
92
93     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
94     InstructionHandle parent;
95     final ConstantPoolGen cpg = classGen.getConstantPool();
96     final InstructionList il = methodGen.getInstructionList();
97
98     /*
99      * The scope of this local var must be the entire method since
100      * a another pattern may decide to jump back into the loop
101      */

102     final LocalVariableGen local =
103         methodGen.addLocalVariable2("app", Util.getJCRefType(NODE_SIG),
104                     il.getEnd());
105
106     final com.sun.org.apache.bcel.internal.generic.Instruction loadLocal =
107         new ILOAD(local.getIndex());
108     final com.sun.org.apache.bcel.internal.generic.Instruction storeLocal =
109         new ISTORE(local.getIndex());
110
111     if (_right instanceof StepPattern) {
112         il.append(DUP);
113         il.append(storeLocal);
114         _right.translate(classGen, methodGen);
115         il.append(methodGen.loadDOM());
116         il.append(loadLocal);
117     }
118     else {
119         _right.translate(classGen, methodGen);
120
121         if (_right instanceof AncestorPattern) {
122         il.append(methodGen.loadDOM());
123         il.append(SWAP);
124         }
125     }
126
127     if (_left != null) {
128         final int getParent = cpg.addInterfaceMethodref(DOM_INTF,
129                                 GET_PARENT,
130                                 GET_PARENT_SIG);
131         parent = il.append(new INVOKEINTERFACE(getParent, 2));
132         
133         il.append(DUP);
134         il.append(storeLocal);
135         _falseList.add(il.append(new IFLT(null)));
136         il.append(loadLocal);
137
138         _left.translate(classGen, methodGen);
139
140         final SyntaxTreeNode p = getParent();
141         if (p == null || p instanceof Instruction ||
142         p instanceof TopLevelElement)
143         {
144         // do nothing
145
}
146         else {
147         il.append(loadLocal);
148         }
149
150         final BranchHandle exit = il.append(new GOTO(null));
151         _loop = il.append(methodGen.loadDOM());
152         il.append(loadLocal);
153         local.setEnd(_loop);
154         il.append(new GOTO(parent));
155         exit.setTarget(il.append(NOP));
156         _left.backPatchFalseList(_loop);
157
158         _trueList.append(_left._trueList);
159     }
160     else {
161         il.append(POP2);
162     }
163     
164     /*
165      * If _right is an ancestor pattern, backpatch this pattern's false
166      * list to the loop that searches for more ancestors.
167      */

168     if (_right instanceof AncestorPattern) {
169         final AncestorPattern ancestor = (AncestorPattern) _right;
170         _falseList.backPatch(ancestor.getLoopHandle()); // clears list
171
}
172
173     _trueList.append(_right._trueList);
174     _falseList.append(_right._falseList);
175     }
176
177     public String JavaDoc toString() {
178     return "AncestorPattern(" + _left + ", " + _right + ')';
179     }
180 }
181
Popular Tags