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 }