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, /*@non_null*/Identifier containerId,
427                                       boolean specOnly)                    
428      {
429        int loc = l.startingLoc;
430        int modifiers = parseModifiers(l);
431        //alx: dw clone the array to use it later
432        int[] localUniverseArray = null;
433        if (useUniverses)
434            localUniverseArray = (int[])this.universeArray.clone();
435        //alx-end
436    
437        ModifierPragmaVec modifierPragmas = this.modifierPragmas;
438        TypeDeclElem result = null;
439    
440        if( l.ttype == TagConstants.SEMICOLON 
441           && modifiers == Modifiers.NONE
442           && modifierPragmas == null ) {
443          // Semicolons are not in JLS, 
444          // but accepted by javac and in many java progs
445          // so allow them and do nothing
446          l.getNextToken();
447          return null;
448        } 
449        else if( l.ttype == TagConstants.CLASS 
450              || l.ttype == TagConstants.INTERFACE) {
451          /* Nested class/interface */
452          TypeDecl nested = parseTypeDeclaration(l, specOnly);
453          nested.modifiers = modifiers;
454          nested.pmodifiers = modifierPragmas;
455          seqTypeDeclElem.addElement(nested);
456          return nested;
457        } 
458        else if( l.ttype == TagConstants.LBRACE ) {
459          /* Initialization block */
460          if( keyword == TagConstants.INTERFACE ) 
461            fail(l.startingLoc, 
462                 "Cannot have initializer blocks in an interface");
463          if (specOnly)
464            parseBlock(l, true);
465          else {
466            seqTypeDeclElem.addElement( result = InitBlock.make( modifiers, modifierPragmas,
467                                                        parseBlock(l,false) ) );
468          }
469          return result;
470        } 
471        else if( atStartOfConstructorOrMethod(l) ) {
472          // Constructor declaration 
473          if( keyword == TagConstants.INTERFACE ) 
474            fail(l.startingLoc, "Cannot declare constructors in an interface");
475          int locId = l.startingLoc;
476          Identifier id = parseIdentifier(l);
477          TypeModifierPragmaVec tmodifiers = parseTypeModifierPragmas(l);
478          if (id != containerId) {
479              if (containerId.toString().startsWith("$anon_"))
480                  fail(l.startingLoc,
481                       "Anonymous classes may not have constructors");
482              else
483                  fail(l.startingLoc, 
484                       "Invalid name '"+id+"' for constructor;"
485                       +" expected '"+containerId+"'");
486          }
487    
488          FormalParaDeclVec args = parseFormalParameterList(l);
489          int locThrowsKeyword;
490          if (l.ttype == TagConstants.THROWS) {
491            locThrowsKeyword = l.startingLoc;
492          } else {
493            locThrowsKeyword = Location.NULL;
494          }
495          TypeNameVec raises = parseTypeNames( l, TagConstants.THROWS );
496    
497          // allow more modifier pragmas
498          modifierPragmas = parseMoreModifierPragmas( l, modifierPragmas );
499          BlockStmt body = null;
500          int locOpenBrace = Location.NULL;
501          if ( l.ttype == TagConstants.SEMICOLON ) {
502              l.getNextToken();   // swallow semicolon
503          } else {
504              locOpenBrace = l.startingLoc;
505              // specOnly means do not keep any bodies of methods/constructors/etc.
506              body = specOnly ? parseBlock(l, true)
507                                        : parseConstructorBody(l);
508    
509          }
510          seqTypeDeclElem.addElement( result = ConstructorDecl.make( modifiers,
511                                                            modifierPragmas,
512                                                            tmodifiers,
513                                                            args, 
514                                                            raises, body,
515                                                            locOpenBrace,
516                                                            loc, locId, 
517                                                            locThrowsKeyword ) );
518          return result;
519        } 
520        else if( l.ttype == TagConstants.TYPEDECLELEMPRAGMA ) {
521          // TypeDeclElemPragma
522          if( modifiers != Modifiers.NONE)
523            ErrorSet.error(l.startingLoc, 
524                 "Cannot have modifiers outside of the annotation on a TypeDeclElem pragma");
525          TypeDeclElemPragma pragma = (TypeDeclElemPragma)l.auxVal;
526          pragma.decorate(modifierPragmas);
527          seqTypeDeclElem.addElement( pragma );
528          l.getNextToken();
529        }
530        else if (l.ttype == TagConstants.POSTMODIFIERPRAGMA) {
531            ErrorSet.error(l.startingLoc,
532                "Ignoring a modifier pragma that presumably follows a field declaration but is not in the same annotation comment"); // FIXME - can this be fixed?
533          l.getNextToken();
534        }
535        else {
536          /* Is field or method declaration */
537          int locType = l.startingLoc;
538          Type type = parseType(l);
539          if(  atStartOfConstructorOrMethod(l) ) {
540            // Method declaration 
541            
542            int locId              = l.startingLoc;
543            Identifier id          = parseIdentifier(l);
544            TypeModifierPragmaVec tmodifiers = parseTypeModifierPragmas(l);
545            FormalParaDeclVec args = parseFormalParameterList(l);
546            type = parseBracketPairs( l, type );
547            int locThrowsKeyword;
548            if (l.ttype == TagConstants.THROWS) {
549              locThrowsKeyword = l.startingLoc;
550            } else {
551              locThrowsKeyword = Location.NULL;
552            }
553            TypeNameVec raises     = parseTypeNames(l, TagConstants.THROWS );
554            int locOpenBrace;
555            BlockStmt body;
556    
557            // Allow some more modifier pragmas here
558            modifierPragmas = parseMoreModifierPragmas( l, modifierPragmas );
559    
560            if ( l.ttype == TagConstants.SEMICOLON ) {
561              l.getNextToken();   // swallow semicolon
562              locOpenBrace = Location.NULL;
563              body = null;
564    // FIXME - check that this is specOnly for no body ?
565            } else {
566              if( keyword == TagConstants.INTERFACE ) 
567                fail(l.startingLoc, 
568                     "Cannot define a method body inside an interface");
569              locOpenBrace = l.startingLoc;
570              body = parseBlock(l, specOnly);
571            }
572            MethodDecl md = MethodDecl.make(modifiers, modifierPragmas, tmodifiers,
573                                            args, 
574                                            raises, body, locOpenBrace,
575                                            loc, locId, locThrowsKeyword,
576                                            id, type, locType);
577            //alx: dw save universe return type to method declaration node
578            if (useUniverses)
579                    setUniverse(md,localUniverseArray,type,locType);
580            //alx-end
581    
582            seqTypeDeclElem.addElement( md );
583            return md;
584    
585          } else {
586    
587            // Field declaration. 
588            
589            // Have modifiers and type. 
590            // May need to loop over many VariableDeclarators 
591    
592            // make modifierPragmas non-null, so can retroactively extend
593            if( modifierPragmas == null )
594              modifierPragmas = ModifierPragmaVec.make();
595    
596            List fds = new LinkedList(); // a list of all the fds produced here
597            for(;;) {
598              int locId     = l.startingLoc;
599              Identifier id = parseIdentifier(l);
600              Type vartype = parseBracketPairs(l, type);
601    
602              VarInit init = null;
603              int locAssignOp = Location.NULL;
604              if( l.ttype == TagConstants.ASSIGN ) {
605                locAssignOp = l.startingLoc;
606                l.getNextToken();
607                init = parseVariableInitializer(l, specOnly);
608              }
609              FieldDecl fielddecl
610                = FieldDecl.make(modifiers, modifierPragmas.copy(), 
611                                 id, vartype, locId, init, locAssignOp );
612              //alx: dw set universes of field decls
613              if (useUniverses)
614                    setUniverse(fielddecl,localUniverseArray);
615              //alx-end
616    
617              seqTypeDeclElem.addElement( fielddecl );
618              fds.add(fielddecl);
619    
620              if(l.ttype == TagConstants.MODIFIERPRAGMA
621                        || l.ttype == TagConstants.SEMICOLON ) 
622              {
623                // if modifier pragma, retroactively add to modifierPragmas
624                parseMoreModifierPragmas( l, fielddecl.pmodifiers );
625    
626                // End of Declaration 
627    
628                // JML added some clauses that can follow type declarations.
629                // This bit of hackery is to check if there are any such
630                // and associate them with the correct declaration.  All other
631                // modifiers precede the declaration with which they are 
632                // associated (or at least precede the terminating semicolon).
633                l.getNextToken();
634                while (l.ttype == TagConstants.POSTMODIFIERPRAGMA) {
635                    Identifier idd = ((javafe.ast.IdPragma)l.auxVal).id();
636                    Iterator i = fds.iterator();
637                    while (i.hasNext()) {
638                        FieldDecl fd = (FieldDecl)i.next();
639                        if (idd == null || idd == fd.id)
640                            fd.pmodifiers.addElement((ModifierPragma)l.auxVal);
641                    }
642                    l.getNextToken();
643                }
644    
645                return fielddecl;
646              } else {
647                expect( l, TagConstants.COMMA );
648                /* And go around loop again */
649              }
650            } /* loop thru field declarations */
651          } /* is field declarations */
652        } /* field or method declarations */
653        return null;
654      } /* parseTypeDeclElemIntoSeqTDE */
655    
656      /**********************************************************************
657        Parse a <TT>FormalParameterList</TT>, which includes enclosing parens.
658        Note: this definition differs from JLS, where it does not include the
659        parens
660    
661        <PRE>
662          FormalParameterList:
663            LPAREN FormalParameter (, FormalParameter)* RPAREN
664    
665          FormalParameter:
666            [Modifiers] Type Identifier BracketPair* ModifierPragma*     [1.1]
667        <PRE>       
668       */
669    
670      //@ requires l != null && l.m_in != null;
671      //@ ensures \result != null;
672      public FormalParaDeclVec parseFormalParameterList(Lex l) 
673      {
674        /* Should be on LPAREN */
675        if( l.ttype != TagConstants.LPAREN ) 
676          fail(l.startingLoc, "Expected open paren");
677        if( l.lookahead(1) == TagConstants.RPAREN ) {
678          // Empty parameter list
679          expect( l, TagConstants.LPAREN );
680          expect( l, TagConstants.RPAREN );
681          return FormalParaDeclVec.make();
682        } else {
683          seqFormalParaDecl.push();
684          while( l.ttype != TagConstants.RPAREN ) {
685            l.getNextToken();                // swallow open paren or comma
686            int modifiers = parseModifiers(l);
687            //alx: dw save array to use it later
688            int[] localUniverseArray = null;
689            if (useUniverses)
690                    localUniverseArray = (int[]) this.universeArray.clone();
691            //alx-end
692    
693            ModifierPragmaVec modifierPragmas = this.modifierPragmas;
694            Type type = parseType(l);
695            int locId = l.startingLoc;
696            Identifier id = parseIdentifier(l);
697            type = parseBracketPairs(l, type);
698            modifierPragmas = parseMoreModifierPragmas(l, modifierPragmas);
699            //alx: dw save array to the var decl node and add the node to the 
700            //        vector
701            if (useUniverses) seqFormalParaDecl.addElement( 
702                                 setUniverse(FormalParaDecl.make(modifiers, 
703                                                                 modifierPragmas, 
704                                                                 id, 
705                                                                 type, 
706                                                                 locId ),
707                                 localUniverseArray) );
708            else
709            //alx-end
710            seqFormalParaDecl.addElement( FormalParaDecl.make(modifiers,
711                                                              modifierPragmas, 
712                                                              id, type, locId ) );
713            if( l.ttype != TagConstants.RPAREN && l.ttype != TagConstants.COMMA )
714              fail(l.startingLoc, "Expected comma or close paren");
715          }
716          expect( l, TagConstants.RPAREN );
717          return FormalParaDeclVec.popFromStackVector( seqFormalParaDecl );
718        }
719      }
720    }