History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/reflect/generics/parser/SignatureParser.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/reflect/generics/parser/SignatureParser.java+530−0
@@ -0,0 +1,530 @@
1+/*
2+ * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.reflect.generics.parser;
27+
28+
29+import java.lang.reflect.GenericSignatureFormatError;
30+import java.util.*;
31+import sun.reflect.generics.tree.*;
32+
33+
34+/**
35+ * Parser for type signatures, as defined in the Java Virtual
36+// Machine Specification (JVMS) chapter 4.
37+ * Converts the signatures into an abstract syntax tree (AST) representation.
38+// See the package sun.reflect.generics.tree for details of the AST.
39+ */
40+public class SignatureParser {
41+ // The input is conceptually a character stream (though currently it's
42+ // a string). This is slightly different than traditional parsers,
43+ // because there is no lexical scanner performing tokenization.
44+ // Having a separate tokenizer does not fit with the nature of the
45+ // input format.
46+ // Other than the absence of a tokenizer, this parser is a classic
47+ // recursive descent parser. Its structure corresponds as closely
48+ // as possible to the grammar in the JVMS.
49+ //
50+ // A note on asserts vs. errors: The code contains assertions
51+ // in situations that should never occur. An assertion failure
52+ // indicates a failure of the parser logic. A common pattern
53+ // is an assertion that the current input is a particular
54+ // character. This is often paired with a separate check
55+ // that this is the case, which seems redundant. For example:
56+ //
57+ // assert(current() != x);
58+ // if (current != x {error("expected an x");
59+ //
60+ // where x is some character constant.
61+ // The assertion inidcates, that, as currently written,
62+ // the code should nver reach this point unless the input is an
63+ // x. On the other hand, the test is there to check the legality
64+ // of the input wrt to a given production. It may be that at a later
65+ // time the code might be called directly, and if the input is
66+ // invalid, the parser should flag an error in accordance
67+ // with its logic.
68+
69+ private char[] input; // the input signature
70+ private int index = 0; // index into the input
71+// used to mark end of input
72+ private static final char EOI = ':';
73+ private static final boolean DEBUG = false;
74+
75+ // private constructor - enforces use of static factory
76+ private SignatureParser(){}
77+
78+ // Utility methods.
79+
80+ // Most parsing routines use the following routines to access the
81+ // input stream, and advance it as necessary.
82+ // This makes it easy to adapt the parser to operate on streams
83+ // of various kinds as well as strings.
84+
85+ // returns current element of the input and advances the input
86+ private char getNext(){
87+ assert(index <= input.length);
88+ try {
89+ return input[index++];
90+ } catch (ArrayIndexOutOfBoundsException e) { return EOI;}
91+ }
92+
93+ // returns current element of the input
94+ private char current(){
95+ assert(index <= input.length);
96+ try {
97+ return input[index];
98+ } catch (ArrayIndexOutOfBoundsException e) { return EOI;}
99+ }
100+
101+ // advance the input
102+ private void advance(){
103+ assert(index <= input.length);
104+ index++;
105+ }
106+
107+ // Match c against a "set" of characters
108+ private boolean matches(char c, char... set) {
109+ for (char e : set) {
110+ if (c == e) return true;
111+ }
112+ return false;
113+ }
114+
115+ // Error handling routine. Encapsulates error handling.
116+ // Takes a string error message as argument.
117+ // Currently throws a GenericSignatureFormatError.
118+
119+ private Error error(String errorMsg) {
120+ if (DEBUG) System.out.println("Parse error:" + errorMsg);
121+ return new GenericSignatureFormatError();
122+ }
123+
124+ /**
125+ * Static factory method. Produces a parser instance.
126+ * @return an instance of <tt>SignatureParser</tt>
127+ */
128+ public static SignatureParser make() {
129+ return new SignatureParser();
130+ }
131+
132+ /**
133+ * Parses a class signature (as defined in the JVMS, chapter 4)
134+ * and produces an abstract syntax tree representing it.
135+ * @param s a string representing the input class signature
136+ * @return An abstract syntax tree for a class signature
137+ * corresponding to the input string
138+ * @throws GenericSignatureFormatError if the input is not a valid
139+ * class signature
140+ */
141+ public ClassSignature parseClassSig(String s) {
142+ if (DEBUG) System.out.println("Parsing class sig:" + s);
143+ input = s.toCharArray();
144+ return parseClassSignature();
145+ }
146+
147+ /**
148+ * Parses a method signature (as defined in the JVMS, chapter 4)
149+ * and produces an abstract syntax tree representing it.
150+ * @param s a string representing the input method signature
151+ * @return An abstract syntax tree for a method signature
152+ * corresponding to the input string
153+ * @throws GenericSignatureFormatError if the input is not a valid
154+ * method signature
155+ */
156+ public MethodTypeSignature parseMethodSig(String s) {
157+ if (DEBUG) System.out.println("Parsing method sig:" + s);
158+ input = s.toCharArray();
159+ return parseMethodTypeSignature();
160+ }
161+
162+
163+ /**
164+ * Parses a type signature
165+ * and produces an abstract syntax tree representing it.
166+ * @param s a string representing the input type signature
167+ * @return An abstract syntax tree for a type signature
168+ * corresponding to the input string
169+ * @throws GenericSignatureFormatError if the input is not a valid
170+ * type signature
171+ */
172+ public TypeSignature parseTypeSig(String s) {
173+ if (DEBUG) System.out.println("Parsing type sig:" + s);
174+ input = s.toCharArray();
175+ return parseTypeSignature();
176+ }
177+
178+ // Parsing routines.
179+ // As a rule, the parsing routines access the input using the
180+ // utilities current(), getNext() and/or advance().
181+ // The convention is that when a parsing routine is invoked
182+ // it expects the current input to be the first character it should parse
183+ // and when it completes parsing, it leaves the input at the first
184+ // character after the input parses.
185+
186+ // parse a class signature based on the implicit input.
187+ private ClassSignature parseClassSignature() {
188+ assert(index == 0);
189+ return ClassSignature.make(parseZeroOrMoreFormalTypeParameters(),
190+ parseClassTypeSignature(),
191+ parseSuperInterfaces());
192+ }
193+
194+ private FormalTypeParameter[] parseZeroOrMoreFormalTypeParameters(){
195+ if (current() == '<') { return parseFormalTypeParameters();}
196+ else {return new FormalTypeParameter[0];}
197+ }
198+
199+
200+ private FormalTypeParameter[] parseFormalTypeParameters(){
201+ Collection<FormalTypeParameter> ftps =
202+ new ArrayList<FormalTypeParameter>(3);
203+ assert(current() == '<'); // should not have been called at all
204+ if (current() != '<') { throw error("expected <");}
205+ advance();
206+ ftps.add(parseFormalTypeParameter());
207+ while (current() != '>') {
208+ ftps.add(parseFormalTypeParameter());
209+ }
210+ advance();
211+ FormalTypeParameter[] ftpa = new FormalTypeParameter[ftps.size()];
212+ return ftps.toArray(ftpa);
213+ }
214+
215+ private FormalTypeParameter parseFormalTypeParameter(){
216+ String id = parseIdentifier();
217+ FieldTypeSignature[] bs = parseZeroOrMoreBounds();
218+ return FormalTypeParameter.make(id, bs);
219+ }
220+
221+ private String parseIdentifier(){
222+ StringBuilder result = new StringBuilder();
223+ while (!Character.isWhitespace(current())) {
224+ char c = current();
225+ switch(c) {
226+ case ';':
227+ case '.':
228+ case '/':
229+ case '[':
230+ case ':':
231+ case '>':
232+ case '<': return result.toString();
233+ default:{
234+ result.append(c);
235+ advance();
236+ }
237+
238+ }
239+ }
240+ return result.toString();
241+ }
242+
243+ private FieldTypeSignature parseFieldTypeSignature() {
244+ switch(current()) {
245+ case 'L':
246+ return parseClassTypeSignature();
247+ case 'T':
248+ return parseTypeVariableSignature();
249+ case '[':
250+ return parseArrayTypeSignature();
251+ default: throw error("Expected Field Type Signature");
252+ }
253+ }
254+
255+ private ClassTypeSignature parseClassTypeSignature(){
256+ assert(current() == 'L');
257+ if (current() != 'L') { throw error("expected a class type");}
258+ advance();
259+ List<SimpleClassTypeSignature> scts =
260+ new ArrayList<SimpleClassTypeSignature>(5);
261+ scts.add(parseSimpleClassTypeSignature(false));
262+ parseClassTypeSignatureSuffix(scts);
263+ if (current() != ';')
264+ throw error("expected ';' got '" + current() + "'");
265+
266+ advance();
267+ return ClassTypeSignature.make(scts);
268+ }
269+
270+ private SimpleClassTypeSignature parseSimpleClassTypeSignature(boolean dollar){
271+ String id = parseIdentifier();
272+ char c = current();
273+ switch (c) {
274+ case ';':
275+ case '/':
276+ return SimpleClassTypeSignature.make(id, dollar, new TypeArgument[0]) ;
277+ case '<': {
278+ return SimpleClassTypeSignature.make(id, dollar, parseTypeArguments());
279+ }
280+ default: {throw error("expected < or ; or /");}
281+ }
282+ }
283+
284+ private void parseClassTypeSignatureSuffix(List<SimpleClassTypeSignature> scts) {
285+ while (current() == '/' || current() == '.') {
286+ boolean dollar = (current() == '.');
287+ advance();
288+ scts.add(parseSimpleClassTypeSignature(dollar));
289+ }
290+ }
291+
292+ private TypeArgument[] parseTypeArgumentsOpt() {
293+ if (current() == '<') {return parseTypeArguments();}
294+ else {return new TypeArgument[0];}
295+ }
296+
297+ private TypeArgument[] parseTypeArguments() {
298+ Collection<TypeArgument> tas = new ArrayList<TypeArgument>(3);
299+ assert(current() == '<');
300+ if (current() != '<') { throw error("expected <");}
301+ advance();
302+ tas.add(parseTypeArgument());
303+ while (current() != '>') {
304+ //(matches(current(), '+', '-', 'L', '[', 'T', '*')) {
305+ tas.add(parseTypeArgument());
306+ }
307+ advance();
308+ TypeArgument[] taa = new TypeArgument[tas.size()];
309+ return tas.toArray(taa);
310+ }
311+
312+ private TypeArgument parseTypeArgument() {
313+ FieldTypeSignature[] ub, lb;
314+ ub = new FieldTypeSignature[1];
315+ lb = new FieldTypeSignature[1];
316+ TypeArgument[] ta = new TypeArgument[0];
317+ char c = current();
318+ switch (c) {
319+ case '+': {
320+ advance();
321+ ub[0] = parseFieldTypeSignature();
322+ lb[0] = BottomSignature.make(); // bottom
323+ return Wildcard.make(ub, lb);
324+ }
325+ case '*':{
326+ advance();
327+ ub[0] = SimpleClassTypeSignature.make("java.lang.Object", false, ta);
328+ lb[0] = BottomSignature.make(); // bottom
329+ return Wildcard.make(ub, lb);
330+ }
331+ case '-': {
332+ advance();
333+ lb[0] = parseFieldTypeSignature();
334+ ub[0] = SimpleClassTypeSignature.make("java.lang.Object", false, ta);
335+ return Wildcard.make(ub, lb);
336+ }
337+ default: return parseFieldTypeSignature();
338+ }
339+ }
340+
341+ // TypeVariableSignature -> T identifier
342+
343+ private TypeVariableSignature parseTypeVariableSignature(){
344+ assert(current() == 'T');
345+ if (current() != 'T') { throw error("expected a type variable usage");}
346+ advance();
347+ TypeVariableSignature ts =
348+ TypeVariableSignature.make(parseIdentifier());
349+ if (current() != ';') {
350+ throw error("; expected in signature of type variable named" +
351+ ts.getIdentifier());
352+ }
353+ advance();
354+ return ts;
355+ }
356+
357+ // ArrayTypeSignature -> [ TypeSignature
358+
359+ private ArrayTypeSignature parseArrayTypeSignature() {
360+ if (current() != '[') {throw error("expected array type signature");}
361+ advance();
362+ return ArrayTypeSignature.make(parseTypeSignature());
363+ }
364+
365+ // TypeSignature -> BaseType | FieldTypeSignature
366+
367+ private TypeSignature parseTypeSignature() {
368+ switch (current()) {
369+ case 'B':
370+ case 'C':
371+ case 'D':
372+ case 'F':
373+ case 'I':
374+ case 'J':
375+ case 'S':
376+ case 'Z':return parseBaseType();
377+ default: return parseFieldTypeSignature();
378+ }
379+ }
380+
381+ private BaseType parseBaseType() {
382+ switch(current()) {
383+ case 'B':
384+ advance();
385+ return ByteSignature.make();
386+ case 'C':
387+ advance();
388+ return CharSignature.make();
389+ case 'D':
390+ advance();
391+ return DoubleSignature.make();
392+ case 'F':
393+ advance();
394+ return FloatSignature.make();
395+ case 'I':
396+ advance();
397+ return IntSignature.make();
398+ case 'J':
399+ advance();
400+ return LongSignature.make();
401+ case 'S':
402+ advance();
403+ return ShortSignature.make();
404+ case 'Z':
405+ advance();
406+ return BooleanSignature.make();
407+ default: {
408+ assert(false);
409+ throw error("expected primitive type");
410+ }
411+ }
412+ }
413+
414+ private FieldTypeSignature[] parseZeroOrMoreBounds() {
415+ Collection<FieldTypeSignature> fts =
416+ new ArrayList<FieldTypeSignature>(3);
417+
418+ if (current() == ':') {
419+ advance();
420+ switch(current()) {
421+ case ':': // empty class bound
422+ break;
423+
424+ default: // parse class bound
425+ fts.add(parseFieldTypeSignature());
426+ }
427+
428+ // zero or more interface bounds
429+ while (current() == ':') {
430+ advance();
431+ fts.add(parseFieldTypeSignature());
432+ }
433+ }
434+
435+ FieldTypeSignature[] fta = new FieldTypeSignature[fts.size()];
436+ return fts.toArray(fta);
437+ }
438+
439+ private ClassTypeSignature[] parseSuperInterfaces() {
440+ Collection<ClassTypeSignature> cts =
441+ new ArrayList<ClassTypeSignature>(5);
442+ while(current() == 'L') {
443+ cts.add(parseClassTypeSignature());
444+ }
445+ ClassTypeSignature[] cta = new ClassTypeSignature[cts.size()];
446+ return cts.toArray(cta);
447+ }
448+
449+ // parse a method signature based on the implicit input.
450+ private MethodTypeSignature parseMethodTypeSignature() {
451+ FieldTypeSignature[] ets;
452+
453+ assert(index == 0);
454+ return MethodTypeSignature.make(parseZeroOrMoreFormalTypeParameters(),
455+ parseFormalParameters(),
456+ parseReturnType(),
457+ parseZeroOrMoreThrowsSignatures());
458+ }
459+
460+ // (TypeSignature*)
461+ private TypeSignature[] parseFormalParameters() {
462+ if (current() != '(') {throw error("expected (");}
463+ advance();
464+ TypeSignature[] pts = parseZeroOrMoreTypeSignatures();
465+ if (current() != ')') {throw error("expected )");}
466+ advance();
467+ return pts;
468+ }
469+
470+ // TypeSignature*
471+ private TypeSignature[] parseZeroOrMoreTypeSignatures() {
472+ Collection<TypeSignature> ts = new ArrayList<TypeSignature>();
473+ boolean stop = false;
474+ while (!stop) {
475+ switch(current()) {
476+ case 'B':
477+ case 'C':
478+ case 'D':
479+ case 'F':
480+ case 'I':
481+ case 'J':
482+ case 'S':
483+ case 'Z':
484+ case 'L':
485+ case 'T':
486+ case '[': {
487+ ts.add(parseTypeSignature());
488+ break;
489+ }
490+ default: stop = true;
491+ }
492+ }
493+ /* while( matches(current(),
494+ 'B', 'C', 'D', 'F', 'I', 'J', 'S', 'Z', 'L', 'T', '[')
495+ ) {
496+ ts.add(parseTypeSignature());
497+ }*/
498+ TypeSignature[] ta = new TypeSignature[ts.size()];
499+ return ts.toArray(ta);
500+ }
501+
502+ // ReturnType -> V | TypeSignature
503+
504+ private ReturnType parseReturnType(){
505+ if (current() == 'V') {
506+ advance();
507+ return VoidDescriptor.make();
508+ } else return parseTypeSignature();
509+ }
510+
511+ // ThrowSignature*
512+ private FieldTypeSignature[] parseZeroOrMoreThrowsSignatures(){
513+ Collection<FieldTypeSignature> ets =
514+ new ArrayList<FieldTypeSignature>(3);
515+ while( current() == '^') {
516+ ets.add(parseThrowsSignature());
517+ }
518+ FieldTypeSignature[] eta = new FieldTypeSignature[ets.size()];
519+ return ets.toArray(eta);
520+ }
521+
522+ // ThrowSignature -> ^ FieldTypeSignature
523+
524+ private FieldTypeSignature parseThrowsSignature() {
525+ assert(current() == '^');
526+ if (current() != '^') { throw error("expected throws signature");}
527+ advance();
528+ return parseFieldTypeSignature();
529+ }
530+ }