KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > polyglot > ext > jl > ast > Disamb_c


1 package polyglot.ext.jl.ast;
2
3 import polyglot.ast.*;
4 import polyglot.types.*;
5 import polyglot.util.Position;
6 import polyglot.visit.ContextVisitor;
7
8 /**
9  * Utility class which is used to disambiguate ambiguous
10  * AST nodes (Expr, Type, Receiver, Qualifier, Prefix).
11  */

12 public class Disamb_c implements Disamb
13 {
14     protected ContextVisitor v;
15     protected Position pos;
16     protected Prefix prefix;
17     protected String JavaDoc name;
18
19     protected NodeFactory nf;
20     protected TypeSystem ts;
21     protected Context c;
22     protected Ambiguous amb;
23
24     /**
25      * Disambiguate the prefix and name into a unambiguous node.
26      * @return An unambiguous AST node, or null if disambiguation
27      * fails.
28      */

29     public Node disambiguate(Ambiguous amb, ContextVisitor v, Position pos,
30             Prefix prefix, String JavaDoc name) throws SemanticException {
31
32         this.v = v;
33         this.pos = pos;
34         this.prefix = prefix;
35         this.name = name;
36         this.amb = amb;
37
38         nf = v.nodeFactory();
39         ts = v.typeSystem();
40         c = v.context();
41
42         if (prefix instanceof Ambiguous) {
43             throw new SemanticException(
44                 "Cannot disambiguate node with ambiguous prefix.");
45         }
46
47         if (prefix instanceof PackageNode) {
48             PackageNode pn = (PackageNode) prefix;
49             return disambiguatePackagePrefix(pn);
50         } else if (prefix instanceof TypeNode) {
51             TypeNode tn = (TypeNode) prefix;
52             return disambiguateTypeNodePrefix(tn);
53         } else if (prefix instanceof Expr) {
54             Expr e = (Expr) prefix;
55             return disambiguateExprPrefix(e);
56         } else if (prefix == null) {
57             return disambiguateNoPrefix();
58         }
59
60         return null;
61     }
62
63     protected Node disambiguatePackagePrefix(PackageNode pn) throws SemanticException {
64         Resolver pc = ts.packageContextResolver(c.outerResolver(),
65                                                 pn.package_());
66
67         Named n = pc.find(name);
68         Qualifier q = null;
69
70         if (n instanceof Qualifier) {
71             q = (Qualifier) n;
72         } else {
73             return null;
74         }
75         
76         if (q.isPackage() && packageOK()) {
77             return nf.PackageNode(pos, q.toPackage());
78         } else if (q.isType() && typeOK()) {
79             return nf.CanonicalTypeNode(pos, q.toType());
80         }
81
82         return null;
83     }
84
85
86     protected Node disambiguateTypeNodePrefix(TypeNode tn)
87         throws SemanticException
88     {
89         // Try static fields.
90
Type t = tn.type();
91
92         if (t.isReference() && exprOK()) {
93             try {
94                 FieldInstance fi = ts.findField(t.toReference(), name, c);
95                 return nf.Field(pos, tn, name).fieldInstance(fi);
96             } catch (NoMemberException e) {
97                 if (e.getKind() != e.FIELD) {
98                     // something went wrong...
99
throw e;
100                 }
101                 
102                 // ignore so we can check if we're a member class.
103
}
104         }
105
106         // Try member classes.
107
if (t.isClass() && typeOK()) {
108             Resolver tc = ts.classContextResolver(t.toClass());
109             Named n = tc.find(name);
110             if (n instanceof Type) {
111                 Type type = (Type) n;
112                 return nf.CanonicalTypeNode(pos, type);
113             }
114         }
115
116         return null;
117     }
118
119     protected Node disambiguateExprPrefix(Expr e) throws SemanticException {
120         // Must be a non-static field.
121
if (exprOK()) {
122             return nf.Field(pos, e, name);
123         }
124         return null;
125     }
126
127     protected Node disambiguateNoPrefix() throws SemanticException {
128
129         // First try local variables and fields.
130
VarInstance vi = c.findVariableSilent(name);
131         
132         if (vi != null && exprOK()) {
133             Node n = disambiguateVarInstance(vi);
134             if (n != null) return n;
135         }
136
137         // no variable found. try types.
138
if (typeOK()) {
139             try {
140                 Named n = c.find(name);
141                 if (n instanceof Type) {
142                     Type type = (Type) n;
143                     return nf.CanonicalTypeNode(pos, type);
144                 }
145             } catch (NoClassException e) {
146                 if (!name.equals(e.getClassName())) {
147                     // hmm, something else must have gone wrong
148
// rethrow the exception
149
throw e;
150                 }
151
152                 // couldn't find a type named name.
153
// It must be a package--ignore the exception.
154
}
155         }
156
157         // Must be a package then...
158
if (packageOK()) {
159             return nf.PackageNode(pos, ts.packageForName(name));
160         }
161
162         return null;
163     }
164
165     protected Node disambiguateVarInstance(VarInstance vi) throws SemanticException {
166         if (vi instanceof FieldInstance) {
167             FieldInstance fi = (FieldInstance) vi;
168             Receiver r = makeMissingFieldTarget(fi);
169             return nf.Field(pos, r, name).fieldInstance(fi).targetImplicit(true);
170         } else if (vi instanceof LocalInstance) {
171             LocalInstance li = (LocalInstance) vi;
172             return nf.Local(pos, name).localInstance(li);
173         }
174         return null;
175     }
176
177     protected Receiver makeMissingFieldTarget(FieldInstance fi) throws SemanticException {
178         Receiver r;
179
180         if (fi.flags().isStatic()) {
181             r = nf.CanonicalTypeNode(pos, fi.container());
182         } else {
183             // The field is non-static, so we must prepend with
184
// "this", but we need to determine if the "this"
185
// should be qualified. Get the enclosing class which
186
// brought the field into scope. This is different
187
// from fi.container(). fi.container() returns a super
188
// type of the class we want.
189
ClassType scope = c.findFieldScope(name);
190
191             if (! ts.equals(scope, c.currentClass())) {
192                 r = nf.This(pos, nf.CanonicalTypeNode(pos, scope));
193             } else {
194                 r = nf.This(pos);
195             }
196         }
197
198         return r;
199     }
200
201     protected boolean typeOK() {
202         return ! (amb instanceof Expr) &&
203               (amb instanceof TypeNode || amb instanceof QualifierNode ||
204                amb instanceof Receiver || amb instanceof Prefix);
205
206     }
207
208     protected boolean packageOK() {
209         return ! (amb instanceof Receiver) &&
210               (amb instanceof QualifierNode || amb instanceof Prefix);
211     }
212
213     protected boolean exprOK() {
214         return ! (amb instanceof QualifierNode) &&
215               (amb instanceof Expr || amb instanceof Receiver ||
216                amb instanceof Prefix);
217     }
218 }
219
Popular Tags