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 }