1 /*
   2  * Copyright (c) 2003, 2011, 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 import java.lang.reflect.GenericSignatureFormatError;
  29 import java.util.*;
  30 import sun.reflect.generics.tree.*;
  31 
  32 /**
  33  * Parser for type signatures, as defined in the Java Virtual
  34  * Machine Specification (JVMS) chapter 4.
  35  * Converts the signatures into an abstract syntax tree (AST) representation.
  36  * See the package sun.reflect.generics.tree for details of the AST.
  37  */
  38 public class SignatureParser {
  39     // The input is conceptually a character stream (though currently it's
  40     // a string). This is slightly different than traditional parsers,
  41     // because there is no lexical scanner performing tokenization.
  42     // Having a separate tokenizer does not fit with the nature of the
  43     // input format.
  44     // Other than the absence of a tokenizer, this parser is a classic
  45     // recursive descent parser. Its structure corresponds as closely
  46     // as possible to the grammar in the JVMS.
  47     //
  48     // A note on asserts vs. errors: The code contains assertions
  49     // in situations that should never occur. An assertion failure
  50     // indicates a failure of the parser logic. A common pattern
  51     // is an assertion that the current input is a particular
  52     // character. This is often paired with a separate check
  53     // that this is the case, which seems redundant. For example:
  54     //
  55     // assert(current() != x);
  56     // if (current != x {error("expected an x");
  57     //
  58     // where x is some character constant.
  59     // The assertion indicates, that, as currently written,
  60     // the code should never reach this point unless the input is an
  61     // x. On the other hand, the test is there to check the legality
  62     // of the input wrt to a given production. It may be that at a later
  63     // time the code might be called directly, and if the input is
  64     // invalid, the parser should flag an error in accordance
  65     // with its logic.
  66 
  67     private char[] input; // the input signature
  68     private int index = 0; // index into the input
  69     // used to mark end of input
  70     private static final char EOI = ':';
  71     private static final boolean DEBUG = false;
  72 
  73     // private constructor - enforces use of static factory
  74     private SignatureParser(){}
  75 
  76     // Utility methods.
  77 
  78     // Most parsing routines use the following routines to access the
  79     // input stream, and advance it as necessary.
  80     // This makes it easy to adapt the parser to operate on streams
  81     // of various kinds as well as strings.
  82 
  83     // returns current element of the input and advances the input
  84     private char getNext(){
  85         assert(index <= input.length);
  86         try {
  87             return input[index++];
  88         } catch (ArrayIndexOutOfBoundsException e) { return EOI;}
  89     }
  90 
  91     // returns current element of the input
  92     private char current(){
  93         assert(index <= input.length);
  94         try {
  95             return input[index];
  96         } catch (ArrayIndexOutOfBoundsException e) { return EOI;}
  97     }
  98 
  99     // advance the input
 100     private void advance(){
 101         assert(index <= input.length);
 102         index++;
 103     }
 104 
 105     // For debugging, prints current character to the end of the input.
 106     private String remainder() {
 107         return new String(input, index, input.length-index);
 108     }
 109 
 110     // Match c against a "set" of characters
 111     private boolean matches(char c, char... set) {
 112         for (char e : set) {
 113             if (c == e) return true;
 114         }
 115         return false;
 116     }
 117 
 118     // Error handling routine. Encapsulates error handling.
 119     // Takes a string error message as argument.
 120     // Currently throws a GenericSignatureFormatError.
 121 
 122     private Error error(String errorMsg) {
 123         return new GenericSignatureFormatError("Signature Parse error: " + errorMsg +
 124                                                "\n\tRemaining input: " + remainder());
 125     }
 126 
 127     /**
 128      * Verify the parse has made forward progress; throw an exception
 129      * if no progress.
 130      */
 131     private void progress(int startingPosition) {
 132         if (index <= startingPosition)
 133             throw error("Failure to make progress!");
 134     }
 135 
 136     /**
 137      * Static factory method. Produces a parser instance.
 138      * @return an instance of {@code SignatureParser}
 139      */
 140     public static SignatureParser make() {
 141         return new SignatureParser();
 142     }
 143 
 144     /**
 145      * Parses a class signature (as defined in the JVMS, chapter 4)
 146      * and produces an abstract syntax tree representing it.
 147      * @param s a string representing the input class signature
 148      * @return An abstract syntax tree for a class signature
 149      * corresponding to the input string
 150      * @throws GenericSignatureFormatError if the input is not a valid
 151      * class signature
 152      */
 153     public ClassSignature parseClassSig(String s) {
 154         if (DEBUG) System.out.println("Parsing class sig:" + s);
 155         input = s.toCharArray();
 156         return parseClassSignature();
 157     }
 158 
 159     /**
 160      * Parses a method signature (as defined in the JVMS, chapter 4)
 161      * and produces an abstract syntax tree representing it.
 162      * @param s a string representing the input method signature
 163      * @return An abstract syntax tree for a method signature
 164      * corresponding to the input string
 165      * @throws GenericSignatureFormatError if the input is not a valid
 166      * method signature
 167      */
 168     public MethodTypeSignature parseMethodSig(String s) {
 169         if (DEBUG) System.out.println("Parsing method sig:" + s);
 170         input = s.toCharArray();
 171         return parseMethodTypeSignature();
 172     }
 173 
 174 
 175     /**
 176      * Parses a type signature
 177      * and produces an abstract syntax tree representing it.
 178      *
 179      * @param s a string representing the input type signature
 180      * @return An abstract syntax tree for a type signature
 181      * corresponding to the input string
 182      * @throws GenericSignatureFormatError if the input is not a valid
 183      * type signature
 184      */
 185     public TypeSignature parseTypeSig(String s) {
 186         if (DEBUG) System.out.println("Parsing type sig:" + s);
 187         input = s.toCharArray();
 188         return parseTypeSignature();
 189     }
 190 
 191     // Parsing routines.
 192     // As a rule, the parsing routines access the input using the
 193     // utilities current(), getNext() and/or advance().
 194     // The convention is that when a parsing routine is invoked
 195     // it expects the current input to be the first character it should parse
 196     // and when it completes parsing, it leaves the input at the first
 197     // character after the input parses.
 198 
 199     /*
 200      * Note on grammar conventions: a trailing "*" matches zero or
 201      * more occurrences, a trailing "+" matches one or more occurrences,
 202      * "_opt" indicates an optional component.
 203      */
 204 
 205     /**
 206      * ClassSignature:
 207      *     FormalTypeParameters_opt SuperclassSignature SuperinterfaceSignature*
 208      */
 209     private ClassSignature parseClassSignature() {
 210         // parse a class signature based on the implicit input.
 211         assert(index == 0);
 212         return ClassSignature.make(parseZeroOrMoreFormalTypeParameters(),
 213                                    parseClassTypeSignature(), // Only rule for SuperclassSignature
 214                                    parseSuperInterfaces());
 215     }
 216 
 217     private FormalTypeParameter[] parseZeroOrMoreFormalTypeParameters(){
 218         if (current() == '<') {
 219             return parseFormalTypeParameters();
 220         } else {
 221             return new FormalTypeParameter[0];
 222         }
 223     }
 224 
 225     /**
 226      * FormalTypeParameters:
 227      *     "<" FormalTypeParameter+ ">"
 228      */
 229     private FormalTypeParameter[] parseFormalTypeParameters(){
 230         List<FormalTypeParameter> ftps = new ArrayList<>(3);
 231         assert(current() == '<'); // should not have been called at all
 232         if (current() != '<') { throw error("expected '<'");}
 233         advance();
 234         ftps.add(parseFormalTypeParameter());
 235         while (current() != '>') {
 236             int startingPosition = index;
 237             ftps.add(parseFormalTypeParameter());
 238             progress(startingPosition);
 239         }
 240         advance();
 241         return ftps.toArray(new FormalTypeParameter[ftps.size()]);
 242     }
 243 
 244     /**
 245      * FormalTypeParameter:
 246      *     Identifier ClassBound InterfaceBound*
 247      */
 248     private FormalTypeParameter parseFormalTypeParameter(){
 249         String id = parseIdentifier();
 250         FieldTypeSignature[] bs = parseBounds();
 251         return FormalTypeParameter.make(id, bs);
 252     }
 253 
 254     private String parseIdentifier(){
 255         StringBuilder result = new StringBuilder();
 256         while (!Character.isWhitespace(current())) {
 257             char c = current();
 258             switch(c) {
 259             case ';':
 260             case '.':
 261             case '/':
 262             case '[':
 263             case ':':
 264             case '>':
 265             case '<':
 266                 return result.toString();
 267             default:{
 268                 result.append(c);
 269                 advance();
 270             }
 271 
 272             }
 273         }
 274         return result.toString();
 275     }
 276     /**
 277      * FieldTypeSignature:
 278      *     ClassTypeSignature
 279      *     ArrayTypeSignature
 280      *     TypeVariableSignature
 281      */
 282     private FieldTypeSignature parseFieldTypeSignature() {
 283         return parseFieldTypeSignature(true);
 284     }
 285 
 286     private FieldTypeSignature parseFieldTypeSignature(boolean allowArrays) {
 287         switch(current()) {
 288         case 'L':
 289            return parseClassTypeSignature();
 290         case 'T':
 291             return parseTypeVariableSignature();
 292         case '[':
 293             if (allowArrays)
 294                 return parseArrayTypeSignature();
 295             else
 296                 throw error("Array signature not allowed here.");
 297         default: throw error("Expected Field Type Signature");
 298         }
 299     }
 300 
 301     /**
 302      * ClassTypeSignature:
 303      *     "L" PackageSpecifier_opt SimpleClassTypeSignature ClassTypeSignatureSuffix* ";"
 304      */
 305     private ClassTypeSignature parseClassTypeSignature(){
 306         assert(current() == 'L');
 307         if (current() != 'L') { throw error("expected a class type");}
 308         advance();
 309         List<SimpleClassTypeSignature> scts = new ArrayList<>(5);
 310         scts.add(parsePackageNameAndSimpleClassTypeSignature());
 311 
 312         parseClassTypeSignatureSuffix(scts);
 313         if (current() != ';')
 314             throw error("expected ';' got '" + current() + "'");
 315 
 316         advance();
 317         return ClassTypeSignature.make(scts);
 318     }
 319 
 320     /**
 321      * PackageSpecifier:
 322      *     Identifier "/" PackageSpecifier*
 323      */
 324     private SimpleClassTypeSignature parsePackageNameAndSimpleClassTypeSignature() {
 325         // Parse both any optional leading PackageSpecifier as well as
 326         // the following SimpleClassTypeSignature.
 327 
 328         String id = parseIdentifier();
 329 
 330         if (current() == '/') { // package name
 331             StringBuilder idBuild = new StringBuilder(id);
 332 
 333             while(current() == '/') {
 334                 advance();
 335                 idBuild.append(".");
 336                 idBuild.append(parseIdentifier());
 337             }
 338             id = idBuild.toString();
 339         }
 340 
 341         switch (current()) {
 342         case ';':
 343             return SimpleClassTypeSignature.make(id, false, new TypeArgument[0]); // all done!
 344         case '<':
 345             if (DEBUG) System.out.println("\t remainder: " + remainder());
 346             return SimpleClassTypeSignature.make(id, false, parseTypeArguments());
 347         default:
 348             throw error("expected '<' or ';' but got " + current());
 349         }
 350     }
 351 
 352     /**
 353      * SimpleClassTypeSignature:
 354      *     Identifier TypeArguments_opt
 355      */
 356     private SimpleClassTypeSignature parseSimpleClassTypeSignature(boolean dollar){
 357         String id = parseIdentifier();
 358         char c = current();
 359 
 360         switch (c) {
 361         case ';':
 362         case '.':
 363             return SimpleClassTypeSignature.make(id, dollar, new TypeArgument[0]) ;
 364         case '<':
 365             return SimpleClassTypeSignature.make(id, dollar, parseTypeArguments());
 366         default:
 367             throw error("expected '<' or ';' or '.', got '" + c + "'.");
 368         }
 369     }
 370 
 371     /**
 372      * ClassTypeSignatureSuffix:
 373      *     "." SimpleClassTypeSignature
 374      */
 375     private void parseClassTypeSignatureSuffix(List<SimpleClassTypeSignature> scts) {
 376         while (current() == '.') {
 377             advance();
 378             scts.add(parseSimpleClassTypeSignature(true));
 379         }
 380     }
 381 
 382     private TypeArgument[] parseTypeArgumentsOpt() {
 383         if (current() == '<') {return parseTypeArguments();}
 384         else {return new TypeArgument[0];}
 385     }
 386 
 387     /**
 388      * TypeArguments:
 389      *     "<" TypeArgument+ ">"
 390      */
 391     private TypeArgument[] parseTypeArguments() {
 392         List<TypeArgument> tas = new ArrayList<>(3);
 393         assert(current() == '<');
 394         if (current() != '<') { throw error("expected '<'");}
 395         advance();
 396         tas.add(parseTypeArgument());
 397         while (current() != '>') {
 398                 //(matches(current(),  '+', '-', 'L', '[', 'T', '*')) {
 399             tas.add(parseTypeArgument());
 400         }
 401         advance();
 402         return tas.toArray(new TypeArgument[tas.size()]);
 403     }
 404 
 405     /**
 406      * TypeArgument:
 407      *     WildcardIndicator_opt FieldTypeSignature
 408      *     "*"
 409      */
 410     private TypeArgument parseTypeArgument() {
 411         FieldTypeSignature[] ub, lb;
 412         ub = new FieldTypeSignature[1];
 413         lb = new FieldTypeSignature[1];
 414         TypeArgument[] ta = new TypeArgument[0];
 415         char c = current();
 416         switch (c) {
 417         case '+': {
 418             advance();
 419             ub[0] = parseFieldTypeSignature();
 420             lb[0] = BottomSignature.make(); // bottom
 421             return Wildcard.make(ub, lb);
 422         }
 423         case '*':{
 424             advance();
 425             ub[0] = SimpleClassTypeSignature.make("java.lang.Object", false, ta);
 426             lb[0] = BottomSignature.make(); // bottom
 427             return Wildcard.make(ub, lb);
 428         }
 429         case '-': {
 430             advance();
 431             lb[0] = parseFieldTypeSignature();
 432             ub[0] = SimpleClassTypeSignature.make("java.lang.Object", false, ta);
 433             return Wildcard.make(ub, lb);
 434         }
 435         default:
 436             return parseFieldTypeSignature();
 437         }
 438     }
 439 
 440     /**
 441      * TypeVariableSignature:
 442      *     "T" Identifier ";"
 443      */
 444     private TypeVariableSignature parseTypeVariableSignature() {
 445         assert(current() == 'T');
 446         if (current() != 'T') { throw error("expected a type variable usage");}
 447         advance();
 448         TypeVariableSignature ts = TypeVariableSignature.make(parseIdentifier());
 449         if (current() != ';') {
 450             throw error("; expected in signature of type variable named" +
 451                   ts.getIdentifier());
 452         }
 453         advance();
 454         return ts;
 455     }
 456 
 457     /**
 458      * ArrayTypeSignature:
 459      *     "[" TypeSignature
 460      */
 461     private ArrayTypeSignature parseArrayTypeSignature() {
 462         if (current() != '[') {throw error("expected array type signature");}
 463         advance();
 464         return ArrayTypeSignature.make(parseTypeSignature());
 465     }
 466 
 467     /**
 468      * TypeSignature:
 469      *     FieldTypeSignature
 470      *     BaseType
 471      */
 472     private TypeSignature parseTypeSignature() {
 473         switch (current()) {
 474         case 'B':
 475         case 'C':
 476         case 'D':
 477         case 'F':
 478         case 'I':
 479         case 'J':
 480         case 'S':
 481         case 'Z':
 482             return parseBaseType();
 483 
 484         default:
 485             return parseFieldTypeSignature();
 486         }
 487     }
 488 
 489     private BaseType parseBaseType() {
 490         switch(current()) {
 491         case 'B':
 492             advance();
 493             return ByteSignature.make();
 494         case 'C':
 495             advance();
 496             return CharSignature.make();
 497         case 'D':
 498             advance();
 499             return DoubleSignature.make();
 500         case 'F':
 501             advance();
 502             return FloatSignature.make();
 503         case 'I':
 504             advance();
 505             return IntSignature.make();
 506         case 'J':
 507             advance();
 508             return LongSignature.make();
 509         case 'S':
 510             advance();
 511             return ShortSignature.make();
 512         case 'Z':
 513             advance();
 514             return BooleanSignature.make();
 515         default: {
 516             assert(false);
 517             throw error("expected primitive type");
 518         }
 519         }
 520     }
 521 
 522     /**
 523      * ClassBound:
 524      *     ":" FieldTypeSignature_opt
 525      *
 526      * InterfaceBound:
 527      *     ":" FieldTypeSignature
 528      */
 529     private FieldTypeSignature[] parseBounds() {
 530         List<FieldTypeSignature> fts = new ArrayList<>(3);
 531 
 532         if (current() == ':') {
 533             advance();
 534             switch(current()) {
 535             case ':': // empty class bound
 536                 break;
 537 
 538             default: // parse class bound
 539                 fts.add(parseFieldTypeSignature());
 540             }
 541 
 542             // zero or more interface bounds
 543             while (current() == ':') {
 544                 advance();
 545                 fts.add(parseFieldTypeSignature());
 546             }
 547         } else
 548             error("Bound expected");
 549 
 550         return fts.toArray(new FieldTypeSignature[fts.size()]);
 551     }
 552 
 553     /**
 554      * SuperclassSignature:
 555      *     ClassTypeSignature
 556      */
 557     private ClassTypeSignature[] parseSuperInterfaces() {
 558         List<ClassTypeSignature> cts = new ArrayList<>(5);
 559         while(current() == 'L') {
 560             cts.add(parseClassTypeSignature());
 561         }
 562         return cts.toArray(new ClassTypeSignature[cts.size()]);
 563     }
 564 
 565 
 566     /**
 567      * MethodTypeSignature:
 568      *     FormalTypeParameters_opt "(" TypeSignature* ")" ReturnType ThrowsSignature*
 569      */
 570     private MethodTypeSignature parseMethodTypeSignature() {
 571         // Parse a method signature based on the implicit input.
 572         FieldTypeSignature[] ets;
 573 
 574         assert(index == 0);
 575         return MethodTypeSignature.make(parseZeroOrMoreFormalTypeParameters(),
 576                                         parseFormalParameters(),
 577                                         parseReturnType(),
 578                                         parseZeroOrMoreThrowsSignatures());
 579     }
 580 
 581     // "(" TypeSignature* ")"
 582     private TypeSignature[] parseFormalParameters() {
 583         if (current() != '(') {throw error("expected '('");}
 584         advance();
 585         TypeSignature[] pts = parseZeroOrMoreTypeSignatures();
 586         if (current() != ')') {throw error("expected ')'");}
 587         advance();
 588         return pts;
 589     }
 590 
 591     // TypeSignature*
 592     private TypeSignature[] parseZeroOrMoreTypeSignatures() {
 593         List<TypeSignature> ts = new ArrayList<>();
 594         boolean stop = false;
 595         while (!stop) {
 596             switch(current()) {
 597             case 'B':
 598             case 'C':
 599             case 'D':
 600             case 'F':
 601             case 'I':
 602             case 'J':
 603             case 'S':
 604             case 'Z':
 605             case 'L':
 606             case 'T':
 607             case '[': {
 608                 ts.add(parseTypeSignature());
 609                 break;
 610             }
 611             default: stop = true;
 612             }
 613         }
 614         return ts.toArray(new TypeSignature[ts.size()]);
 615     }
 616 
 617     /**
 618      * ReturnType:
 619      *     TypeSignature
 620      *     VoidDescriptor
 621      */
 622     private ReturnType parseReturnType(){
 623         if (current() == 'V') {
 624             advance();
 625             return VoidDescriptor.make();
 626         } else
 627             return parseTypeSignature();
 628     }
 629 
 630     // ThrowSignature*
 631     private FieldTypeSignature[] parseZeroOrMoreThrowsSignatures(){
 632         List<FieldTypeSignature> ets = new ArrayList<>(3);
 633         while( current() == '^') {
 634             ets.add(parseThrowsSignature());
 635         }
 636         return ets.toArray(new FieldTypeSignature[ets.size()]);
 637     }
 638 
 639     /**
 640      * ThrowsSignature:
 641      *     "^" ClassTypeSignature
 642      *     "^" TypeVariableSignature
 643      */
 644     private FieldTypeSignature parseThrowsSignature() {
 645         assert(current() == '^');
 646         if (current() != '^') { throw error("expected throws signature");}
 647         advance();
 648         return parseFieldTypeSignature(false);
 649     }
 650  }