    001    /* Copyright 2000, 2001, Compaq Computer Corporation */
    002
    003    package javafe.parser;
    004
    005    import javafe.ast.*;
    006    import javafe.util.StackVector;
    007    import javafe.util.ErrorSet;
    008
    009    import javafe.util.CorrelatedReader;    // For test harness only
    010    import javafe.util.Location;
    011
    012    import java.util.List;
    013    import java.util.LinkedList;
    014    import java.util.Iterator;
    015
    016    /**
    017     * Parses java source.
    018     *
    019     * <p> Uses the static <code>make*()</code> methods of the classes of
    020     * the <code>javafe.ast</code> package to create AST nodes.
    021     *
    022     * <p> The main entry point is the method
    023     * {@link #parseStream(CorrelatedReader, boolean)}.
    024     *
    025     * <P>Each parsing method for a particular syntactic unit is
    026     * documented with appropriate grammar production rules for that
    027     * syntactic unit.  These grammar rules follow the conventions
    028     * described in "The Java Language Specification", with the addition
    029     * of the symbols '(', ')', '[', ']', '*', '+', and '|', which have
    030     * their usual meaning. When necessary, we denote the corresponding
    031     * concrete tokens using LPAREN, RPAREN, LSQBRACKET, RSQBRACKET, STAR,
    032     * PLUS and BITOR.
    033     *
    034     * @see javafe.ast.ASTNode
    035     * @see javafe.parser.ParseStmt
    036     */
    037
    038    public class Parse extends ParseStmt
    039    {
    040        public Parse() {
    041            //@ set seqTypeName.elementType = \type(TypeName);
    042            //@ set seqTypeName.owner = this;
    043
    044            //@ set seqFormalParaDecl.elementType = \type(FormalParaDecl);
    045            //@ set seqFormalParaDecl.owner = this;
    046
    047            //@ set seqImportDecl.elementType = \type(ImportDecl);
    048            //@ set seqImportDecl.owner = this;
    049
    050            //@ set seqTypeDecl.elementType = \type(TypeDecl);
    051            //@ set seqTypeDecl.owner = this;
    052        }
    053
    054        /**
    055         * Internal working storage for many Parse functions.
    056         */
    057        //@ invariant seqTypeName.elementType == \type(TypeName);
    058        //@ invariant seqTypeName.owner == this;
    059        protected final /*@ non_null @*/ StackVector seqTypeName
    060            = new StackVector();
    061
    062        /**
    063         * Internal working storage for many Parse functions.
    064         */
    065        //@ invariant seqFormalParaDecl.elementType == \type(FormalParaDecl);
    066        //@ invariant seqFormalParaDecl.owner == this;
    067        protected final /*@ non_null @*/ StackVector seqFormalParaDecl
    068            = new StackVector();
    069
    070        /**
    071         * Internal working storage for many Parse functions.
    072         */
    073        //@ invariant seqImportDecl.elementType == \type(ImportDecl);
    074        //@ invariant seqImportDecl.owner == this;
    075        protected final /*@ non_null @*/ StackVector seqImportDecl
    076            = new StackVector();
    077
    078        /**
    079         * Internal working storage for many Parse functions.
    080         */
    081        //@ invariant seqTypeDecl.elementType == \type(TypeDecl);
    082        //@ invariant seqTypeDecl.owner == this;
    083        protected final /*@ non_null @*/ StackVector seqTypeDecl
    084            = new StackVector();
    085
    086
    087      /** Parse a <TT>CompilationUnit</TT> from an input stream.
    088
    089        <P> Requires: prefix of <TT>in</TT> contains text from which the
    090        <TT>CompilationUnit</TT> non-terminal can be derrived.
    091
    092        <P> Ensures: parses a <TT>CompilationUnit</TT> from the input
    093        stream, generating a syntax tree for it.  All errors are treated
    094        as fatal errors and are reporting through <code>ErrorSet</code>.
    095
    096        @see javafe.util.ErrorSet
    097        */
    098
    099      //@ requires in != null;
    100      public CompilationUnit parseStream(CorrelatedReader in, boolean specOnly) {
    101        if (parseStreamLexer == null) parseStreamLexer = new Lex(null, true);
    102        parseStreamLexer.restart(in);
    103        return parseCompilationUnit(parseStreamLexer, specOnly);
    104      }
    105
    106
    107      private Lex parseStreamLexer;
    108
    109      /** Parse a <TT>CompilationUnit</TT>.
    110          <PRE>
    111          CompilationUnit:
    112             [Package name ;] ImportDeclaration* TypeDeclaration*
    113          </PRE>
    114          To handle pragmas, call this method directly
    115          with an appropriate <TT>Lex</TT> object.
    116        */
    117      // specOnly means parse without keeping the bodies of methods/constructors/..
    118
    119      //@ requires l != null && l.m_in != null;
    120      //@ ensures \result != null;
    121      public CompilationUnit parseCompilationUnit(Lex l, boolean specOnly) {
    122        Name pkgName = null;
    123        int loc = l.startingLoc;
    124
    125
    126        /* Optional PackageDeclaration: package name ; */
    127        if( l.ttype == TagConstants.PACKAGE ) {
    128          l.getNextToken();
    129          pkgName = parseName(l);
    130          expect( l, TagConstants.SEMICOLON );
    131        }
    132
    133        /* Import Declarations */
    134        seqImportDecl.push();
    135        while( l.ttype == TagConstants.IMPORT ) {
    136          seqImportDecl.addElement( parseImportDeclaration( l ) );
    137        }
    138        ImportDeclVec imports = ImportDeclVec.popFromStackVector(seqImportDecl);
    139
    140        /* Type Declarations */
    141        seqTypeDeclElem.push();
    142        seqTypeDecl.push();
    143        while( l.ttype != TagConstants.EOF ) {
    144          if( l.ttype == TagConstants.SEMICOLON )
    145            l.getNextToken();
    146          else {
    147            int locstart = l.startingLoc;
    148            int modifiers = parseModifiers(l);
    149            ModifierPragmaVec modifierPragmas = this.modifierPragmas;
    150
    151              if (l.ttype == TagConstants.TYPEDECLELEMPRAGMA) {
    152                TypeDeclElemPragma pragma = (TypeDeclElemPragma)l.auxVal;
    153                pragma.decorate(modifierPragmas);
    154                    // FIXME - what about modifiers ?
    155                seqTypeDeclElem.addElement( pragma );
    156                l.getNextToken();
    157              } else {
    158                TypeDecl td = parseTypeDeclaration(l, specOnly,modifiers,modifierPragmas,locstart);
    159                if (td != null) seqTypeDecl.addElement( td );
    160              }
    161          }
    162        }
    163        TypeDeclVec elems = TypeDeclVec.popFromStackVector( seqTypeDecl );
    164        TypeDeclElemVec extras = TypeDeclElemVec.popFromStackVector( seqTypeDeclElem);
    165
    166        LexicalPragmaVec lexicalPragmas = l.getLexicalPragmas();
    167
    168        return CompilationUnit.make(pkgName, lexicalPragmas,
    169                                    imports, elems, loc, extras );
    170      }
    171
    172      /** Parse an <TT>ImportDeclaration</TT>.
    173        <PRE>
    174        ImportDeclaration:
    175          import Name ;
    176          import Name . STAR ;
    177        </PRE>
    178       */
    179
    180      //@ requires l != null && l.m_in != null;
    181      //@ ensures \result != null;
    182      protected ImportDecl parseImportDeclaration(Lex l) {
    183        int loc = l.startingLoc;
    184        l.getNextToken();                // swallow import keyword
    185        Name name = parseName(l);
    186        if( l.ttype == TagConstants.SEMICOLON ) {
    187          l.getNextToken();              // swallow semicolon
    188          TypeName typename = TypeName.make( name );
    189          return SingleTypeImportDecl.make( loc, typename );
    190        } else {
    191          expect( l, TagConstants.FIELD );
    192          expect( l, TagConstants.STAR );
    193          expect( l, TagConstants.SEMICOLON );
    194          return OnDemandImportDecl.make( loc, name );
    195        }
    196      }
    197
    198
    199      /**********************************************************************
    200        Parse a <TT>TypeDeclaration</TT> (ie a class or interface declaration).
    201        <PRE>
    202          TypeDeclaration:
    203            ClassDeclaration
    204            InterfaceDeclaration
    205            ;
    206
    207          ClassDeclaration:
    208            TypeDeclElemPragma* Modifiers class Identifier [extends TypeName] [implements TypeNameList]
    209              { TypeDeclElem* }
    210            TypeDeclElemPragma* Modifiers interface Identifier [extends TypeNameList]
    211              { TypeDeclElem* }
    212         </PRE>
    213       */
    214
    215      //@ requires l != null && l.m_in != null;
    216      //@ ensures \result != null;
    217      protected TypeDecl parseTypeDeclaration(Lex l, boolean specOnly) {
    218        int locstart = l.startingLoc;
    219        int modifiers = parseModifiers(l);
    220        ModifierPragmaVec modifierPragmas = this.modifierPragmas;
    221        return parseTypeDeclaration(l,specOnly,modifiers,modifierPragmas,
    222                                            locstart);
    223      }
    224      protected TypeDecl parseTypeDeclaration(Lex l, boolean specOnly,
    225                            int modifiers, ModifierPragmaVec modifierPragmas,
    226                            int loc) {
    227        TypeDecl result =
    228            parseTypeDeclTail(l, specOnly, loc, modifiers, modifierPragmas);
    229        return result;
    230      }
    231
    232      /**********************************************************************
    233        Parse a <TT>TypeDeclTail</TT> (ie a class or interface declaration
    234        starting at the keyword 'class' or 'interface').
    235        <PRE>
    236          TypeDeclTail:
    237            class Identifier [TypeModifierPragma]* [extends TypeName] [implements TypeNameList]
    238              { TypeDeclElem* }
    239            interface Identifier [TypeModifierPragma]* [extends TypeNameList] { TypeDeclElem* }
    240         </PRE> */
    241
    242      protected
    243      TypeDecl parseTypeDeclTail(Lex l, boolean specOnly, int loc,
    244                                 int modifiers, ModifierPragmaVec modifierPragmas){
    245        int keyword = l.ttype;
    246
    247        if( keyword != TagConstants.CLASS && keyword != TagConstants.INTERFACE ) {
    248          if (keyword == TagConstants.EOF) return null;
    249          fail(l.startingLoc, "expected 'class' or 'interface' instead of "
    250                    + TagConstants.toString(keyword));
    251        }
    252
    253        l.getNextToken();              // swallow keyword
    254
    255        int locId = l.startingLoc;
    256        Identifier id = parseIdentifier(l);
    257        TypeModifierPragmaVec tmodifiers = parseTypeModifierPragmas(l);
    258
    259        /* Parse superclass, if any */
    260        TypeName superClass = null;
    261        if( keyword == TagConstants.CLASS && l.ttype == TagConstants.EXTENDS ) {
    262          l.getNextToken();            // swallow "extends" keyword
    263          superClass = parseTypeName(l);
    264        }
    265
    266        /* Parse super interfaces, if any */
    267        TypeNameVec superInterfaces =
    268          parseTypeNames( l, (keyword == TagConstants.CLASS ?
    269                              TagConstants.IMPLEMENTS : TagConstants.EXTENDS ) );
    270
    271        /* Now parse class body */
    272        int locOpenBrace = l.startingLoc;
    273        expect( l, TagConstants.LBRACE );
    274
    275        /* Build up Vec of TypeDeclElems in class or interface */
    276        seqTypeDeclElem.push();
    277        while( l.ttype != TagConstants.RBRACE ) {
    278          parseTypeDeclElemIntoSeqTDE( l, keyword, id, specOnly );
    279        }
    280        TypeDeclElemVec elems =
    281            TypeDeclElemVec.popFromStackVector( seqTypeDeclElem );
    282
    283        int locCloseBrace = l.startingLoc;
    284        expect( l, TagConstants.RBRACE );
    285
    286        TypeDecl result;
    287        if (keyword == TagConstants.CLASS) {
    288          addDefaultConstructor(elems, locOpenBrace, specOnly);
    289          result = ClassDecl.make(modifiers, modifierPragmas, id,
    290                                  superInterfaces, tmodifiers, elems,
    291                                  loc, locId, locOpenBrace, locCloseBrace,
    292                                  superClass);
    293        } else {
    294          result = InterfaceDecl.make(modifiers, modifierPragmas, id,
    295                                      superInterfaces, tmodifiers, elems,
    296                                      loc, locId,
    297                                      locOpenBrace, locCloseBrace );
    298        }
    299        result.specOnly = specOnly;
    300        return result;
    301      }
    302
    303
    304      /** checks for           X TypeModifierPragma* (
    305          in the input stream.
    306          Use this to match the beginning of a constructor or method declration
    307          versus the beginning of a field declaration.
    308      */
    309        //@ requires l != null && l.m_in != null;
    310        private boolean atStartOfConstructorOrMethod(Lex l) {
    311            int i = 1;
    312            while ((l.lookahead(i) == TagConstants.TYPEMODIFIERPRAGMA)) {
    313                i++;
    314            }
    315            return l.lookahead(i) == TagConstants.LPAREN;
    316        }
    317
    318
    319
    320
    321      /** If no constructors are found in "elems", adds a default one to it.
    322        If a default constructor is created, the "loc" and "locId" fields of
    323        the default constructor will be set to "loc". */
    324      void addDefaultConstructor(TypeDeclElemVec elems, int loc, boolean specOnly) {
    325          // Return if a constructor is already present:
    326          for (int i=0; i<elems.size(); i++) {
    327              if (elems.elementAt(i) instanceof ConstructorDecl)
    328                  return;
    329          }
    330
    331          /*
    332           * No constructor found, add one:
    333           *  name() { super(); }
    334           *
    335           * Don't put super constructor invocation in --  it is added by
    336           * the type checker.
    337           */
    338          BlockStmt blk = specOnly ? null :BlockStmt.make(StmtVec.make(), loc, loc);
    339          TypeNameVec raises = TypeNameVec.make();
    340          FormalParaDeclVec formals = FormalParaDeclVec.make();
    341          ConstructorDecl cd
    342              = ConstructorDecl.make(Modifiers.ACC_PUBLIC, null, null,
    343                                     formals, raises, blk, loc, loc, loc,
    344                                     Location.NULL );
    345          cd.implicit = true;
    346          elems.addElement(cd);
    347      }
    348
    349      /** Parse a keyword,
    350          followed by a comma-separated list of <TT>TypeName</TT>s.
    351
    352          Used to parse throws clauses, and super-interface clauses.
    353          <PRE>
    354          TypeNames:
    355             keyword TypeNameList
    356             empty
    357
    358          TypeNameList:
    359            TypeName ( , TypeName )*
    360          </PRE>
    361       */
    362
    363      //@ requires l != null && l.m_in != null;
    364      //@ ensures \result != null;
    365      protected TypeNameVec parseTypeNames(Lex l, int keyword)
    366      {
    367        if( l.ttype != keyword )
    368          return TypeNameVec.make();
    369
    370        /* Have type names */
    371        seqTypeName.push();
    372        do {
    373          // Skip keyword or ',' .
    374          l.getNextToken();
    375          seqTypeName.addElement( parseTypeName(l) );
    376        } while( l.ttype == TagConstants.COMMA );
    377        return TypeNameVec.popFromStackVector( seqTypeName );
    378      }
    379
    380    /************************************************************************
    381
    382    Parse a <TT>TypeDeclElem</TT>, which is either a field, method, or
    383    constructor declaration, a static block, or a TypeDecl [1.1].
    384
    385    <p> A field declaration may define many fields.  Since returning
    386    multiple declared entities is cumbersome, this method simply adds all
    387    the declared entities onto the StackVector seqTypeDeclElem.  The
    388    <TT>keyword</TT> argument is either CLASS or INTERFACE.  The argument
    389    containerId is the name of the enclosing class, which is necessary for
    390    checking constructor declarations.
    391
    392    <PRE>
    393    TypeDeclElem:
    394       FieldDeclaration
    395       MethodDeclaration
    396       ConstructorDeclaration
    397       InitBlock
    398       TypeDeclElemPragma
    399       TypeDeclaration              [1.1]
    400       ;
    401
    402    FieldDeclaration:
    403       Modifiers Type VariableDeclarator (, VariableDeclarator)* ;
    404
    405    MethodDeclaration:
    406       Modifiers Type Identifier FormalParameterList BracketPair*
    407          [throws TypeNameList]
    408          ( ; | Block )
    409
    410    ConstructorDeclaration:
    411       Modifiers Identifier FormalParameterList Block
    412
    413    InitBlock:
    414       Modifiers Block
    415
    416    VariableDeclarator:
    417       Identifier BRACKET_PAIR* [ = VariableInitializer ]
    418
    419    </PRE>
    420
    421    @see javafe.parser.TagConstants
    422
    423    */
    424
    425      protected TypeDeclElem
    426      parseTypeDeclElemIntoSeqTDE(Lex l, int keyword, Identifier containerId,
    427                                       boolean specOnly)
    428      {
    429        int loc = l.startingLoc;
    430        int modifiers = parseModifiers(l);
    431        ModifierPragmaVec modifierPragmas = this.modifierPragmas;
    432        TypeDeclElem result = null;
    433
    434        if( l.ttype == TagConstants.SEMICOLON
    435           && modifiers == Modifiers.NONE
    436           && modifierPragmas == null ) {
    437          // Semicolons are not in JLS,
    438          // but accepted by javac and in many java progs
    439          // so allow them and do nothing
    440          l.getNextToken();
    441          return null;
    442        }
    443        else if( l.ttype == TagConstants.CLASS
    444              || l.ttype == TagConstants.INTERFACE) {
    445          /* Nested class/interface */
    446          TypeDecl nested = parseTypeDeclaration(l, specOnly);
    447          nested.modifiers = modifiers;
    448          nested.pmodifiers = modifierPragmas;
    449          seqTypeDeclElem.addElement(nested);
    450          return nested;
    451        }
    452        else if( l.ttype == TagConstants.LBRACE ) {
    453          /* Initialization block */
    454          if( keyword == TagConstants.INTERFACE )
    455            fail(l.startingLoc,
    456                 "Cannot have initializer blocks in an interface");
    457          if (specOnly)
    458            parseBlock(l, true);
    459          else {
    460            seqTypeDeclElem.addElement( result = InitBlock.make( modifiers, modifierPragmas,
    461                                                        parseBlock(l,false) ) );
    462          }
    463          return result;
    464        }
    465        else if( atStartOfConstructorOrMethod(l) ) {
    466          // Constructor declaration
    467          if( keyword == TagConstants.INTERFACE )
    468            fail(l.startingLoc, "Cannot declare constructors in an interface");
    469          int locId = l.startingLoc;
    470          Identifier id = parseIdentifier(l);
    471          TypeModifierPragmaVec tmodifiers = parseTypeModifierPragmas(l);
    472          if (id != containerId) {
    473              if (containerId.toString().startsWith("$anon_"))
    474                  fail(l.startingLoc,
    475                       "Anonymous classes may not have constructors");
    476              else
    477                  fail(l.startingLoc,
    478                       "Invalid name '"+id+"' for constructor;"
    479                       +" expected '"+containerId+"'");
    480          }
    481
    482          FormalParaDeclVec args = parseFormalParameterList(l);
    483          int locThrowsKeyword;
    484          if (l.ttype == TagConstants.THROWS) {
    485            locThrowsKeyword = l.startingLoc;
    486          } else {
    487            locThrowsKeyword = Location.NULL;
    488          }
    489          TypeNameVec raises = parseTypeNames( l, TagConstants.THROWS );
    490
    491          // allow more modifier pragmas
    492          modifierPragmas = parseMoreModifierPragmas( l, modifierPragmas );
    493          BlockStmt body = null;
    494          int locOpenBrace = Location.NULL;
    495          if ( l.ttype == TagConstants.SEMICOLON ) {
    496              l.getNextToken();   // swallow semicolon
    497          } else {
    498              locOpenBrace = l.startingLoc;
    499              // specOnly means do not keep any bodies of methods/constructors/etc.
    500              body = specOnly ? parseBlock(l, true)
    501                                        : parseConstructorBody(l);
    502
    503          }
    504          seqTypeDeclElem.addElement( result = ConstructorDecl.make( modifiers,
    505                                                            modifierPragmas,
    506                                                            tmodifiers,
    507                                                            args,
    508                                                            raises, body,
    509                                                            locOpenBrace,
    510                                                            loc, locId,
    511                                                            locThrowsKeyword ) );
    512          return result;
    513        }
    514        else if( l.ttype == TagConstants.TYPEDECLELEMPRAGMA ) {
    515          // TypeDeclElemPragma
    516          if( modifiers != Modifiers.NONE)
    517            ErrorSet.error(l.startingLoc,
    518                 "Cannot have modifiers outside of the annotation on a TypeDeclElem pragma");
    519          TypeDeclElemPragma pragma = (TypeDeclElemPragma)l.auxVal;
    520          pragma.decorate(modifierPragmas);
    521          seqTypeDeclElem.addElement( pragma );
    522          l.getNextToken();
    523        }
    524        else if (l.ttype == TagConstants.POSTMODIFIERPRAGMA) {
    525            ErrorSet.error(l.startingLoc,
    526                "Ignoring a modifier pragma that presumably follows a field declaration but is not in the same annotation comment"); // FIXME - can this be fixed?
    527          l.getNextToken();
    528        }
    529        else {
    530          /* Is field or method declaration */
    531          int locType = l.startingLoc;
    532          Type type = parseType(l);
    533          if(  atStartOfConstructorOrMethod(l) ) {
    534            // Method declaration
    535
    536            int locId              = l.startingLoc;
    537            Identifier id          = parseIdentifier(l);
    538            TypeModifierPragmaVec tmodifiers = parseTypeModifierPragmas(l);
    539            FormalParaDeclVec args = parseFormalParameterList(l);
    540            type = parseBracketPairs( l, type );
    541            int locThrowsKeyword;
    542            if (l.ttype == TagConstants.THROWS) {
    543              locThrowsKeyword = l.startingLoc;
    544            } else {
    545              locThrowsKeyword = Location.NULL;
    546            }
    547            TypeNameVec raises     = parseTypeNames(l, TagConstants.THROWS );
    548            int locOpenBrace;
    549            BlockStmt body;
    550
    551            // Allow some more modifier pragmas here
    552            modifierPragmas = parseMoreModifierPragmas( l, modifierPragmas );
    553
    554            if ( l.ttype == TagConstants.SEMICOLON ) {
    555              l.getNextToken();   // swallow semicolon
    556              locOpenBrace = Location.NULL;
    557              body = null;
    558    // FIXME - check that this is specOnly for no body ?
    559            } else {
    560              if( keyword == TagConstants.INTERFACE )
    561                fail(l.startingLoc,
    562                     "Cannot define a method body inside an interface");
    563              locOpenBrace = l.startingLoc;
    564              body = parseBlock(l, specOnly);
    565            }
    566            MethodDecl md = MethodDecl.make(modifiers, modifierPragmas, tmodifiers,
    567                                            args,
    568                                            raises, body, locOpenBrace,
    569                                            loc, locId, locThrowsKeyword,
    570                                            id, type, locType);
    571            seqTypeDeclElem.addElement( md );
    572            return md;
    573
    574          } else {
    575
    576            // Field declaration.
    577
    578            // Have modifiers and type.
    579            // May need to loop over many VariableDeclarators
    580
    581            // make modifierPragmas non-null, so can retroactively extend
    582            if( modifierPragmas == null )
    583              modifierPragmas = ModifierPragmaVec.make();
    584
    585            List fds = new LinkedList(); // a list of all the fds produced here
    586            for(;;) {
    587              int locId     = l.startingLoc;
    588              Identifier id = parseIdentifier(l);
    589              Type vartype = parseBracketPairs(l, type);
    590
    591              VarInit init = null;
    592              int locAssignOp = Location.NULL;
    593              if( l.ttype == TagConstants.ASSIGN ) {
    594                locAssignOp = l.startingLoc;
    595                l.getNextToken();
    596                init = parseVariableInitializer(l, specOnly);
    597              }
    598              FieldDecl fielddecl
    599                = FieldDecl.make(modifiers, modifierPragmas.copy(),
    600                                 id, vartype, locId, init, locAssignOp );
    601              seqTypeDeclElem.addElement( fielddecl );
    602              fds.add(fielddecl);
    603
    604              if(l.ttype == TagConstants.MODIFIERPRAGMA
    605                        || l.ttype == TagConstants.SEMICOLON )
    606              {
    607                // if modifier pragma, retroactively add to modifierPragmas
    608                parseMoreModifierPragmas( l, fielddecl.pmodifiers );
    609
    610                // End of Declaration
    611
    612                // JML added some clauses that can follow type declarations.
    613                // This bit of hackery is to check if there are any such
    614                // and associate them with the correct declaration.  All other
    615                // modifiers precede the declaration with which they are
    616                // associated (or at least precede the terminating semicolon).
    617                l.getNextToken();
    618                while (l.ttype == TagConstants.POSTMODIFIERPRAGMA) {
    619                    Identifier idd = ((javafe.ast.IdPragma)l.auxVal).id();
    620                    Iterator i = fds.iterator();
    621                    while (i.hasNext()) {
    622                        FieldDecl fd = (FieldDecl)i.next();
    623                        if (idd == null || idd == fd.id)
    624                            fd.pmodifiers.addElement((ModifierPragma)l.auxVal);
    625                    }
    626                    l.getNextToken();
    627                }
    628
    629                return fielddecl;
    630              } else {
    631                expect( l, TagConstants.COMMA );
    632                /* And go around loop again */
    633              }
    634            } /* loop thru field declarations */
    635          } /* is field declarations */
    636        } /* field or method declarations */
    637        return null;
    638      } /* parseTypeDeclElemIntoSeqTDE */
    639
    640      /**********************************************************************
    641        Parse a <TT>FormalParameterList</TT>, which includes enclosing parens.
    642        Note: this definition differs from JLS, where it does not include the
    643        parens
    644
    645        <PRE>
    646          FormalParameterList:
    647            LPAREN FormalParameter (, FormalParameter)* RPAREN
    648
    649          FormalParameter:
    650            [Modifiers] Type Identifier BracketPair* ModifierPragma*     [1.1]
    651        <PRE>
    652       */
    653
    654      //@ requires l != null && l.m_in != null;
    655      //@ ensures \result != null;
    656      public FormalParaDeclVec parseFormalParameterList(Lex l)
    657      {
    658        /* Should be on LPAREN */
    659        if( l.ttype != TagConstants.LPAREN )
    660          fail(l.startingLoc, "Expected open paren");
    661        if( l.lookahead(1) == TagConstants.RPAREN ) {
    662          // Empty parameter list
    663          expect( l, TagConstants.LPAREN );
    664          expect( l, TagConstants.RPAREN );
    665          return FormalParaDeclVec.make();
    666        } else {
    667          seqFormalParaDecl.push();
    668          while( l.ttype != TagConstants.RPAREN ) {
    669            l.getNextToken();                // swallow open paren or comma
    670            int modifiers = parseModifiers(l);
    671            ModifierPragmaVec modifierPragmas = this.modifierPragmas;
    672            Type type = parseType(l);
    673            int locId = l.startingLoc;
    674            Identifier id = parseIdentifier(l);
    675            type = parseBracketPairs(l, type);
    676            modifierPragmas = parseMoreModifierPragmas(l, modifierPragmas);
    677            seqFormalParaDecl.addElement( FormalParaDecl.make(modifiers,
    678                                                              modifierPragmas,
    679                                                              id, type, locId ) );
    680            if( l.ttype != TagConstants.RPAREN && l.ttype != TagConstants.COMMA )
    681              fail(l.startingLoc, "Expected comma or close paren");
    682          }
    683          expect( l, TagConstants.RPAREN );
    684          return FormalParaDeclVec.popFromStackVector( seqFormalParaDecl );
    685        }
    686      }
    687    }