1/* 2 * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25/* 26 * COMPONENT_NAME: idl.parser 27 * 28 * ORIGINS: 27 29 * 30 * Licensed Materials - Property of IBM 31 * 5639-D57 (C) COPYRIGHT International Business Machines Corp. 1997, 1999 32 * RMI-IIOP v1.0 33 * 34 */ 35 36package com.sun.tools.corba.se.idl; 37 38// NOTES: 39// -F46082.51<daz> Remove -stateful feature. 40// -D52042<daz> Allow floating-point constants to be initialized with 41// integral as well as floating-point literals. No other variations allowed. 42// -D58058<daz> Set index array type to long rather than array element type. 43// -D56351<daz> Update computation of RepositoryIDs to CORBA 2.3 (see spec.). 44// -D57110<daz> Provide method() to set/clear ability for scoped names to 45// resolve to modules. Allows rep. ids to be assigned to modules. 46// -D46094<daz> Prohibit exceptions from appearing wihtin structs, unions, exceptions. 47// -D46094<daz> Prohibit attributes from appearing as operation parameter types, 48// operation return types, attribute types. 49// -D59067<daz> Prohibit nested value boxes. 50// -D59166<daz> Prohibit collisions between keywords and non-escaped identifiers. 51// -D59809<daz> At Pigeonhole(), add map short name of CORBA types to long name 52// (e.g., CORBA/StringValue --> org/omg/CORBA/StringValue), which allows fully- 53// qualified CORBA type names to resolve successfully. 54// -F60858.1<daz> Support "-corba" option, level <= 2.2: issue warning for 55// keyowrd collisions; 56// -D60942<daz> Prohibit operations from appearing within parameter types. 57// -D61643<daz> Repair pigeonhole() to correctly filter bad RepIDs. 58// -D62023<daz> Support -noWarn option; Issue warnings when tokens are 59// deprecated keywords or keywords in greater release version. 60// -D61919<daz> Emit entries for modules originally opened in #include files 61// appearing at global scope and then reopened in the main IDL file. Only 62// types appearing in the main IDL source will be emitted. 63 64import java.io.EOFException; 65import java.io.IOException; 66 67import java.util.Enumeration; 68import java.util.Hashtable; 69import java.util.Stack; 70import java.util.Vector; 71import java.util.List ; 72import java.util.ArrayList ; 73import java.util.Iterator ; 74 75import java.math.BigInteger; 76 77import com.sun.tools.corba.se.idl.constExpr.*; 78 79/** 80 * 81 **/ 82class Parser 83{ 84 /** 85 * 86 **/ 87 Parser (Preprocessor preprocessor, Arguments arguments, Hashtable overrides, 88 Hashtable symtab, SymtabFactory stFac, ExprFactory exprFac, String [] genKeywords) 89 { 90 this.arguments = arguments; 91 noWarn = arguments.noWarn; // <d62023> 92 corbaLevel = arguments.corbaLevel; // <f60858.1> 93 paths = arguments.includePaths; 94 symbols = arguments.definedSymbols; 95 verbose = arguments.verbose; 96 emitAll = arguments.emitAll; 97 // <f46082.46.01> 98 cppModule = arguments.cppModule; 99 // <f46082.51> Remove -stateful feature. 100 //parseStateful = arguments.parseStateful; 101 overrideNames = (overrides == null) ? new Hashtable () : overrides; 102 symbolTable = (symtab == null) ? new Hashtable () : symtab; 103 keywords = (genKeywords == null) ? new String [0] : genKeywords; 104 stFactory = stFac; 105 exprFactory = exprFac; 106 currentModule = topLevelModule = new ModuleEntry (); 107 prep = preprocessor; 108 repIDStack.push (new IDLID ()); 109 addPrimEntries (); 110 } // ctor 111 112 /** 113 * 114 **/ 115 void parse (String file) throws IOException 116 { 117 IncludeEntry fileEntry = stFactory.includeEntry (); 118 fileEntry.name ('"' + file + '"'); 119 try 120 { 121 // Set absolute file path 122 fileEntry.absFilename (Util.getAbsolutePath (file, paths)); 123 } 124 catch (IOException ioe) 125 {} 126 127 // <f46082.51> Remove -stateful feature. 128 //scanner = new Scanner (fileEntry, keywords, verbose, parseStateful, emitAll); 129 // <f60585.1> Support "-corba [level]" option. 130 //scanner = new Scanner (fileEntry, keywords, verbose, emitAll); 131 scanner = new Scanner (fileEntry, keywords, verbose, emitAll, corbaLevel, 132 arguments.scannerDebugFlag ); 133 topLevelModule.sourceFile (fileEntry); 134 135 // Prime the pump... 136 // Match handles preprocessor directives, so use match to 137 // call scanner.getToken just in case the first token is 138 // such a directive. But match depends on the token 139 // already having a value, so fudge something. 140 token = new Token (0); 141 tokenHistory.insert (token); // Initialize look back buffer <26jul1997daz>. 142 try 143 { 144 match (0); 145 if (token.equals (Token.EOF)) 146 ParseException.nothing (file); 147 else 148 specification (topLevelModule); 149 } 150 catch (ParseException exception) // Match MIGHT throw this 151 { 152 // It has already been reported, just end. 153 } 154 catch (EOFException exception) // skipToSemicolon MIGHT throw this 155 { 156 // It has already been reported, just end. 157 } 158 } // parse 159 160 /** 161 * 162 **/ 163 private void addPrimEntries () 164 { 165 symbolTable.put ("short", stFactory.primitiveEntry ("short")); 166 symbolTable.put ("long", stFactory.primitiveEntry ("long")); 167 symbolTable.put ("long long", stFactory.primitiveEntry ("long long")); 168 symbolTable.put ("unsigned short", stFactory.primitiveEntry ("unsigned short")); 169 symbolTable.put ("unsigned long", stFactory.primitiveEntry ("unsigned long")); 170 symbolTable.put ("unsigned long long", stFactory.primitiveEntry ("unsigned long long")); 171 symbolTable.put ("char", stFactory.primitiveEntry ("char")); 172 symbolTable.put ("wchar", stFactory.primitiveEntry ("wchar")); 173 symbolTable.put ("float", stFactory.primitiveEntry ("float")); 174 //Support fixed type: symbolTable.put ("fixed", stFactory.primitiveEntry ("fixed")); 175 symbolTable.put ("double", stFactory.primitiveEntry ("double")); 176 symbolTable.put ("boolean", stFactory.primitiveEntry ("boolean")); 177 symbolTable.put ("octet", stFactory.primitiveEntry ("octet")); 178 symbolTable.put ("any", stFactory.primitiveEntry ("any")); 179 180 InterfaceEntry object = stFactory.interfaceEntry(); 181 object.name ("Object"); 182 symbolTable.put ("Object", object); 183 184 ValueEntry valueBase = stFactory.valueEntry(); 185 valueBase.name ("ValueBase"); 186 symbolTable.put ("ValueBase", valueBase); 187 188 // put these same entries in the lowercase symbol table 189 lcSymbolTable.put ("short", stFactory.primitiveEntry ("short")); 190 lcSymbolTable.put ("long", stFactory.primitiveEntry ("long")); 191 lcSymbolTable.put ("long long", stFactory.primitiveEntry ("long long")); 192 lcSymbolTable.put ("unsigned short", stFactory.primitiveEntry ("unsigned short")); 193 lcSymbolTable.put ("unsigned long", stFactory.primitiveEntry ("unsigned long")); 194 lcSymbolTable.put ("unsigned long long", stFactory.primitiveEntry ("unsigned long long")); 195 lcSymbolTable.put ("char", stFactory.primitiveEntry ("char")); 196 lcSymbolTable.put ("wchar", stFactory.primitiveEntry ("wchar")); 197 lcSymbolTable.put ("float", stFactory.primitiveEntry ("float")); 198 // Support fixed type: lcSymbolTable.put ("fixed", stFactory.primitiveEntry ("fixed")); 199 lcSymbolTable.put ("double", stFactory.primitiveEntry ("double")); 200 lcSymbolTable.put ("boolean", stFactory.primitiveEntry ("boolean")); 201 lcSymbolTable.put ("octet", stFactory.primitiveEntry ("octet")); 202 lcSymbolTable.put ("any", stFactory.primitiveEntry ("any")); 203 lcSymbolTable.put ("object", object); 204 lcSymbolTable.put ("valuebase", valueBase); 205 } // addPrimEntries 206 207 /** 208 * 209 **/ 210 private void specification (ModuleEntry entry) throws IOException 211 { 212 while (!token.equals (Token.EOF)) 213 { 214 definition (entry); 215 addToEmitList (entry); 216 } 217 } // specification 218 219 // ModuleEntry is the topLevelModule; add its contained types to the emit list. 220 /** 221 * 222 **/ 223 private void addToEmitList (ModuleEntry entry) 224 { 225 for (Enumeration e = entry.contained ().elements (); e.hasMoreElements();) 226 { 227 SymtabEntry emitEntry = (SymtabEntry)e.nextElement (); 228 if (emitEntry.emit ()) 229 { 230 emitList.addElement (emitEntry); 231 232 // <d61919> I think the absence of the following statement was an 233 // oversight. If module X.Y.Z first appears in an include file, then is 234 // reopened in the main IDL source, this statement guarantees that X.Y.Z 235 // definitions within the main IDL source are emitted. 236 ///--------------------------------------------------------------------- 237 // If any of this module's elements should be emitted, add 238 // this module to the emit list. 239 if (emitEntry instanceof ModuleEntry) 240 checkContained ((ModuleEntry)emitEntry); 241 if (emitEntry instanceof IncludeEntry) 242 { 243 includes.addElement (emitEntry.name ()); 244 includeEntries.addElement (emitEntry); 245 } 246 } 247 else 248 // If any of this module's elements should be emitted, add 249 // this module to the emit list. 250 if (emitEntry instanceof ModuleEntry) 251 checkContained ((ModuleEntry)emitEntry); 252 } 253 entry.contained ().removeAllElements (); 254 } // addToEmitList 255 256 /** 257 * 258 **/ 259 private void checkContained (ModuleEntry entry) 260 { 261 // If any of this module's elements is to be emitted, 262 // then add the module to the emit list. 263 for (Enumeration e = entry.contained ().elements (); e.hasMoreElements ();) 264 { 265 SymtabEntry contained = (SymtabEntry)e.nextElement (); 266 if (contained instanceof ModuleEntry) 267 checkContained ((ModuleEntry)contained); 268 if (contained.emit ()) 269 { 270 if (!emitList.contains (entry)) 271 emitList.addElement (entry); 272 entry.emit (true); 273 break; 274 } 275 } 276 } // checkContained 277 278 /** 279 * 280 **/ 281 private void definition (ModuleEntry entry) throws IOException 282 { 283 try 284 { 285 switch (token.type) 286 { 287 case Token.Typedef: 288 case Token.Struct: 289 case Token.Union: 290 case Token.Enum: 291 typeDcl (entry); 292 break; 293 case Token.Const: 294 constDcl (entry); 295 break; 296 case Token.Native: 297 nativeDcl (entry); 298 break; 299 case Token.Exception: 300 exceptDcl (entry); 301 break; 302 case Token.Interface: 303 interfaceProd (entry, InterfaceEntry.NORMAL); 304 break; 305 case Token.Local: 306 match( Token.Local ) ; 307 if (token.type == Token.Interface) 308 interfaceProd( entry, InterfaceEntry.LOCAL ) ; 309 else 310 throw ParseException.syntaxError( scanner, new int[] { 311 Token.Interface }, token.type ) ; 312 break ; 313 case Token.Module: 314 module (entry); 315 break; 316 case Token.Abstract: 317 match (Token.Abstract); 318 if (token.type == Token.Interface) 319 interfaceProd (entry, InterfaceEntry.ABSTRACT); 320 else if (token.type == Token.Valuetype) 321 valueProd (entry, true); 322 else 323 throw ParseException.syntaxError (scanner, new int[] { 324 Token.Interface, Token.Valuetype }, token.type); 325 break; 326 case Token.Custom: 327 case Token.Valuetype: 328 valueProd (entry, false); 329 break; 330 default: 331 throw ParseException.syntaxError (scanner, new int[] { 332 Token.Typedef, Token.Struct, Token.Union, Token.Enum, 333 Token.Const, Token.Exception, Token.Interface, Token.Valuetype, 334 Token.Module }, token.type); 335 } 336 match (Token.Semicolon); 337 } 338 catch (ParseException e) 339 { 340 skipToSemicolon (); 341 } 342 } // definition 343 344 /** 345 * 346 **/ 347 private void module (ModuleEntry entry) throws IOException, ParseException 348 { 349 match (Token.Module); 350 repIDStack.push (((IDLID)repIDStack.peek ()).clone ()); 351 ModuleEntry newEntry = newModule (entry); 352 ((IDLID)repIDStack.peek ()).appendToName (newEntry.name ()); 353 // comment must immediately precede "module" keyword 354 newEntry.comment (tokenHistory.lookBack (1).comment); 355 currentModule = newEntry; 356 match (Token.Identifier); 357 prep.openScope (newEntry); 358 match (Token.LeftBrace); 359 definition (newEntry); 360 while (!token.equals (Token.EOF) && !token.equals (Token.RightBrace)) 361 definition (newEntry); 362 prep.closeScope (newEntry); 363 match (Token.RightBrace); 364 currentModule = entry; 365 repIDStack.pop (); 366 } // module 367 368 /** 369 * 370 **/ 371 private void interfaceProd (ModuleEntry entry, int interfaceType) 372 throws IOException, ParseException 373 { 374 match (Token.Interface); 375 String name = token.name; 376 match (Token.Identifier); 377 interface2 (entry, name, interfaceType); 378 } // interfaceProd 379 380 /** 381 * 382 **/ 383 private void interface2 (ModuleEntry module, String name, int interfaceType) 384 throws IOException, ParseException 385 { 386 if (token.type == Token.Colon || token.type == Token.LeftBrace) { 387 repIDStack.push (((IDLID)repIDStack.peek ()).clone ()); 388 InterfaceEntry entry = stFactory.interfaceEntry (module, 389 (IDLID)repIDStack.peek ()); 390 entry.sourceFile (scanner.fileEntry ()); 391 entry.name (name); 392 entry.setInterfaceType(interfaceType); 393 // Comment must immediately precede "[local | abstract] interface" keyword 394 entry.comment (tokenHistory.lookBack ( 395 entry.getInterfaceType() == InterfaceEntry.NORMAL ? 2 : 3).comment); 396 397 if (!ForwardEntry.replaceForwardDecl (entry)) 398 ParseException.badAbstract (scanner, entry.fullName ()); 399 pigeonhole (module, entry); 400 ((IDLID)repIDStack.peek ()).appendToName (name); 401 currentModule = entry; 402 interfaceDcl (entry); 403 currentModule = module; 404 repIDStack.pop (); 405 } else { // This is a forward declaration 406 ForwardEntry entry = stFactory.forwardEntry (module, (IDLID)repIDStack.peek ()); 407 entry.sourceFile (scanner.fileEntry ()); 408 entry.name (name); 409 entry.setInterfaceType(interfaceType); 410 // comment must immediately precede "interface" keyword. 411 entry.comment (tokenHistory.lookBack ( 412 entry.getInterfaceType() == InterfaceEntry.NORMAL ? 2 : 3).comment); 413 pigeonhole (module, entry); 414 } 415 } // interface2 416 417 /** 418 * 419 **/ 420 private void interfaceDcl (InterfaceEntry entry) throws IOException, ParseException 421 { 422 if (token.type != Token.LeftBrace) 423 inheritanceSpec (entry); 424 else if (!entry.isAbstract ()) { 425 SymtabEntry objectEntry = qualifiedEntry ("Object"); 426 SymtabEntry realOEntry = typeOf (objectEntry); 427 if (objectEntry == null) 428 ; // qualifiedEntry already generated an error message 429 else if (!isInterface(realOEntry)) 430 ParseException.wrongType (scanner, overrideName ("Object"), 431 "interface", objectEntry.typeName ()); 432 else 433 entry.derivedFromAddElement (realOEntry, scanner); 434 } 435 436 prep.openScope (entry); 437 match (Token.LeftBrace); 438 while (token.type != Token.RightBrace) 439 export (entry); 440 prep.closeScope (entry); 441 match (Token.RightBrace); 442 } // interfaceDcl 443 444 /** 445 * 446 **/ 447 private void export (InterfaceEntry entry) throws IOException 448 { 449 try 450 { 451 switch (token.type) 452 { 453 case Token.Typedef: 454 case Token.Struct: 455 case Token.Union: 456 case Token.Enum: 457 typeDcl (entry); 458 break; 459 case Token.Const: 460 constDcl (entry); 461 break; 462 case Token.Native: 463 nativeDcl (entry); 464 break; 465 case Token.Exception: 466 exceptDcl (entry); 467 break; 468 case Token.Readonly: 469 case Token.Attribute: 470 attrDcl (entry); 471 break; 472 case Token.Oneway: 473 case Token.Float: 474 case Token.Double: 475 case Token.Long: 476 case Token.Short: 477 case Token.Unsigned: 478 case Token.Char: 479 case Token.Wchar: 480 case Token.Boolean: 481 case Token.Octet: 482 case Token.Any: 483 case Token.String: 484 case Token.Wstring: 485 case Token.Identifier: 486 case Token.Object: 487 // <f46082.40> Value base type. 488 case Token.ValueBase: 489 case Token.DoubleColon: 490 case Token.Void: 491 opDcl (entry); 492 break; 493 // <f46082.51> Remove -stateful feature. 494 //case Token.State: if (parseStateful) { 495 // stateDef (entry); 496 // break; } 497 default: 498 throw ParseException.syntaxError(scanner, new int [] { 499 Token.Typedef, Token.Struct, Token.Union, Token.Enum, 500 Token.Const, Token.Exception, Token.Readonly, Token.Attribute, 501 Token.Oneway, Token.Float, Token.Double, Token.Long, 502 Token.Short, Token.Unsigned, Token.Char, Token.Wchar, 503 Token.Boolean, Token.Octet, Token.Any, Token.String, 504 Token.Wstring, Token.Identifier, Token.DoubleColon, Token.Void, 505 Token.ValueBase }, token.type); 506 } 507 match (Token.Semicolon); 508 } 509 catch (ParseException exception) 510 { 511 skipToSemicolon (); 512 } 513 } // export 514 515 private void inheritanceSpec (InterfaceEntry entry) throws IOException, ParseException 516 { 517 for (match (Token.Colon); ; match (Token.Comma)) { 518 SymtabEntry parent = scopedName (entry.container (), 519 stFactory.interfaceEntry ()); 520 SymtabEntry realParent = typeOf (parent); 521 522 if (isInterfaceOnly (realParent)) { 523 boolean isInterface = (realParent instanceof InterfaceEntry); 524 if (entry.derivedFrom ().contains (realParent)) 525 ParseException.alreadyDerived (scanner, realParent.fullName (), entry.fullName ()); 526 else if (!entry.isAbstract () || 527 (((InterfaceType)realParent).getInterfaceType() == InterfaceType.ABSTRACT)) 528 entry.derivedFromAddElement (realParent, scanner); 529 else 530 ParseException.nonAbstractParent (scanner, entry.fullName (), parent.fullName ()); 531 } else if (isForward( realParent )) { 532 ParseException.illegalForwardInheritance( scanner, 533 entry.fullName(), parent.fullName() ) ; 534 } else 535 ParseException.wrongType (scanner, parent.fullName (), "interface", entryName (parent)); 536 537 if ((parent instanceof InterfaceEntry) && (((InterfaceEntry)parent).state () != null)) 538 if (entry.state () == null) 539 entry.initState (); 540 else 541 throw ParseException.badState (scanner, entry.fullName ()); 542 543 if (token.type != Token.Comma) 544 break; 545 } 546 } // inheritanceSpec 547 548 // <57110> Member _moduleIsLegalType may be set by any feature to allow 549 // method scopedName() and any of its helper methods -- qualifiedName(), 550 // partlyQualifiedName(), and unqualifiedName() -- to return a ModuleEntry 551 // rather than a parse error in the event a name resolves to a module. The 552 // flag must be cleared (set to false) to resume normal parsing behavior. 553 // 554 // Currently, this is used only when preprocessing the ID pragma directive. 555 556 private boolean _isModuleLegalType = false; 557 558 /** 559 * 560 **/ 561 public boolean isModuleLegalType () 562 { 563 return _isModuleLegalType; 564 }; // moduleIsLegaType 565 566 /** 567 * 568 **/ 569 public void isModuleLegalType (boolean b) 570 { 571 _isModuleLegalType = b; 572 }; // moduleIsLegalType 573 574 /** 575 * 576 **/ 577 SymtabEntry scopedName (SymtabEntry container, 578 SymtabEntry expected) throws IOException, ParseException 579 { 580 return scopedName( container, expected, true ) ; 581 } 582 583 SymtabEntry scopedName (SymtabEntry container, SymtabEntry expected, 584 boolean mustBeReferencable ) throws IOException, ParseException 585 { 586 boolean globalScope = false; 587 boolean partialScope = false; 588 String name = null; 589 if (token.type == Token.DoubleColon) 590 globalScope = true; 591 else 592 { 593 if (token.type == Token.Object) 594 { 595 name = "Object"; 596 match (Token.Object); 597 } 598 else if (token.type == Token.ValueBase) // <f46082.40> 599 { 600 name = "ValueBase"; 601 match (Token.ValueBase); 602 } 603 else 604 { 605 name = token.name; 606 match (Token.Identifier); 607 } 608 } 609 while (token.type == Token.DoubleColon) 610 { 611 match (Token.DoubleColon); 612 partialScope = true; 613 if (name != null) 614 name += '/' + token.name; 615 else name = token.name; 616 match (Token.Identifier); 617 } 618 SymtabEntry entry = null; 619 if (globalScope) 620 entry = qualifiedEntry (name); 621 else if (partialScope) 622 entry = partlyQualifiedEntry (name, container); 623 else 624 entry = unqualifiedEntry (name, container); 625 626 if (entry == null) 627 // Make the entry the expected entry. The generators will 628 // not be called now, since a semantic exception ocurred, but 629 // the parse has to finish and something valid has to be 630 // returned. 631 (entry = expected).name (name); 632 else if (!entry.isReferencable() && mustBeReferencable) 633 throw ParseException.illegalIncompleteTypeReference( scanner, name ) ; 634 635 return entry; 636 } // scopedName 637 638 private void valueProd (ModuleEntry entry, boolean isAbstract) throws IOException, ParseException 639 { 640 boolean isCustom = (token.type == Token.Custom); 641 if (isCustom) 642 match (Token.Custom); 643 match (Token.Valuetype); 644 String name = token.name; 645 match (Token.Identifier); 646 647 switch (token.type) 648 { 649 case Token.LeftBrace: 650 case Token.Colon: 651 case Token.Supports: 652 value2 (entry, name, isAbstract, isCustom); 653 return; 654 case Token.Semicolon: 655 if (isCustom) 656 break; 657 valueForwardDcl (entry, name, isAbstract); 658 return; 659 } 660 if (isCustom) 661 throw ParseException.badCustom (scanner); 662 if (isAbstract) 663 throw ParseException.abstractValueBox (scanner); 664 valueBox (entry, name); 665 } // valueProd 666 667 /** 668 * 669 **/ 670 private void value2 (ModuleEntry module, String name, boolean isAbstract, 671 boolean isCustom) throws IOException, ParseException 672 { 673 repIDStack.push (((IDLID)repIDStack.peek ()).clone ()); 674 // The 'actual' repository ID will be calculated at the end of the 675 // parsing phase, since it is based on the entire contents of the 676 // declaration, and needs to have all forward references resolved: 677 ValueEntry entry = stFactory.valueEntry (module, (IDLID)repIDStack.peek ()); 678 entry.sourceFile (scanner.fileEntry ()); 679 entry.name (name); 680 entry.setInterfaceType (isAbstract ? InterfaceType.ABSTRACT : InterfaceType.NORMAL); 681 entry.setCustom (isCustom); 682 // Comment must immediately precede "[abstract | custom] value" keyword 683 entry.comment (tokenHistory.lookBack ((isAbstract || isCustom) ? 3 : 2).comment); 684 // If this value has been forward declared, there are probably 685 // other values which derive from a ForwardValueEntry. Replace 686 // those ForwardValueEntry's with this ValueEntry: 687 if (!ForwardEntry.replaceForwardDecl (entry)) 688 ParseException.badAbstract (scanner, entry.fullName ()); 689 pigeonhole (module, entry); 690 ((IDLID)repIDStack.peek ()).appendToName (name); 691 currentModule = entry; 692 valueDcl (entry); 693 entry.tagMethods (); 694 currentModule = module; 695 repIDStack.pop (); 696 } // value2 697 698 /** 699 * 700 **/ 701 private void valueDcl (ValueEntry entry) throws IOException, ParseException 702 { 703 if (token.type == Token.Colon) 704 valueInheritanceSpec (entry); 705 else if (!entry.isAbstract ()) 706 { 707 SymtabEntry objectEntry = qualifiedEntry ("ValueBase"); 708 SymtabEntry realOEntry = typeOf (objectEntry); 709 if (objectEntry == null) 710 ; // qualifiedEntry already generated an error message 711 else if (!isValue (realOEntry)) 712 ParseException.wrongType (scanner, overrideName ("ValueBase"), "value", objectEntry.typeName ()); 713 else 714 entry.derivedFromAddElement (realOEntry, false, scanner); 715 } 716 if (token.type == Token.Supports) 717 valueSupportsSpec (entry); 718 prep.openScope (entry); 719 match (Token.LeftBrace); 720 while (token.type != Token.RightBrace) 721 { 722 valueElement (entry); 723 } 724 prep.closeScope (entry); 725 match (Token.RightBrace); 726 } // valueDcl 727 728 /** 729 * 730 **/ 731 private void valueInheritanceSpec (ValueEntry entry) throws IOException, ParseException 732 { 733 match (Token.Colon); 734 boolean isTruncatable = (token.type == Token.Truncatable); 735 if (isTruncatable) 736 match (Token.Truncatable); 737 for (; ; match (Token.Comma), isTruncatable = false) { 738 SymtabEntry parent = scopedName (entry.container (), 739 stFactory.valueEntry ()); 740 SymtabEntry realParent = typeOf (parent); 741 if (isValue (realParent) && !(realParent instanceof ValueBoxEntry)) 742 entry.derivedFromAddElement (realParent, isTruncatable, 743 scanner); 744 else if (isForward(realParent)) 745 ParseException.illegalForwardInheritance( scanner, 746 entry.fullName(), parent.fullName() ) ; 747 else 748 ParseException.wrongType (scanner, 749 parent.fullName (), "value", entryName (parent)); 750 if (token.type != Token.Comma) 751 break; 752 } 753 } // valueInheritanceSpec 754 755 /** 756 * 757 **/ 758 private void valueSupportsSpec (ValueEntry entry) throws IOException, ParseException 759 { 760 match (Token.Supports) ; 761 for (; ; match( Token.Comma ) ) { 762 SymtabEntry parent = scopedName (entry.container (), stFactory.interfaceEntry ()); 763 SymtabEntry realParent = typeOf (parent); 764 if (isInterface(realParent)) 765 entry.derivedFromAddElement (realParent, scanner); 766 else 767 ParseException.wrongType (scanner, parent.fullName (), "interface", 768 entryName (parent)); 769 770 if (token.type != Token.Comma) 771 break; 772 } 773 } // valueSupportsSpec 774 775 private void valueElement (ValueEntry entry) throws IOException, ParseException 776 { 777 if (entry.isAbstract ()) 778 export (entry); 779 else 780 switch (token.type) 781 { 782 case Token.Private: 783 case Token.Public: 784 valueStateMember (entry); 785 break; 786 case Token.Init: 787 case Token.Factory: // <d62023> "factory" supplants "init" in 2.4RTF 788 initDcl (entry); 789 break; 790 case Token.Typedef: 791 case Token.Struct: 792 case Token.Union: 793 case Token.Enum: 794 case Token.Const: 795 case Token.Native: 796 case Token.Exception: 797 case Token.Readonly: 798 case Token.Attribute: 799 case Token.Oneway: 800 case Token.Float: 801 case Token.Double: 802 case Token.Long: 803 case Token.Short: 804 case Token.Unsigned: 805 case Token.Char: 806 case Token.Wchar: 807 case Token.Boolean: 808 case Token.Octet: 809 case Token.Any: 810 case Token.String: 811 case Token.Wstring: 812 case Token.Identifier: 813 case Token.Object: 814 case Token.ValueBase: 815 case Token.DoubleColon: 816 case Token.Void: 817 export (entry); 818 break; 819 default: 820 throw ParseException.syntaxError(scanner, new int[] { 821 Token.Private, Token.Public, Token.Init, Token.ValueBase, 822 Token.Typedef, Token.Struct, Token.Union, Token.Enum, 823 Token.Const, Token.Exception, Token.Readonly, Token.Attribute, 824 Token.Oneway, Token.Float, Token.Double, Token.Long, 825 Token.Short, Token.Unsigned, Token.Char, Token.Wchar, 826 Token.Boolean, Token.Octet, Token.Any, Token.String, 827 Token.Wstring, Token.Identifier, Token.DoubleColon, Token.Void }, 828 token.type); 829 } // switch 830 } // valueElement 831 832 // <f46082.40> 833 /** 834 * 835 **/ 836 private void valueStateMember (ValueEntry entry) throws IOException, ParseException 837 { 838 TypedefEntry typedefEntry = 839 stFactory.typedefEntry (entry, (IDLID)repIDStack.peek ()); 840 typedefEntry.sourceFile (scanner.fileEntry ()); 841 // comment must immediately precede "public", "private" keywords 842 typedefEntry.comment (token.comment); 843 boolean isPublic = (token.type == Token.Public); 844 if (isPublic) 845 match (Token.Public); 846 else 847 match (Token.Private); 848 // <f46082.40> Add constructed types declared "inline" to the contained 849 // vector of this value entry. 850 boolean isConstTypeSpec = 851 (token.type == Token.Struct || token.type == Token.Union || token.type == Token.Enum); 852 // <f46082.40> Make typedefEntry anonymous. If this line is removed, 853 // the entry will be named incorrectly. See <d50618>. 854 typedefEntry.name (""); 855 typedefEntry.type (typeSpec (typedefEntry)); 856 addDeclarators (entry, typedefEntry, isPublic); 857 // <f46082.40> 858 if (isConstTypeSpec) 859 entry.addContained (typedefEntry); 860 match (Token.Semicolon); 861 } // valueStateMember 862 863 864 private void addDeclarators (ValueEntry entry, TypedefEntry typedefEntry, 865 boolean isPublic) throws IOException, ParseException 866 { 867 int modifier = isPublic ? InterfaceState.Public : InterfaceState.Private; 868 try 869 { 870 Vector typedefList = new Vector (); 871 declarators (typedefEntry, typedefList); 872 for (Enumeration e = typedefList.elements (); e.hasMoreElements ();) 873 entry.addStateElement ( 874 new InterfaceState (modifier, (TypedefEntry)e.nextElement ()), scanner); 875 } 876 catch (ParseException exception) 877 { 878 skipToSemicolon (); 879 } 880 } // addDeclarators 881 882 /** 883 * 884 **/ 885 private void initDcl (ValueEntry entry) throws IOException, ParseException 886 { 887 MethodEntry method = stFactory.methodEntry (entry, (IDLID)repIDStack.peek ()); 888 method.sourceFile (scanner.fileEntry ()); 889 // Comment must immediately precede "init" keyword: 890 method.comment (token.comment); 891 repIDStack.push (((IDLID)repIDStack.peek ()).clone ()); 892 ((IDLID)repIDStack.peek ()).appendToName (token.name); 893 894 // <d62023> In 2.3 prelim, <init_dcl> ::= "init" "(" ... 895 if (token.type == Token.Init) 896 { 897 method.name ("init"); 898 match (Token.Init); 899 match (Token.LeftParen); 900 } 901 else // <d62023> In 2.4rtf, <init_dcl> ::= "factory" <Indentifier> "(" ... 902 { 903 match (Token.Factory); 904 method.name (token.name); 905 if (token.type == Token.MacroIdentifier) 906 match (Token.MacroIdentifier); // "(" already consumed. 907 else 908 { 909 match (Token.Identifier); 910 match (Token.LeftParen); 911 } 912 } 913 914 if (token.type != Token.RightParen) 915 for (;;) 916 { 917 initParamDcl (method); 918 if (token.type == Token.RightParen) 919 break; 920 match (Token.Comma); 921 } 922 entry.initializersAddElement (method, scanner); 923 match (Token.RightParen); 924 match (Token.Semicolon); 925 repIDStack.pop (); 926 } // initDcl 927 928 /** 929 * 930 **/ 931 private void initParamDcl (MethodEntry entry) throws IOException, ParseException 932 { 933 ParameterEntry parmEntry = stFactory.parameterEntry (entry, (IDLID)repIDStack.peek ()); 934 parmEntry.sourceFile (scanner.fileEntry()); 935 // Comment must immediately precede parameter attribute 936 parmEntry.comment (token.comment); 937 match (Token.In); 938 parmEntry.passType (ParameterEntry.In); 939 parmEntry.type (paramTypeSpec (entry)); 940 parmEntry.name (token.name); 941 match (Token.Identifier); 942 if (isntInList (entry.parameters (), parmEntry.name ())) 943 entry.addParameter (parmEntry); 944 } // initParamDcl 945 946 /** 947 * 948 **/ 949 private void valueBox (ModuleEntry module, String name) throws IOException, ParseException 950 { 951 repIDStack.push (((IDLID)repIDStack.peek ()).clone ()); 952 // Note: The 'actual' repository ID will be calculated at the end of 953 // the parsing phase, since it is based on the entire contents of the 954 // declaration, and needs to have all forward references resolved: 955 ValueEntry entry = stFactory.valueBoxEntry (module, (IDLID)repIDStack.peek ()); 956 entry.sourceFile (scanner.fileEntry ()); 957 entry.name (name); 958 // comment must immediately precede "value" keyword 959 entry.comment (tokenHistory.lookBack (2).comment); 960 // <f46082.40> Value boxes may not be forwarded. 961 // If this value has been forward declared, there are probably 962 // other values which derive from a ForwardValueEntry. 963 // Replace those ForwardValueEntry's with this ValueEntry: 964 //if (!ForwardValueEntry.replaceForwardDecl (entry)) 965 // ParseException.badAbstract (scanner, entry.fullName()); 966 SymtabEntry valueForward = (SymtabEntry)Parser.symbolTable.get (entry.fullName ()); 967 if (valueForward != null && valueForward instanceof ForwardEntry) 968 ParseException.forwardedValueBox (scanner, entry.fullName ()); 969 pigeonhole (module, entry); 970 ((IDLID)repIDStack.peek ()).appendToName (name); 971 currentModule = entry; 972 TypedefEntry typedefEntry = stFactory.typedefEntry (entry, (IDLID)repIDStack.peek ()); 973 typedefEntry.sourceFile (scanner.fileEntry ()); 974 typedefEntry.comment (token.comment); 975 // <d50237> Workaround to place typedefEntry in the _contained vector of 976 // this value box entry ONLY when <type_spec> is a constructed type declared 977 // at this point (i.e., not an identifier that resolves to a constructed 978 // type), so that emitters may generate bindings for it. <daz> 979 boolean isConstTypeSpec = 980 token.type == Token.Struct || token.type == Token.Union || token.type == Token.Enum; 981 // <d50618> Make typedefEntry anonymous. If this line is removed, the 982 // entry will be named incorrectly. 983 typedefEntry.name (""); 984 typedefEntry.type (typeSpec (typedefEntry)); 985 // <d59067> Value boxes cannot be nested. 986 if (typedefEntry.type () instanceof ValueBoxEntry) 987 ParseException.nestedValueBox (scanner); 988 //typedefEntry.name (""); 989 entry.addStateElement (new InterfaceState (InterfaceState.Public, typedefEntry), scanner); 990 if (isConstTypeSpec) 991 entry.addContained (typedefEntry); 992 currentModule = module; 993 repIDStack.pop (); 994 } // valueBox 995 996 /** 997 * 998 **/ 999 private void valueForwardDcl (ModuleEntry module, String name, boolean isAbstract) 1000 throws IOException, ParseException 1001 { 1002 ForwardValueEntry entry = stFactory.forwardValueEntry (module, (IDLID)repIDStack.peek ()); 1003 entry.sourceFile (scanner.fileEntry ()); 1004 entry.name (name); 1005 entry.setInterfaceType(isAbstract ? InterfaceType.ABSTRACT : InterfaceType.NORMAL ); 1006 // Comment must immediately precede "[abstract] value" keyword[s] 1007 entry.comment (tokenHistory.lookBack (isAbstract? 3 : 2).comment); 1008 pigeonhole (module, entry); 1009 } // valueForwardDcl 1010 1011 private void nativeDcl (SymtabEntry entry) throws IOException, ParseException 1012 { 1013 match (Token.Native); 1014 NativeEntry nativeEntry = stFactory.nativeEntry (entry, (IDLID)repIDStack.peek ()); 1015 nativeEntry.sourceFile (scanner.fileEntry ()); 1016 // Comment must immediately precede "native" keyword 1017 nativeEntry.comment (tokenHistory.lookBack (1).comment); 1018 nativeEntry.name (token.name); 1019 match (Token.Identifier); 1020 pigeonhole (entry, nativeEntry); 1021 } // nativeDcl 1022 /** 1023 * 1024 **/ 1025 private void constDcl (SymtabEntry entry) throws IOException, ParseException 1026 { 1027 match (Token.Const); 1028 ConstEntry constEntry = stFactory.constEntry (entry, (IDLID)repIDStack.peek ()); 1029 constEntry.sourceFile (scanner.fileEntry ()); 1030 // Comment must immediately precede "const" keyword 1031 constEntry.comment (tokenHistory.lookBack (1).comment); 1032 constType (constEntry); 1033 constEntry.name (token.name); 1034 match (Token.Identifier); 1035 match (Token.Equal); 1036 constEntry.value (constExp (constEntry)); 1037 verifyConstType (constEntry.value (), typeOf (constEntry.type ())); 1038 pigeonhole (entry, constEntry); 1039 } // constDcl 1040 1041 /** 1042 * 1043 **/ 1044 private void constType (SymtabEntry entry) throws IOException, ParseException 1045 { 1046 switch (token.type) 1047 { 1048 case Token.Octet: 1049 entry.type( octetType()) ; 1050 break ; 1051 case Token.Long: 1052 case Token.Short: 1053 case Token.Unsigned: 1054 entry.type (integerType (entry)); 1055 break; 1056 case Token.Char: 1057 case Token.Wchar: 1058 entry.type (charType ()); 1059 break; 1060 case Token.Boolean: 1061 entry.type (booleanType ()); 1062 break; 1063 case Token.Float: 1064 case Token.Double: 1065 entry.type (floatingPtType ()); 1066 break; 1067 case Token.String: 1068 case Token.Wstring: 1069 entry.type (stringType (entry)); 1070 break; 1071 case Token.Identifier: 1072 case Token.DoubleColon: 1073 entry.type (scopedName (entry.container (), stFactory.primitiveEntry ())); 1074 if (hasArrayInfo (entry.type ())) 1075 ParseException.illegalArray (scanner, "const"); 1076 SymtabEntry entryType = typeOf (entry.type ()); 1077 if (!((entryType instanceof PrimitiveEntry) || (entryType instanceof StringEntry))) 1078 { 1079 ParseException.wrongType(scanner, entry.fullName (), "primitive or string", entryName (entry.type ())); 1080 entry.type (qualifiedEntry ("long")); 1081 } 1082 else if (entryType instanceof PrimitiveEntry) 1083 { 1084 String any = overrideName ("any"); 1085 if (entryType.name().equals (any)) 1086 { 1087 ParseException.wrongType (scanner, entry.fullName (), "primitive or string (except " + any + ')', any); 1088 entry.type (qualifiedEntry ("long")); 1089 } 1090 } 1091 break; 1092 default: 1093 throw ParseException.syntaxError (scanner, new int [] { 1094 Token.Long, Token.Short, Token.Unsigned, Token.Char, 1095 Token.Wchar, Token.Boolean, Token.Float, Token.Double, 1096 Token.String, Token.Wstring, Token.Identifier, 1097 Token.DoubleColon }, token.type); 1098 } 1099 } // constType 1100 1101 /** 1102 * 1103 **/ 1104 private boolean hasArrayInfo (SymtabEntry entry) 1105 { 1106 while (entry instanceof TypedefEntry) 1107 { 1108 if (((TypedefEntry)entry).arrayInfo ().size () != 0) 1109 return true; 1110 entry = entry.type (); 1111 } 1112 return false; 1113 } // hasArrayInfo 1114 1115 /** 1116 * 1117 **/ 1118 public static String overrideName (String string) 1119 { 1120 String name = (String)overrideNames.get (string); 1121 return (name == null) ? string : name; 1122 } // overrideName 1123 1124 // If entry is boolean, expression value must be boolean 1125 // If entry is float/double, expression value must be float/double 1126 // If entry is integral, expression value must be integral 1127 // If entry is string, expression value must be string 1128 1129 /** 1130 * 1131 **/ 1132 private void verifyConstType (Expression e, SymtabEntry t) 1133 { 1134 Object value = e.value (); 1135 if (value instanceof BigInteger) 1136 verifyIntegral ((Number)value, t); 1137 else if (value instanceof String) 1138 verifyString (e, t); 1139 else if (value instanceof Boolean) 1140 verifyBoolean (t); 1141 else if (value instanceof Character) 1142 verifyCharacter (e, t); 1143 else if (value instanceof Float || value instanceof Double) 1144 verifyFloat((Number)value, t); 1145 else if (value instanceof ConstEntry) 1146 verifyConstType (((ConstEntry)value).value (), t); 1147 else 1148 ParseException.wrongExprType (scanner, t.fullName (), 1149 (value == null) ? "" : value.toString ()); 1150 } // verifyConstType 1151 1152 private static final int MAX_SHORT = 32767; 1153 private static final int MIN_SHORT = -32768; 1154 private static final int MAX_USHORT = 65535; 1155 1156 /** 1157 * 1158 **/ 1159 private void verifyIntegral (Number n, SymtabEntry t) 1160 { 1161 boolean outOfRange = false; 1162 //KEEP: Useful for debugging com.sun.tools.corba.se.idl.constExpr package 1163 //System.out.println ("verifyIntegral, n = " + n.toString ()); 1164 1165 if (t == qualifiedEntry( "octet" )) { 1166 if ((n.longValue() > 255) || (n.longValue() < 0)) 1167 outOfRange = true ; 1168 } else if (t == qualifiedEntry ("long")) { 1169 if (n.longValue () > Integer.MAX_VALUE || n.longValue() < Integer.MIN_VALUE) 1170 outOfRange = true; 1171 } else if (t == qualifiedEntry ("short")) { 1172 if (n.intValue () > Short.MAX_VALUE || n.intValue () < Short.MIN_VALUE) 1173 outOfRange = true; 1174 } else if (t == qualifiedEntry ("unsigned long")) { 1175 if (n.longValue () > (long)Integer.MAX_VALUE*2+1 || n.longValue() < 0) 1176 outOfRange = true; 1177 } else if (t == qualifiedEntry ("unsigned short")) { 1178 if (n.intValue () > (int) Short.MAX_VALUE*2+1 || n.intValue () < 0) 1179 outOfRange = true; 1180 } else if (t == qualifiedEntry ("long long")) { 1181 // BigInteger required because value being compared may exceed 1182 // java.lang.Long.MAX_VALUE/MIN_VALUE: 1183 BigInteger llMax = BigInteger.valueOf (Long.MAX_VALUE); 1184 BigInteger llMin = BigInteger.valueOf (Long.MIN_VALUE); 1185 if (((BigInteger)n).compareTo (llMax) > 0 || 1186 ((BigInteger)n).compareTo (llMin) < 0) 1187 outOfRange = true; 1188 } else if (t == qualifiedEntry ("unsigned long long")) { 1189 BigInteger ullMax = BigInteger.valueOf (Long.MAX_VALUE). 1190 multiply (BigInteger.valueOf (2)). 1191 add (BigInteger.valueOf (1)); 1192 BigInteger ullMin = BigInteger.valueOf (0); 1193 if (((BigInteger)n).compareTo (ullMax) > 0 || 1194 ((BigInteger)n).compareTo (ullMin) < 0) 1195 outOfRange = true; 1196 } else { 1197 String got = null; 1198 // THIS MUST BE CHANGED; BIGINTEGER IS ALWAYS THE CONTAINER 1199 /* 1200 if (n instanceof Short) 1201 got = "short"; 1202 else if (n instanceof Integer) 1203 got = "long"; 1204 else 1205 got = "long long"; 1206 */ 1207 got = "long"; 1208 ParseException.wrongExprType (scanner, t.fullName (), got); 1209 } 1210 1211 if (outOfRange) 1212 ParseException.outOfRange (scanner, n.toString (), t.fullName ()); 1213 } // verifyIntegral 1214 1215 /** 1216 * 1217 **/ 1218 private void verifyString (Expression e, SymtabEntry t) 1219 { 1220 String string = (String)(e.value()) ; 1221 if (!(t instanceof StringEntry)) { 1222 ParseException.wrongExprType (scanner, t.fullName (), e.type() ); 1223 } else if (((StringEntry)t).maxSize () != null) { 1224 Expression maxExp = ((StringEntry)t).maxSize (); 1225 try { 1226 Number max = (Number)maxExp.value (); 1227 if (string.length () > max.intValue ()) 1228 ParseException.stringTooLong (scanner, string, max.toString ()); 1229 } catch (Exception exception) { 1230 // If the above statement is not valid and throws an 1231 // exception, then an error occurred and was reported 1232 // earlier. Move on. 1233 } 1234 } 1235 1236 if (!e.type().equals( t.name())) { 1237 // cannot mix strings and wide strings 1238 ParseException.wrongExprType (scanner, t.name(), e.type() ) ; 1239 } 1240 } // verifyString 1241 1242 /** 1243 * 1244 **/ 1245 private void verifyBoolean (SymtabEntry t) 1246 { 1247 if (!t.name ().equals (overrideName ("boolean"))) 1248 ParseException.wrongExprType(scanner, t.name(), "boolean"); 1249 } // verifyBoolean 1250 1251 /** 1252 * 1253 **/ 1254 private void verifyCharacter (Expression e, SymtabEntry t) 1255 { 1256 // Bug fix 4382578: Can't compile a wchar literal. 1257 // Allow a Character to be either a char or a wchar. 1258 if (!t.name ().equals (overrideName ("char")) && 1259 !t.name ().equals (overrideName ("wchar")) || 1260 !t.name().equals(e.type()) ) 1261 ParseException.wrongExprType (scanner, t.fullName(), e.type() ) ; 1262 } // verifyCharacter 1263 1264 /** 1265 * 1266 **/ 1267 private void verifyFloat (Number f, SymtabEntry t) 1268 { 1269 // <d52042> Added range checking for floats. 1270 //if (!(t.name ().equals (overrideName ("float")) || 1271 // t.name ().equals (overrideName ("double")))) 1272 // ParseException.wrongExprType (scanner, 1273 // t.fullName (), (f instanceof Float) ? "float" : "double"); 1274 //KEEP: Useful for debugging com.sun.tools.corba.se.idl.constExpr package 1275 //System.out.println ("verifyFloat, f = " + f.toString ()); 1276 boolean outOfRange = false; 1277 if (t.name ().equals (overrideName ("float"))) 1278 { 1279 double absVal = (f.doubleValue () < 0.0) ? 1280 f.doubleValue () * -1.0 : f.doubleValue (); 1281 if ((absVal != 0.0) && 1282 (absVal > Float.MAX_VALUE || absVal < Float.MIN_VALUE)) 1283 outOfRange = true; 1284 } 1285 else if (t.name ().equals (overrideName ("double"))) 1286 { 1287 // Cannot check range of double until BigDecimal is the basis 1288 // of all floating-point types. Currently, it is Double. The 1289 // parser will fail when instantiating a Double with an exception. 1290 } 1291 else 1292 { 1293 ParseException.wrongExprType (scanner, t.fullName (), 1294 (f instanceof Float) ? "float" : "double"); 1295 } 1296 if (outOfRange) 1297 ParseException.outOfRange (scanner, f.toString (), t.fullName ()); 1298 } // verifyFloat 1299 1300 /** 1301 * 1302 **/ 1303 Expression constExp (SymtabEntry entry) throws IOException, ParseException 1304 { 1305 // Parse the expression. 1306 Expression expr = orExpr (null, entry); 1307 1308 // Set its target type. 1309 if (expr.type() == null) 1310 expr.type (entry.typeName ()); 1311 // Compute its value and <d53042> coerce it to the target type. 1312 try 1313 { 1314 expr.evaluate (); 1315 1316 // <d54042> Coerces integral value to Double if an integer literal 1317 // was used to initialize a floating-point constant expression. 1318 if (expr instanceof Terminal && 1319 expr.value () instanceof BigInteger && 1320 (overrideName (expr.type ()).equals ("float") || 1321 overrideName (expr.type ()).indexOf ("double") >= 0)) 1322 { 1323 expr.value (new Double (((BigInteger)expr.value ()).doubleValue ())); 1324 } 1325 } 1326 catch (EvaluationException exception) 1327 { 1328 ParseException.evaluationError (scanner, exception.toString ()); 1329 } 1330 return expr; 1331 } // constExp 1332 1333 /** 1334 * 1335 **/ 1336 private Expression orExpr (Expression e, SymtabEntry entry) throws IOException, ParseException 1337 { 1338 if (e == null) 1339 e = xorExpr (null, entry); 1340 else 1341 { 1342 BinaryExpr b = (BinaryExpr)e; 1343 b.right (xorExpr (null, entry)); 1344 e.rep (e.rep () + b.right ().rep ()); 1345 } 1346 if (token.equals (Token.Bar)) 1347 { 1348 match (token.type); 1349 Or or = exprFactory.or (e, null); 1350 or.type (entry.typeName ()); 1351 or.rep (e.rep () + " | "); 1352 return orExpr (or, entry); 1353 } 1354 return e; 1355 } // orExpr 1356 1357 /** 1358 * 1359 **/ 1360 private Expression xorExpr (Expression e, SymtabEntry entry) throws IOException, ParseException 1361 { 1362 if (e == null) 1363 e = andExpr (null, entry); 1364 else 1365 { 1366 BinaryExpr b = (BinaryExpr)e; 1367 b.right (andExpr (null, entry)); 1368 e.rep (e.rep () + b.right ().rep ()); 1369 } 1370 if (token.equals (Token.Carat)) 1371 { 1372 match (token.type); 1373 Xor xor = exprFactory.xor (e, null); 1374 xor.rep (e.rep () + " ^ "); 1375 xor.type (entry.typeName ()); 1376 return xorExpr (xor, entry); 1377 } 1378 return e; 1379 } // xorExpr 1380 1381 /** 1382 * 1383 **/ 1384 private Expression andExpr (Expression e, SymtabEntry entry) throws IOException, ParseException 1385 { 1386 if (e == null) 1387 e = shiftExpr (null, entry); 1388 else 1389 { 1390 BinaryExpr b = (BinaryExpr)e; 1391 b.right (shiftExpr (null, entry)); 1392 e.rep (e.rep () + b.right ().rep ()); 1393 } 1394 if (token.equals (Token.Ampersand)) 1395 { 1396 match (token.type); 1397 And and = exprFactory.and (e, null); 1398 and.rep(e.rep () + " & "); 1399 and.type (entry.typeName ()); 1400 return andExpr (and, entry); 1401 } 1402 return e; 1403 } // andExpr 1404 1405 /** 1406 * 1407 **/ 1408 private Expression shiftExpr (Expression e, SymtabEntry entry) throws IOException, ParseException 1409 { 1410 if (e == null) 1411 e = addExpr (null, entry); 1412 else 1413 { 1414 BinaryExpr b = (BinaryExpr)e; 1415 b.right (addExpr (null, entry)); 1416 e.rep (e.rep () + b.right ().rep ()); 1417 } 1418 if (token.equals (Token.ShiftLeft)) 1419 { 1420 match (token.type); 1421 ShiftLeft sl = exprFactory.shiftLeft (e, null); 1422 sl.type (entry.typeName ()); 1423 sl.rep (e.rep () + " << "); 1424 return shiftExpr (sl, entry); 1425 } 1426 if (token.equals (Token.ShiftRight)) 1427 { 1428 match (token.type); 1429 ShiftRight sr = exprFactory.shiftRight (e, null); 1430 sr.type (entry.typeName ()); 1431 sr.rep (e.rep () + " >> "); 1432 return shiftExpr (sr, entry); 1433 } 1434 return e; 1435 } // shiftExpr 1436 1437 /** 1438 * 1439 **/ 1440 private Expression addExpr (Expression e, SymtabEntry entry) throws IOException, ParseException 1441 { 1442 if (e == null) 1443 e = multExpr (null, entry); 1444 else 1445 { 1446 BinaryExpr b = (BinaryExpr)e; 1447 b.right (multExpr (null, entry)); 1448 e.rep (e.rep () + b.right ().rep ()); 1449 } 1450 if (token.equals (Token.Plus)) 1451 { 1452 match (token.type); 1453 Plus p = exprFactory.plus (e, null); 1454 p.type (entry.typeName ()); 1455 p.rep (e.rep () + " + "); 1456 return addExpr (p, entry); 1457 } 1458 if (token.equals (Token.Minus)) 1459 { 1460 match (token.type); 1461 Minus m = exprFactory.minus (e, null); 1462 m.type (entry.typeName ()); 1463 m.rep (e.rep () + " - "); 1464 return addExpr (m, entry); 1465 } 1466 return e; 1467 } // addExpr 1468 1469 /** 1470 * 1471 **/ 1472 private Expression multExpr (Expression e, SymtabEntry entry) throws IOException, ParseException 1473 { 1474 if (e == null) 1475 e = unaryExpr (entry); 1476 else 1477 { 1478 BinaryExpr b = (BinaryExpr)e; 1479 b.right (unaryExpr (entry)); 1480 e.rep (e.rep () + b.right ().rep ()); 1481 } 1482 if (token.equals (Token.Star)) 1483 { 1484 match (token.type); 1485 Times t = exprFactory.times (e, null); 1486 t.type (entry.typeName ()); 1487 t.rep (e.rep () + " * "); 1488 return multExpr (t, entry); 1489 } 1490 if (token.equals (Token.Slash)) 1491 { 1492 match (token.type); 1493 Divide d = exprFactory.divide (e, null); 1494 d.type (entry.typeName ()); 1495 d.rep (e.rep () + " / "); 1496 return multExpr (d, entry); 1497 } 1498 if (token.equals (Token.Percent)) 1499 { 1500 match (token.type); 1501 Modulo m = exprFactory.modulo (e, null); 1502 m.type (entry.typeName ()); 1503 m.rep (e.rep () + " % "); 1504 return multExpr (m, entry); 1505 } 1506 return e; 1507 } // multExpr 1508 1509 /** 1510 * 1511 **/ 1512 private Expression unaryExpr (SymtabEntry entry) throws IOException, ParseException 1513 { 1514 if (token.equals (Token.Plus)) 1515 { 1516 match (token.type); 1517 Expression e = primaryExpr (entry); 1518 Positive pos = exprFactory.positive (e); 1519 pos.type (entry.typeName()); 1520 pos.rep ('+' + e.rep()); 1521 return pos; 1522 } 1523 if (token.equals (Token.Minus)) 1524 { 1525 match (token.type); 1526 Expression e = primaryExpr (entry); 1527 Negative neg = exprFactory.negative (e); 1528 neg.type (entry.typeName()); 1529 neg.rep ('-' + e.rep()); 1530 return neg; 1531 } 1532 if (token.equals (Token.Tilde)) 1533 { 1534 match (token.type); 1535 Expression e = primaryExpr (entry); 1536 Not not = exprFactory.not (e); 1537 not.type (entry.typeName()); 1538 not.rep ('~' + e.rep()); 1539 return not; 1540 } 1541 return primaryExpr (entry); 1542 } // unaryExpr 1543 1544 /** 1545 * 1546 **/ 1547 private Expression primaryExpr (SymtabEntry entry) 1548 throws IOException, ParseException 1549 { 1550 Expression primary = null; 1551 if (parsingConditionalExpr) 1552 { 1553 prep.token = token; // Give current token to preprocessor 1554 primary = prep.primaryExpr (entry); 1555 token = prep.token; // Get the current token from preprocessor 1556 } 1557 else 1558 switch (token.type) 1559 { 1560 case Token.Identifier: 1561 case Token.DoubleColon: 1562 ConstEntry expectedC = stFactory.constEntry (); 1563 expectedC.value (exprFactory.terminal ("1", BigInteger.valueOf (1))); 1564 SymtabEntry ref = scopedName (entry.container (), expectedC); 1565 if (!(ref instanceof ConstEntry)) 1566 { 1567 ParseException.invalidConst (scanner, ref.fullName ()); 1568 // An error occurred. Just give it some bogus value. <daz> 1569 //primary = exprFactory.terminal ("1", new Long (1)); 1570 primary = exprFactory.terminal ("1", BigInteger.valueOf (1)); 1571 } 1572 else 1573 primary = exprFactory.terminal ((ConstEntry)ref); 1574 break; 1575 case Token.BooleanLiteral: 1576 case Token.CharacterLiteral: 1577 case Token.IntegerLiteral: 1578 case Token.FloatingPointLiteral: 1579 case Token.StringLiteral: 1580 primary = literal (entry); 1581 break; 1582 case Token.LeftParen: 1583 match (Token.LeftParen); 1584 primary = constExp (entry); 1585 match (Token.RightParen); 1586 primary.rep ('(' + primary.rep () + ')'); 1587 break; 1588 default: 1589 throw ParseException.syntaxError (scanner, new int [] { 1590 Token.Identifier, Token.DoubleColon, Token.Literal, Token.LeftParen}, 1591 token.type); 1592 } 1593 return primary; 1594 } // primaryExpr 1595 1596 /** 1597 * 1598 **/ 1599 Expression literal (SymtabEntry entry) throws IOException, ParseException 1600 { 1601 String string = token.name; 1602 Expression literal = null; 1603 switch (token.type) 1604 { 1605 case Token.IntegerLiteral: 1606 match (Token.IntegerLiteral); 1607 try 1608 { 1609 literal = exprFactory.terminal (string, parseString (string)); 1610 literal.type (entry.typeName ()); 1611 } 1612 catch (NumberFormatException exception) 1613 { 1614 ParseException.notANumber (scanner, string); 1615 literal = exprFactory.terminal ("0", BigInteger.valueOf (0)); 1616 } 1617 break; 1618 case Token.CharacterLiteral: 1619 boolean isWide = token.isWide(); 1620 match (Token.CharacterLiteral); 1621 literal = exprFactory.terminal ("'" + string.substring (1) + "'", 1622 new Character (string.charAt (0)), isWide ); 1623 break; 1624 case Token.FloatingPointLiteral: 1625 match (Token.FloatingPointLiteral); 1626 try 1627 { 1628 literal = exprFactory.terminal (string, new Double (string)); 1629 literal.type (entry.typeName ()); 1630 } 1631 catch (NumberFormatException e) 1632 { 1633 ParseException.notANumber (scanner, string); 1634 } 1635 break; 1636 case Token.BooleanLiteral: 1637 literal = booleanLiteral (); 1638 break; 1639 case Token.StringLiteral: 1640 literal = stringLiteral (); 1641 break; 1642 default: 1643 throw ParseException.syntaxError (scanner, Token.Literal,token.type); 1644 } 1645 return literal; 1646 } // literal 1647 1648 /** 1649 * 1650 **/ 1651 private BigInteger parseString (String string) throws NumberFormatException 1652 { 1653 int radix = 10; 1654 if (string.length() > 1) 1655 if (string.charAt (0) == '0') 1656 if (string.charAt (1) == 'x' || string.charAt (1) == 'X') 1657 { 1658 string = string.substring (2); 1659 radix = 16; 1660 } 1661 else 1662 radix = 8; 1663 return new BigInteger (string, radix); 1664 } // parseString 1665 1666 /** 1667 * 1668 **/ 1669 private Terminal booleanLiteral () throws IOException, ParseException 1670 { 1671 Boolean bool = null; 1672 if (token.name.equals ("TRUE")) 1673 bool = new Boolean (true); 1674 else if (token.name.equals ("FALSE")) 1675 bool = new Boolean (false); 1676 else 1677 { 1678 ParseException.invalidConst (scanner, token.name); 1679 bool = new Boolean (false); 1680 } 1681 String name = token.name; 1682 match (Token.BooleanLiteral); 1683 return exprFactory.terminal (name, bool); 1684 } // booleanLiteral 1685 1686 /** 1687 * 1688 **/ 1689 private Expression stringLiteral () throws IOException, ParseException 1690 { 1691 // If string literals appear together, concatenate them. Ie: 1692 // "Twas " "brillig " "and " "the " "slithy " "toves" 1693 // becomes 1694 // "Twas brillig and the slithy toves" 1695 boolean isWide = token.isWide() ; 1696 String literal = ""; 1697 do 1698 { 1699 literal += token.name; 1700 match (Token.StringLiteral); 1701 } while (token.equals (Token.StringLiteral)); 1702 Expression stringExpr = exprFactory.terminal (literal, isWide ); 1703 stringExpr.rep ('"' + literal + '"'); 1704 return stringExpr; 1705 } // stringLiteral 1706 1707 /** 1708 * 1709 **/ 1710 private Expression positiveIntConst (SymtabEntry entry) throws IOException, ParseException 1711 { 1712 Expression e = constExp (entry); 1713 Object value = e.value (); 1714 while (value instanceof ConstEntry) 1715 value = ((ConstEntry)value).value ().value (); 1716 if (!(value instanceof Number) || value instanceof Float || value instanceof Double) 1717 { 1718 ParseException.notPositiveInt (scanner, e.rep ()); 1719 //e = exprFactory.terminal ("1", new Long (1)); 1720 e = exprFactory.terminal ("1", BigInteger.valueOf (1)); 1721 } 1722 //else if (((Number)value).longValue () <= 0) { 1723 // ParseException.notPositiveInt (scanner, value.toString ()); 1724 // e = exprFactory.terminal ("1", new Long (1)); } 1725 else if (((BigInteger)value).compareTo (BigInteger.valueOf (0)) <= 0) 1726 { 1727 ParseException.notPositiveInt (scanner, value.toString ()); 1728 //e = exprFactory.terminal ("1", new Long (1)); <daz> 1729 e = exprFactory.terminal ("1", BigInteger.valueOf (1)); 1730 } 1731 return e; 1732 } // positiveIntConst 1733 1734 /** 1735 * 1736 **/ 1737 private SymtabEntry typeDcl (SymtabEntry entry) throws IOException, ParseException 1738 { 1739 switch (token.type) 1740 { 1741 case Token.Typedef: 1742 match (Token.Typedef); 1743 return typeDeclarator (entry); 1744 case Token.Struct: 1745 return structType (entry); 1746 case Token.Union: 1747 return unionType (entry); 1748 case Token.Enum: 1749 return enumType (entry); 1750 default: 1751 throw ParseException.syntaxError (scanner, new int [] { 1752 Token.Typedef, Token.Struct, Token.Union, Token.Enum}, token.type); 1753 } 1754 } // typeDcl 1755 1756 /** 1757 * 1758 **/ 1759 private TypedefEntry typeDeclarator (SymtabEntry entry) throws IOException, ParseException 1760 { 1761 TypedefEntry typedefEntry = stFactory.typedefEntry (entry, (IDLID)repIDStack.peek ()); 1762 typedefEntry.sourceFile (scanner.fileEntry ()); 1763 // Comment must immediately precede "typedef" keyword 1764 typedefEntry.comment (tokenHistory.lookBack (1).comment); 1765 typedefEntry.type (typeSpec (entry)); 1766 Vector typedefList = new Vector (); 1767 declarators (typedefEntry, typedefList); 1768 for (Enumeration e = typedefList.elements(); e.hasMoreElements();) 1769 pigeonhole (entry, (SymtabEntry)e.nextElement ()); 1770 return typedefEntry; 1771 } // typeDeclarator 1772 1773 /** 1774 * 1775 **/ 1776 private SymtabEntry typeSpec (SymtabEntry entry) throws IOException, ParseException 1777 { 1778 return ((token.type == Token.Struct) || 1779 (token.type == Token.Union) || 1780 (token.type == Token.Enum)) 1781 ? constrTypeSpec (entry) 1782 : simpleTypeSpec (entry, true); 1783 } // typeSpec 1784 1785 /** 1786 * 1787 **/ 1788 private SymtabEntry simpleTypeSpec (SymtabEntry entry, 1789 boolean mustBeReferencable ) throws IOException, ParseException 1790 { 1791 // <f46082.40> 1792 //if ((token.type == Token.Identifier) || 1793 // (token.type == Token.DoubleColon) || 1794 // (token.type == Token.Object)) { 1795 if ((token.type == Token.Identifier) || 1796 (token.type == Token.DoubleColon) || 1797 (token.type == Token.Object) || 1798 (token.type == Token.ValueBase)) 1799 { 1800 SymtabEntry container = ((entry instanceof InterfaceEntry) || 1801 (entry instanceof ModuleEntry) || 1802 (entry instanceof StructEntry) || 1803 (entry instanceof UnionEntry)) 1804 ? entry 1805 : entry.container (); 1806 return scopedName (container, stFactory.primitiveEntry (), 1807 mustBeReferencable); 1808 } 1809 return ((token.type == Token.Sequence) || 1810 (token.type == Token.String) || 1811 (token.type == Token.Wstring)) 1812 ? templateTypeSpec (entry) 1813 : baseTypeSpec (entry); 1814 } // simpleTypeSpec 1815 1816 /** 1817 * 1818 **/ 1819 private SymtabEntry baseTypeSpec (SymtabEntry entry) throws IOException, ParseException 1820 { 1821 switch (token.type) 1822 { 1823 case Token.Float: 1824 case Token.Double: 1825 return floatingPtType (); 1826 case Token.Long: 1827 case Token.Short: 1828 case Token.Unsigned: 1829 return integerType (entry); 1830 case Token.Char: 1831 case Token.Wchar: 1832 return charType (); 1833 case Token.Boolean: 1834 return booleanType (); 1835 case Token.Octet: 1836 return octetType (); 1837 case Token.Any: 1838 return anyType (); 1839 // NOTE: Object and ValueBase are <base_type_spec>s, but both 1840 // are processed at simpleTypeSpec(), not here. parmTypeSpec() 1841 // directly checks for these types. Could make baseTypeSpec() do 1842 // the same 1843 default: 1844 throw ParseException.syntaxError (scanner, new int [] { 1845 Token.Float, Token.Double, Token.Long, Token.Short, 1846 Token.Unsigned, Token.Char, Token.Wchar, Token.Boolean, 1847 Token.Octet, Token.Any}, token.type); 1848 } 1849 } // baseTypeSpec 1850 1851 /** 1852 * 1853 **/ 1854 private SymtabEntry templateTypeSpec (SymtabEntry entry) throws IOException, ParseException 1855 { 1856 switch (token.type) 1857 { 1858 case Token.Sequence: 1859 return sequenceType (entry); 1860 case Token.String: 1861 case Token.Wstring: 1862 return stringType (entry); 1863 } 1864 throw ParseException.syntaxError (scanner, new int [] {Token.Sequence, Token.String, Token.Wstring}, token.type); 1865 } // templateTypeSpec 1866 1867 /** 1868 * 1869 **/ 1870 private SymtabEntry constrTypeSpec (SymtabEntry entry) throws IOException, ParseException 1871 { 1872 switch (token.type) 1873 { 1874 case Token.Struct: 1875 return structType (entry); 1876 case Token.Union: 1877 return unionType (entry); 1878 case Token.Enum: 1879 return enumType (entry); 1880 } 1881 throw ParseException.syntaxError (scanner, new int [] {Token.Struct, Token.Union, Token.Enum}, token.type); 1882 } // constrTypeSpec 1883 1884 /** 1885 * 1886 **/ 1887 private void declarators (TypedefEntry entry, Vector list) throws IOException, ParseException 1888 { 1889 for (; ; match (Token.Comma)) 1890 { 1891 TypedefEntry newEntry = (TypedefEntry)entry.clone (); 1892 declarator (newEntry); 1893 if (isntInList (list, newEntry.name ())) 1894 list.addElement (newEntry); 1895 if (token.type != Token.Comma) 1896 break; 1897 } 1898 } // declarators 1899 1900 /** 1901 * 1902 **/ 1903 private void declarator (TypedefEntry entry) throws IOException, ParseException 1904 { 1905 entry.name (token.name); 1906 // If the declarator is commented then override the comment cloned from the parent 1907 // entry. <08aug1997daz> 1908 if (!token.comment.text ().equals ("")) 1909 entry.comment (token.comment); 1910 match (Token.Identifier); 1911 while (token.type == Token.LeftBracket) 1912 fixedArraySize (entry); 1913 } // declarator 1914 1915 /** 1916 * 1917 **/ 1918 private PrimitiveEntry floatingPtType () throws IOException, ParseException 1919 { 1920 String name = "double"; 1921 if (token.type == Token.Float) 1922 { 1923 match (Token.Float); 1924 name = "float"; 1925 } 1926 else if (token.type == Token.Double) 1927 match (Token.Double); 1928 else 1929 { 1930 int [] expected = {Token.Float, Token.Double}; 1931 ParseException.syntaxError (scanner, new int [] {Token.Float, Token.Double }, token.type); 1932 } 1933 PrimitiveEntry ret = null; 1934 try 1935 { 1936 ret = (PrimitiveEntry)qualifiedEntry (name); 1937 } 1938 catch (ClassCastException exception) 1939 { 1940 ParseException.undeclaredType (scanner, name); 1941 } 1942 return ret; 1943 } // floatingPtType 1944 1945 /** 1946 * 1947 **/ 1948 private PrimitiveEntry integerType (SymtabEntry entry) throws IOException, ParseException 1949 { 1950 String name = ""; 1951 if (token.type == Token.Unsigned) 1952 { 1953 match (Token.Unsigned); 1954 name = "unsigned "; 1955 } 1956 name += signedInt(); 1957 PrimitiveEntry ret = null; 1958 try 1959 { 1960 ret = (PrimitiveEntry) qualifiedEntry (name); 1961 } 1962 catch (ClassCastException exception) 1963 { 1964 ParseException.undeclaredType (scanner, name); 1965 } 1966 return ret; 1967 } // integerType 1968 1969 /** 1970 * 1971 **/ 1972 private String signedInt () throws IOException, ParseException 1973 { 1974 String ret = "long"; 1975 if (token.type == Token.Long) 1976 { 1977 match (Token.Long); 1978 // <signedInt'> ::= "long" | e 1979 if (token.type == Token.Long) 1980 { 1981 ret = "long long"; 1982 match (Token.Long); 1983 } 1984 } 1985 else if (token.type == Token.Short) 1986 { 1987 ret = "short"; 1988 match (Token.Short); 1989 } 1990 else 1991 ParseException.syntaxError (scanner, new int [] {Token.Long, Token.Short}, token.type); 1992 return ret; 1993 } // signedInt 1994 1995 /** 1996 * 1997 **/ 1998 private PrimitiveEntry charType () throws IOException, ParseException 1999 { 2000 String tokenName; 2001 if (token.type == Token.Char) 2002 { 2003 match (Token.Char); 2004 tokenName = "char"; 2005 } 2006 else 2007 { 2008 match (Token.Wchar); 2009 tokenName = "wchar"; 2010 } 2011 PrimitiveEntry ret = null; 2012 try 2013 { 2014 ret = (PrimitiveEntry) qualifiedEntry (tokenName); 2015 } 2016 catch (ClassCastException exception) 2017 { 2018 ParseException.undeclaredType (scanner, overrideName (tokenName)); 2019 } 2020 return ret; 2021 } // charType 2022 2023 /** 2024 * 2025 **/ 2026 private PrimitiveEntry booleanType () throws IOException, ParseException 2027 { 2028 PrimitiveEntry ret = null; 2029 match (Token.Boolean); 2030 try 2031 { 2032 ret = (PrimitiveEntry) qualifiedEntry ("boolean"); 2033 } 2034 catch (ClassCastException exception) 2035 { 2036 ParseException.undeclaredType (scanner, overrideName ("boolean")); 2037 } 2038 return ret; 2039 } // booleanType 2040 2041 /** 2042 * 2043 **/ 2044 private PrimitiveEntry octetType () throws IOException, ParseException 2045 { 2046 PrimitiveEntry ret = null; 2047 match (Token.Octet); 2048 try 2049 { 2050 ret = (PrimitiveEntry) qualifiedEntry ("octet"); 2051 } 2052 catch (ClassCastException exception) 2053 { 2054 ParseException.undeclaredType (scanner, overrideName ("octet")); 2055 } 2056 return ret; 2057 } // octetType 2058 2059 /** 2060 * 2061 **/ 2062 private SymtabEntry anyType () throws IOException, ParseException 2063 { 2064 match (Token.Any); 2065 try 2066 { 2067 return qualifiedEntry ("any"); 2068 } 2069 catch (ClassCastException exception) 2070 { 2071 ParseException.undeclaredType (scanner, overrideName ("any")); 2072 return null; 2073 } 2074 } // anyType 2075 2076 /** 2077 * 2078 **/ 2079 private StructEntry structType (SymtabEntry entry) throws IOException, 2080 ParseException 2081 { 2082 match (Token.Struct); 2083 String name = token.name; 2084 match (Token.Identifier); 2085 StructEntry structEntry = null ; 2086 2087 if (token.type == Token.LeftBrace) { 2088 repIDStack.push(((IDLID)repIDStack.peek ()).clone ()) ; 2089 structEntry = makeStructEntry( name, entry, false ) ; 2090 ((IDLID)repIDStack.peek ()).appendToName (name); 2091 prep.openScope (structEntry); 2092 match (Token.LeftBrace) ; 2093 member (structEntry) ; 2094 memberList2 (structEntry) ; 2095 prep.closeScope (structEntry); 2096 match (Token.RightBrace) ; 2097 repIDStack.pop() ; 2098 } else if (token.equals( Token.Semicolon )) { 2099 structEntry = makeStructEntry( name, entry, true ) ; 2100 } else { 2101 throw ParseException.syntaxError (scanner, 2102 new int[] { Token.Semicolon, Token.LeftBrace }, token.type); 2103 } 2104 return structEntry; 2105 } // structType 2106 2107 private StructEntry makeStructEntry( String name, SymtabEntry entry, 2108 boolean isForward ) 2109 { 2110 StructEntry structEntry = stFactory.structEntry (entry, 2111 (IDLID)repIDStack.peek () ); 2112 structEntry.isReferencable( !isForward ) ; 2113 structEntry.sourceFile (scanner.fileEntry ()); 2114 structEntry.name (name); 2115 // Comment must immediately preceed "struct" keyword 2116 structEntry.comment (tokenHistory.lookBack (1).comment); 2117 pigeonhole( entry, structEntry ) ; 2118 return structEntry ; 2119 } 2120 2121 /** 2122 * 2123 **/ 2124 private void memberList2 (StructEntry entry) throws IOException 2125 { 2126 while (token.type != Token.RightBrace) 2127 member (entry); 2128 } // memberList2 2129 2130 /** 2131 * 2132 **/ 2133 private void member (StructEntry entry) throws IOException 2134 { 2135 TypedefEntry newEntry = stFactory.typedefEntry(entry, (IDLID)repIDStack.peek()); 2136 newEntry.sourceFile (scanner.fileEntry ()); 2137 // comment must immediately precede <type_spec> lexeme 2138 newEntry.comment (token.comment); 2139 try 2140 { 2141 newEntry.type (typeSpec (entry)); 2142 if (newEntry.type () == entry) 2143 throw ParseException.recursive (scanner, entry.fullName (), 2144 (token.name == null) ? "" : token.name); 2145 // <d46094> Exception cannot appear within a struct, union, or exception 2146 if (typeOf (newEntry) instanceof ExceptionEntry) 2147 throw ParseException.illegalException (scanner, entryName (entry)); 2148 declarators (newEntry, entry.members ()); 2149 match (Token.Semicolon); 2150 } 2151 catch (ParseException exception) 2152 { 2153 skipToSemicolon (); 2154 } 2155 } // member 2156 2157 /** 2158 * 2159 **/ 2160 private final boolean isConstTypeSpec (Token t) 2161 { 2162 return (t.type == Token.Struct || t.type == Token.Union || t.type == Token.Enum); 2163 } // isConstTypeSpec 2164 2165 /** 2166 * 2167 **/ 2168 private UnionEntry unionType (SymtabEntry entry) throws IOException, ParseException 2169 { 2170 match (Token.Union) ; 2171 String name = token.name ; 2172 match (Token.Identifier) ; 2173 UnionEntry unionEntry = null ; 2174 2175 if (token.type == Token.Switch) { 2176 repIDStack.push (((IDLID)repIDStack.peek ()).clone ()); 2177 unionEntry = makeUnionEntry( name, entry, false ) ; 2178 ((IDLID)repIDStack.peek ()).appendToName (name); 2179 match (Token.Switch); 2180 match (Token.LeftParen); 2181 unionEntry.type (switchTypeSpec (unionEntry)); 2182 match (Token.RightParen); 2183 prep.openScope (unionEntry); 2184 match (Token.LeftBrace); 2185 switchBody (unionEntry); 2186 verifyUnion (unionEntry); 2187 prep.closeScope (unionEntry); 2188 match (Token.RightBrace); 2189 repIDStack.pop (); 2190 } else if (token.equals( Token.Semicolon )) { 2191 unionEntry = makeUnionEntry( name, entry, true ) ; 2192 } else { 2193 throw ParseException.syntaxError (scanner, 2194 new int[] { Token.Semicolon, Token.Switch }, token.type); 2195 } 2196 2197 return unionEntry ; 2198 } // unionType 2199 2200 private UnionEntry makeUnionEntry( String name, SymtabEntry entry, 2201 boolean isForward ) 2202 { 2203 UnionEntry unionEntry = stFactory.unionEntry (entry, 2204 (IDLID)repIDStack.peek () ); 2205 unionEntry.isReferencable( !isForward ) ; 2206 unionEntry.sourceFile (scanner.fileEntry ()); 2207 unionEntry.name (name); 2208 // Comment must immediately preceed "union" keyword 2209 unionEntry.comment (tokenHistory.lookBack (1).comment); 2210 pigeonhole( entry, unionEntry ) ; 2211 return unionEntry ; 2212 } 2213 2214 /** 2215 * 2216 **/ 2217 private void verifyUnion (UnionEntry u) 2218 { 2219 if (u.typeName ().equals (overrideName ("boolean"))) 2220 { 2221 if (caseCount (u) > 2) 2222 ParseException.noDefault (scanner); 2223 } 2224 else if (u.type () instanceof EnumEntry) 2225 { 2226 if (caseCount (u) > ((EnumEntry)u.type ()).elements ().size ()) 2227 ParseException.noDefault (scanner); 2228 } 2229 } // verifyUnion 2230 2231 /** 2232 * 2233 **/ 2234 private long caseCount (UnionEntry u) 2235 { 2236 long cases = 0; 2237 Enumeration branches = u.branches ().elements (); 2238 while (branches.hasMoreElements ()) 2239 { 2240 UnionBranch branch = (UnionBranch)branches.nextElement (); 2241 cases += branch.labels.size (); 2242 if (branch.isDefault) 2243 ++cases; 2244 } 2245 return cases; 2246 } // caseCount 2247 2248 /** 2249 * 2250 **/ 2251 private SymtabEntry switchTypeSpec (UnionEntry entry) throws IOException, ParseException 2252 { 2253 SymtabEntry ret = null; 2254 switch (token.type) 2255 { 2256 case Token.Long: 2257 case Token.Short: 2258 case Token.Unsigned: 2259 return integerType (entry); 2260 case Token.Char: 2261 case Token.Wchar: 2262 return charType(); 2263 case Token.Boolean: 2264 return booleanType(); 2265 case Token.Enum: 2266 return enumType (entry); 2267 case Token.Identifier: 2268 case Token.DoubleColon: 2269 ret = scopedName (entry, stFactory.primitiveEntry ()); 2270 if (hasArrayInfo (entry.type ())) 2271 ParseException.illegalArray (scanner, "switch"); 2272 SymtabEntry retType = typeOf (ret); 2273 if (!(retType instanceof EnumEntry || retType instanceof PrimitiveEntry)) 2274 ParseException.wrongType (scanner, ret.fullName (), 2275 "long, unsigned long, short, unsigned short, char, boolean, enum", 2276 entryName (ret.type ())); 2277 else if (ret instanceof PrimitiveEntry) 2278 { 2279 SymtabEntry octet = qualifiedEntry ("octet"); 2280 SymtabEntry flt = qualifiedEntry ("float"); 2281 SymtabEntry dbl = qualifiedEntry ("double"); 2282 if (retType == octet || retType == flt || retType == dbl) 2283 ParseException.wrongType (scanner, ret.fullName(), 2284 "long, unsigned long, short, unsigned short, char, boolean, enum", 2285 entryName(ret.type ())); 2286 } 2287 break; 2288 default: 2289 throw ParseException.syntaxError (scanner, new int [] { 2290 Token.Long, Token.Short, Token.Unsigned, Token.Char, 2291 Token.Boolean, Token.Enum, Token.Identifier, 2292 Token.DoubleColon }, token.type); 2293 } 2294 return ret; 2295 } // switchTypeSpec 2296 2297 // This is only used by the union methods 2298 UnionBranch defaultBranch = null; 2299 2300 /** 2301 * 2302 **/ 2303 private void switchBody (UnionEntry entry) throws IOException, ParseException 2304 { 2305 caseProd (entry); 2306 while (!token.equals (Token.RightBrace)) 2307 caseProd (entry); 2308 entry.defaultBranch ((defaultBranch == null) ? null : defaultBranch.typedef); 2309 defaultBranch = null; 2310 } // switchBody 2311 2312 /** 2313 * 2314 **/ 2315 private void caseProd (UnionEntry entry) throws IOException, ParseException 2316 { 2317 UnionBranch branch = new UnionBranch (); 2318 entry.addBranch (branch); 2319 caseLabel (entry, branch); 2320 while (token.equals (Token.Case) || token.equals (Token.Default)) 2321 caseLabel (entry, branch); 2322 elementSpec (entry, branch); 2323 match (Token.Semicolon); 2324 } // caseProd 2325 2326 /** 2327 * 2328 **/ 2329 private void caseLabel (UnionEntry entry, UnionBranch branch) throws IOException, ParseException 2330 { 2331 if (token.type == Token.Case) 2332 { 2333 match (Token.Case); 2334 ConstEntry tmpEntry = stFactory.constEntry (entry, (IDLID)repIDStack.peek ()); 2335 tmpEntry.sourceFile (scanner.fileEntry ()); 2336 tmpEntry.type (entry); 2337 2338 Expression label; 2339 SymtabEntry type = typeOf (entry.type ()); 2340 if (type instanceof EnumEntry) 2341 label = matchEnum ((EnumEntry)type); 2342 else 2343 { 2344 label = constExp (tmpEntry); 2345 verifyConstType (label, type); 2346 } 2347 if (entry.has (label)) 2348 ParseException.branchLabel (scanner, label.rep ()); 2349 branch.labels.addElement (label); 2350 match (Token.Colon); 2351 } 2352 else if (token.type == Token.Default) 2353 { 2354 match (Token.Default); 2355 match (Token.Colon); 2356 if (entry.defaultBranch () != null) 2357 ParseException.alreadyDefaulted (scanner); 2358 branch.isDefault = true; 2359 defaultBranch = branch; 2360 } 2361 else 2362 throw ParseException.syntaxError (scanner, new int [] { Token.Case, Token.Default }, token.type); 2363 } // caselabel 2364 2365 /** 2366 * 2367 **/ 2368 private Expression matchEnum (EnumEntry entry) throws IOException, ParseException 2369 { 2370 // Get the symbol table entry for the case label based on the 2371 // scope of the EnumEntry, NOT the UnionEntry (the union could be 2372 // in a different scope than the enum). Given 2373 // module M { enum E {A, B, C, D}; }; 2374 // a case label for A could be one of the following: 2375 // case A: 2376 // case M::A: 2377 // case ::M::A: 2378 SymtabEntry label = scopedName (entry.container(), new SymtabEntry ()); 2379 return exprFactory.terminal (label.name (), false); 2380 } // matchEnum 2381 2382 /** 2383 * 2384 **/ 2385 private void elementSpec (UnionEntry entry, UnionBranch branch) throws IOException, ParseException 2386 { 2387 TypedefEntry typedef = stFactory.typedefEntry (entry, (IDLID)repIDStack.peek ()); 2388 typedef.sourceFile (scanner.fileEntry ()); 2389 // Comment must immediately precede <type_spec> lexeme 2390 typedef.comment (token.comment); 2391 typedef.type (typeSpec (entry)); 2392 if (typedef.type () == entry) 2393 throw ParseException.recursive (scanner, entry.fullName (), (token.name == null)? "" : token.name); 2394 // <d46094> Exception cannot appear within a struct, union, or exception 2395 if (typeOf (typedef) instanceof ExceptionEntry) 2396 throw ParseException.illegalException (scanner, entryName (entry)); 2397 declarator (typedef); 2398 branch.typedef = typedef; 2399 // Ensure a branch with the same name doesn't already exist. 2400 if (entry.has (typedef)) 2401 ParseException.branchName (scanner, typedef.name ()); 2402 } // elementSpec 2403 2404 /** 2405 * 2406 **/ 2407 private EnumEntry enumType (SymtabEntry entry) throws IOException, ParseException 2408 { 2409 match (Token.Enum); 2410 EnumEntry enumEntry = newEnumEntry (entry); 2411 // comment must immediately precede "enum" keyword 2412 enumEntry.comment (tokenHistory.lookBack (1).comment); 2413 enumEntry.name (token.name); 2414 match (Token.Identifier); 2415 prep.openScope (enumEntry); 2416 match (Token.LeftBrace); 2417 if (isntInStringList (enumEntry.elements (), token.name)) 2418 { 2419 enumEntry.addElement (token.name); 2420 SymtabEntry element = new SymtabEntry (entry, (IDLID)repIDStack.peek ()); 2421 // if block taken from EnumEntry ctor 2422 if (element.module ().equals ("")) 2423 element.module (element.name ()); 2424 else if (!element.name ().equals ("")) 2425 element.module (element.module () + "/" + element.name ()); 2426 element.name (token.name); 2427 // <d50237> Place the SymtabEntry representing this enumeration 2428 // contant into the SymtabEntry defining its scope (e.g., InterfaceEntry, 2429 // ValueEntry, etc.) rather than the SymtabEntry passed in, which 2430 // may not define the contant's scope (e.g., TypedefEntry). 2431 //pigeonhole (entry, element); } <daz> 2432 pigeonhole (enumEntry.container (), element); 2433 } 2434 match (Token.Identifier); 2435 enumType2 (enumEntry); 2436 prep.closeScope (enumEntry); 2437 match (Token.RightBrace); 2438 return enumEntry; 2439 } // enumType 2440 2441 /** 2442 * 2443 **/ 2444 private void enumType2 (EnumEntry entry) throws IOException, ParseException 2445 { 2446 while (token.type == Token.Comma) 2447 { 2448 match (Token.Comma); 2449 String name = token.name; 2450 match (Token.Identifier); 2451 if (isntInStringList (entry.elements (), name)) 2452 { 2453 entry.addElement (name); 2454 SymtabEntry element = new SymtabEntry (entry.container (), (IDLID)repIDStack.peek ()); 2455 // if block taken from EnumEntry ctor: 2456 if (element.module ().equals ("")) 2457 element.module (element.name ()); 2458 else if (!element.name().equals ("")) 2459 element.module (element.module () + "/" + element.name ()); 2460 element.name (name); 2461 pigeonhole (entry.container (), element); 2462 } 2463 } 2464 } // enumType2 2465 2466 /** 2467 * 2468 **/ 2469 private SequenceEntry sequenceType (SymtabEntry entry) throws IOException, ParseException 2470 { 2471 match (Token.Sequence); 2472 match (Token.LessThan); 2473 2474 SequenceEntry newEntry = newSequenceEntry (entry); 2475 SymtabEntry tsentry = simpleTypeSpec (newEntry, false ); 2476 newEntry.type (tsentry); 2477 if (!tsentry.isReferencable()) { 2478 // This is a sequence type that is referencing an 2479 // incomplete forward declaration of a struct or 2480 // union. Save the sequence in a list for later 2481 // backpatching. 2482 try { 2483 List fwdTypes = (List)tsentry.dynamicVariable( ftlKey ) ; 2484 if (fwdTypes == null) { 2485 fwdTypes = new ArrayList() ; 2486 tsentry.dynamicVariable( ftlKey, fwdTypes ) ; 2487 } 2488 fwdTypes.add( newEntry ) ; 2489 } catch (NoSuchFieldException exc) { 2490 throw new IllegalStateException() ; 2491 } 2492 } 2493 2494 if (token.type == Token.Comma) 2495 { 2496 match (Token.Comma); 2497 ConstEntry tmpEntry = stFactory.constEntry (newEntry, (IDLID)repIDStack.peek ()); 2498 tmpEntry.sourceFile (scanner.fileEntry ()); 2499 tmpEntry.type (qualifiedEntry ("long")); 2500 newEntry.maxSize (positiveIntConst (tmpEntry)); 2501 verifyConstType (newEntry.maxSize(), qualifiedEntry ("long")); 2502 } 2503 match (Token.GreaterThan); 2504 return newEntry; 2505 } // sequenceType 2506 2507 /** 2508 * 2509 **/ 2510 private StringEntry stringType (SymtabEntry entry) throws IOException, ParseException 2511 { 2512 StringEntry string = stFactory.stringEntry (); 2513 if (token.type == Token.String) 2514 { 2515 string.name (overrideName ("string")); 2516 match (Token.String); 2517 } 2518 else 2519 { 2520 string.name (overrideName ("wstring")); 2521 match (Token.Wstring); 2522 } 2523 string.maxSize (stringType2 (entry)); 2524 return string; 2525 } // stringType 2526 2527 /** 2528 * 2529 **/ 2530 private Expression stringType2 (SymtabEntry entry) throws IOException, ParseException 2531 { 2532 if (token.type == Token.LessThan) 2533 { 2534 match (Token.LessThan); 2535 2536 // START IBM.11417 failure in the IDL compiler 2537 //Expression maxSize = positiveIntConst (entry); IBM.11417 2538 2539 ConstEntry tmpEntry = stFactory.constEntry (entry, (IDLID)repIDStack.peek 2540()); 2541 tmpEntry.sourceFile (scanner.fileEntry ()); 2542 tmpEntry.type (qualifiedEntry ("long")); 2543 Expression maxSize = positiveIntConst (tmpEntry); 2544 2545 // END IBM.11417 2546 2547 verifyConstType (maxSize, qualifiedEntry ("long")); 2548 match (Token.GreaterThan); 2549 return maxSize; 2550 } 2551 return null; 2552 } // stringType2 2553 2554 /** 2555 * 2556 **/ 2557 private void fixedArraySize (TypedefEntry entry) throws IOException, ParseException 2558 { 2559 match (Token.LeftBracket); 2560 ConstEntry tmpEntry = stFactory.constEntry (entry, (IDLID)repIDStack.peek ()); 2561 tmpEntry.sourceFile (scanner.fileEntry ()); 2562 // <d58058> Set type of tmpExpr to "long", which is the array index type. 2563 // Previously, this type was erroneously set to the array element type. 2564 //tmpEntry.type (entry.type ()); 2565 tmpEntry.type (qualifiedEntry ("long")); 2566 Expression expr = positiveIntConst (tmpEntry); 2567 entry.addArrayInfo (expr); 2568 verifyConstType (expr, qualifiedEntry ("long")); 2569 match (Token.RightBracket); 2570 } // fixedArraySize 2571 2572 /** 2573 * 2574 **/ 2575 private void attrDcl (InterfaceEntry entry) throws IOException, ParseException 2576 { 2577 AttributeEntry attribute = stFactory.attributeEntry (entry, (IDLID)repIDStack.peek ()); 2578 attribute.sourceFile (scanner.fileEntry ()); 2579 // Comment must immediately precede the "attribute" keyword. Save the 2580 // comment preceding the declaration for use below. 2581 attribute.comment (token.comment); 2582 Comment dclComment = attribute.comment (); 2583 2584 if (token.type == Token.Readonly) 2585 { 2586 match (Token.Readonly); 2587 attribute.readOnly (true); 2588 } 2589 match (Token.Attribute); 2590 attribute.type (paramTypeSpec (attribute)); 2591 attribute.name (token.name); 2592 // Override declaration comment if attribute identifier is commented 2593 if (!token.comment.text ().equals ("")) 2594 attribute.comment (token.comment); 2595 entry.methodsAddElement (attribute, scanner); 2596 pigeonholeMethod (entry, attribute); 2597 // Declaration comment was overriden: 2598 if (!token.comment.text ().equals ("")) 2599 { 2600 // Create a temporary attribute with declaration comment so cloning in 2601 // attrdcl2() can use declaration comment as default. 2602 AttributeEntry attributeClone = (AttributeEntry) attribute.clone (); 2603 attributeClone.comment (dclComment); 2604 2605 match (Token.Identifier); 2606 attrDcl2 (entry, attributeClone); 2607 } 2608 else 2609 { 2610 match (Token.Identifier); 2611 attrDcl2 (entry, attribute); 2612 } 2613 //match (Token.Identifier); 2614 //attrDcl2 (entry, attribute); 2615 } // attrDcl 2616 2617 /** 2618 * 2619 **/ 2620 private void attrDcl2 (InterfaceEntry entry, AttributeEntry clone) 2621 throws IOException, ParseException 2622 { 2623 while (token.type == Token.Comma) 2624 { 2625 match (Token.Comma); 2626 AttributeEntry attribute = (AttributeEntry)clone.clone (); 2627 attribute.name (token.name); 2628 // Override the declaration comment (i.e., that preceding the 2629 // "attribute" keyword) if the attribute identifier is commented. 2630 if (!token.comment.text ().equals ("")) 2631 attribute.comment (token.comment); 2632 entry.methodsAddElement (attribute, scanner); 2633 pigeonholeMethod (entry, attribute); 2634 match (Token.Identifier); 2635 } 2636 } // attrDcl2 2637 2638 /** 2639 * 2640 **/ 2641 private void exceptDcl (SymtabEntry entry) throws IOException, ParseException 2642 { 2643 match (Token.Exception); 2644 repIDStack.push (((IDLID)repIDStack.peek ()).clone ()); 2645 ExceptionEntry exceptEntry = stFactory.exceptionEntry (entry, (IDLID)repIDStack.peek ()); 2646 ((IDLID)repIDStack.peek ()).appendToName (token.name); 2647 exceptEntry.sourceFile (scanner.fileEntry ()); 2648 // Comment must immediately precede "exception" keyword 2649 exceptEntry.comment (tokenHistory.lookBack (1).comment); 2650 exceptEntry.name (token.name); 2651 match (Token.Identifier); 2652 pigeonhole (entry, exceptEntry); 2653 if (token.equals (Token.LeftBrace)) 2654 { 2655 prep.openScope (exceptEntry); 2656 match (Token.LeftBrace); 2657 memberList2 (exceptEntry); 2658 prep.closeScope (exceptEntry); 2659 match (Token.RightBrace); 2660 repIDStack.pop (); 2661 } 2662 else 2663 throw ParseException.syntaxError (scanner, Token.LeftBrace,token.type); 2664 } // exceptDcl 2665 2666 /** 2667 * 2668 **/ 2669 private void opDcl (InterfaceEntry entry) throws IOException, ParseException 2670 { 2671 MethodEntry method = stFactory.methodEntry (entry, (IDLID)repIDStack.peek ()); 2672 method.sourceFile (scanner.fileEntry ()); 2673 // Comment must immediately precede "oneway" keyword or <return_type_spec> 2674 method.comment (token.comment); 2675 if (token.type == Token.Oneway) 2676 { 2677 match (Token.Oneway); 2678 method.oneway (true); 2679 } 2680 method.type (opTypeSpec (method)); 2681 repIDStack.push (((IDLID)repIDStack.peek ()).clone ()); 2682 ((IDLID)repIDStack.peek ()).appendToName (token.name); 2683 method.name (token.name); 2684 entry.methodsAddElement (method, scanner); 2685 pigeonholeMethod (entry, method); 2686 opDcl2 (method); 2687 if (method.oneway ()) 2688 checkIfOpLegalForOneway (method); 2689 repIDStack.pop (); 2690 } // opDcl 2691 2692 /** 2693 * 2694 **/ 2695 private void checkIfOpLegalForOneway (MethodEntry method) 2696 { 2697 boolean notLegal = false; 2698 if ((method.type() != null) || 2699 (method.exceptions().size() != 0)) notLegal = true; 2700 else 2701 { 2702 for (Enumeration e = method.parameters().elements(); e.hasMoreElements();) 2703 { 2704 if (((ParameterEntry)e.nextElement ()).passType () != ParameterEntry.In) 2705 { 2706 notLegal = true; 2707 break; 2708 } 2709 } 2710 } 2711 if (notLegal) 2712 ParseException.oneway (scanner, method.name ()); 2713 } // checkifOpLegalForOneway 2714 2715 /** 2716 * 2717 **/ 2718 private void opDcl2 (MethodEntry method) throws IOException, ParseException 2719 { 2720 if (token.equals (Token.MacroIdentifier)) 2721 { 2722 match (Token.MacroIdentifier); 2723 parameterDcls2 (method); 2724 } 2725 else 2726 { 2727 match (Token.Identifier); 2728 parameterDcls (method); 2729 } 2730 opDcl3 (method); 2731 } // opDcl2 2732 2733 /** 2734 * 2735 **/ 2736 private void opDcl3 (MethodEntry entry) throws IOException, ParseException 2737 { 2738 if (token.type != Token.Semicolon) 2739 { 2740 if (!token.equals (Token.Raises) && !token.equals (Token.Context)) 2741 throw ParseException.syntaxError (scanner, new int [] { 2742 Token.Raises, Token.Context, Token.Semicolon }, token.type); 2743 if (token.type == Token.Raises) 2744 raisesExpr (entry); 2745 if (token.type == Token.Context) 2746 contextExpr (entry); 2747 } 2748 } // opDcl3 2749 2750 /** 2751 * 2752 **/ 2753 private SymtabEntry opTypeSpec (SymtabEntry entry) throws IOException, ParseException 2754 { 2755 SymtabEntry ret = null; 2756 if (token.type == Token.Void) 2757 match (Token.Void); 2758 else 2759 ret = paramTypeSpec (entry); 2760 return ret; 2761 } // opTypeSpec 2762 2763 /** 2764 * 2765 **/ 2766 private void parameterDcls (MethodEntry entry) throws IOException, ParseException 2767 { 2768 match (Token.LeftParen); 2769 parameterDcls2 (entry); 2770 } // parameterDcls 2771 2772 /** 2773 * 2774 **/ 2775 private void parameterDcls2 (MethodEntry entry) throws IOException, ParseException 2776 { 2777 if (token.type == Token.RightParen) 2778 match (Token.RightParen); 2779 else 2780 { 2781 paramDcl (entry); 2782 while (token.type == Token.Comma) 2783 { 2784 match (Token.Comma); 2785 paramDcl (entry); 2786 } 2787 match (Token.RightParen); 2788 } 2789 } // paraneterDcls2 2790 2791 /** 2792 * 2793 **/ 2794 private void paramDcl (MethodEntry entry) throws IOException, ParseException 2795 { 2796 ParameterEntry parmEntry = stFactory.parameterEntry (entry, (IDLID)repIDStack.peek ()); 2797 parmEntry.sourceFile (scanner.fileEntry ()); 2798 // Comment must immeiately precede the parameter attribute 2799 parmEntry.comment (token.comment); 2800 paramAttribute (parmEntry); 2801 parmEntry.type (paramTypeSpec (entry)); 2802 parmEntry.name (token.name); 2803 match (Token.Identifier); 2804 if (isntInList (entry.parameters (), parmEntry.name ())) 2805 entry.addParameter (parmEntry); 2806 } // paramDcl 2807 2808 /** 2809 * 2810 **/ 2811 private void paramAttribute (ParameterEntry entry) throws IOException, ParseException 2812 { 2813 if (token.type == Token.In) 2814 { 2815 entry.passType (ParameterEntry.In); 2816 match (Token.In); 2817 } 2818 else if (token.type == Token.Out) 2819 { 2820 entry.passType (ParameterEntry.Out); 2821 match (Token.Out); 2822 } 2823 else if (token.type == Token.Inout) 2824 { 2825 entry.passType (ParameterEntry.Inout); 2826 match (Token.Inout); 2827 } 2828 else 2829 throw ParseException.syntaxError (scanner, new int [] { 2830 Token.In, Token.Out, Token.Inout }, token.type); 2831 } // paramAttribute 2832 2833 /** 2834 * 2835 **/ 2836 private void raisesExpr (MethodEntry entry) throws IOException, ParseException 2837 { 2838 match (Token.Raises); 2839 match (Token.LeftParen); 2840 // Comment must immediately precede <scoped_name> for exception 2841 Comment tempComment = token.comment; 2842 SymtabEntry exception = scopedName(entry.container (), stFactory.exceptionEntry ()); 2843 if (typeOf (exception) instanceof ExceptionEntry) 2844 { 2845 // Comment must immediately precede <scoped_name> for exception 2846 exception.comment (tempComment); 2847 if (isntInList (entry.exceptions (), exception)) 2848 entry.exceptionsAddElement ((ExceptionEntry) exception); 2849 } 2850 else 2851 ParseException.wrongType (scanner, exception.fullName(), 2852 "exception", entryName (exception.type ())); 2853 raisesExpr2 (entry); 2854 match (Token.RightParen); 2855 } // raisesExpr 2856 2857 /** 2858 * 2859 **/ 2860 private void raisesExpr2 (MethodEntry entry) throws IOException, ParseException 2861 { 2862 while (token.type == Token.Comma) 2863 { 2864 match (Token.Comma); 2865 // Comment must immediately precede <scoped_name> of exception 2866 Comment tempComment = token.comment; 2867 SymtabEntry exception = scopedName (entry.container (), stFactory.exceptionEntry ()); 2868 if (typeOf (exception) instanceof ExceptionEntry) 2869 { 2870 // Comment must immediately precede <scoped_name> of exception 2871 exception.comment (tempComment); 2872 if (isntInList (entry.exceptions (), exception)) 2873 entry.addException ((ExceptionEntry)exception); 2874 } 2875 else 2876 ParseException.wrongType (scanner, exception.fullName (), 2877 "exception", entryName (exception.type ())); 2878 } 2879 } // raisesExpr2 2880 2881 /** 2882 * 2883 **/ 2884 private void contextExpr (MethodEntry entry) throws IOException, ParseException 2885 { 2886 match (Token.Context); 2887 match (Token.LeftParen); 2888 String stringLit = (String)stringLiteral ().value (); 2889 if (isntInStringList (entry.contexts (), stringLit)) 2890 entry.addContext (stringLit); 2891 contextExpr2 (entry); 2892 match (Token.RightParen); 2893 } // contextExpr 2894 2895 2896 private void contextExpr2 (MethodEntry entry) throws IOException, ParseException 2897 { 2898 while (token.type == Token.Comma) 2899 { 2900 match (Token.Comma); 2901 String stringLit = (String)stringLiteral ().value (); 2902 if (isntInStringList (entry.contexts (), stringLit)) 2903 entry.addContext (stringLit); 2904 } 2905 } // contextExpr2 2906 2907 /** 2908 * 2909 **/ 2910 private SymtabEntry paramTypeSpec (SymtabEntry entry) throws IOException, ParseException 2911 { 2912 SymtabEntry ret = null; 2913 switch (token.type) 2914 { 2915 case Token.Float: 2916 case Token.Double: 2917 case Token.Long: 2918 case Token.Short: 2919 case Token.Unsigned: 2920 case Token.Char: 2921 case Token.Wchar: 2922 case Token.Boolean: 2923 case Token.Octet: 2924 case Token.Any: 2925 return baseTypeSpec (entry); 2926 case Token.String: 2927 case Token.Wstring: 2928 return stringType (entry); 2929 case Token.Identifier: 2930 case Token.Object: 2931 // <f46082.40> 2932 case Token.ValueBase: 2933 case Token.DoubleColon: 2934 ret = scopedName (entry.container (), stFactory.primitiveEntry ()); 2935 if (typeOf (ret) instanceof AttributeEntry) 2936 //ParseException.attributeParamType (scanner); 2937 ParseException.attributeNotType (scanner, ret.name ()); 2938 else // <d60942> 2939 if (typeOf (ret) instanceof MethodEntry) 2940 ParseException.operationNotType (scanner, ret.name ()); 2941 2942 //if (!(returnType instanceof PrimitiveEntry || 2943 // returnType instanceof StringEntry)) 2944 //ParseException.wrongType (scanner, ret.fullName(), 2945 // "primitive or string", entryName (ret.type())); 2946 break; 2947 default: 2948 throw ParseException.syntaxError (scanner, new int [] { 2949 Token.Float, Token.Double, Token.Long, Token.Short, 2950 Token.Unsigned, Token.Char, Token.Wchar, Token.Boolean, 2951 Token.Octet, Token.Any, Token.String, Token.Wstring, 2952 Token.Identifier, Token.DoubleColon, Token.ValueBase }, token.type); 2953 } 2954 return ret; 2955 } // paramTypeSpec 2956 2957 /** 2958 * 2959 **/ 2960 private void match (int type) throws IOException, ParseException 2961 { 2962 ParseException exception = null; 2963 if (!token.equals (type)) 2964 { 2965 exception = ParseException.syntaxError (scanner, type, token.type); 2966 // Missing a semicolon is a common error. If a semicolon was expected, 2967 // assume it exists and keep the current token (don't get the next one). 2968 // BEWARE!!! THIS HAS THE POTENTIAL FOR AN INFINITE LOOP! 2969 if (type == Token.Semicolon) 2970 return; 2971 } 2972 // <f46082.40> Unecessary due to new valueElement() algorithm. 2973 //if (!tokenStack.empty()) 2974 //{ 2975 // token = (Token)tokenStack.pop (); 2976 // return; 2977 //} 2978 2979 // Fetch the next token. 2980 token = scanner.getToken (); 2981 2982 // <d62023> Issue warnings about tokens. 2983 issueTokenWarnings (); 2984 2985 // Maintain history of most recent tokens. 2986 tokenHistory.insert (token); 2987 2988 // <d59166> Identifiers that collide with keywords are illegal. Note 2989 // that escaped identifers never collide! 2990 /* 2991 if (token.collidesWithKeyword ()) 2992 { 2993 // <f60858.1> Issue a warning only 2994 if (corbaLevel <= 2.2f) 2995 ParseException.keywordCollisionWarning (scanner, token.name); 2996 else 2997 exception = ParseException.keywordCollision (scanner, token.name); 2998 } 2999 */ 3000 3001 while (token.isDirective ()) 3002 token = prep.process (token); 3003 3004 // If the token is a defined thingy, scan the defined string 3005 // instead of the input stream for a while. 3006 if (token.equals (Token.Identifier) || token.equals (Token.MacroIdentifier)) 3007 { 3008 String string = (String)symbols.get (token.name); 3009 if (string != null && !string.equals ("")) 3010 { 3011 // If this is a macro, parse the macro 3012 if (macros.contains (token.name)) 3013 { 3014 scanner.scanString (prep.expandMacro (string, token)); 3015 match (token.type); 3016 } 3017 else // This is just a normal define. 3018 { 3019 scanner.scanString (string); 3020 match (token.type); 3021 } 3022 } 3023 } 3024 if (exception != null) 3025 throw exception; 3026 } // match 3027 3028 // <d62023> 3029 /** 3030 * Issue warnings according to attributes of current Token. 3031 **/ 3032 private void issueTokenWarnings () 3033 { 3034 if (noWarn) 3035 return; 3036 3037 if ((token.equals (Token.Identifier) || token.equals (Token.MacroIdentifier)) 3038 && !token.isEscaped ()) 3039 { 3040 // Identifier collision with keyword in another release. 3041 // Identifier collision with keyword in letter, but not in case. 3042 if (token.collidesWithKeyword ()) 3043 ParseException.warning (scanner, Util.getMessage ("Migration.keywordCollision", token.name)); 3044 } 3045 // Deprecated keyword. 3046 if (token.isKeyword () && token.isDeprecated ()) 3047 ParseException.warning (scanner, Util.getMessage ("Deprecated.keyword", token.toString ())); 3048 } // issueTokenWarnings 3049 3050 /** 3051 * 3052 **/ 3053 private ModuleEntry newModule (ModuleEntry oldEntry) 3054 { 3055 ModuleEntry entry = stFactory.moduleEntry (oldEntry, (IDLID)repIDStack.peek ()); 3056 entry.sourceFile (scanner.fileEntry ()); 3057 entry.name (token.name); 3058 // If this named module already exists, just reopen it. 3059 /* <46082.46.01> if cppModule, always create new module entry */ 3060 SymtabEntry prevEntry = (SymtabEntry) symbolTable.get (entry.fullName ()); 3061 if (!cppModule && prevEntry != null && prevEntry instanceof ModuleEntry) 3062 { 3063 // A module has been reopened, return that ModuleEntry. 3064 entry = (ModuleEntry) prevEntry; 3065 if (oldEntry == topLevelModule) 3066 { 3067 // Do a little checking: 3068 if (!entry.emit ()) 3069 // The entry module is being reopened to put new stuff into it. 3070 // The module itself is not marked as "emit", but the new stuff 3071 // may be, so put the module on the emitList (add it to topLevelModule). 3072 addToContainer (oldEntry, entry); 3073 else if (!oldEntry.contained().contains (entry)) 3074 // <d50767> The entry module being reopened is to be emitted, but 3075 // will not be placed on the emitList! I.E., it was not added to 3076 // topLevelModule. Occurs when a generator manually inserts 3077 // ModuleEntrys into the symbol table (e.g., org; see preParse() 3078 // in ...idl.toJava.Compile). <daz> 3079 addToContainer (oldEntry, entry); 3080 } 3081 } 3082 else 3083 pigeonhole (oldEntry, entry); 3084 return entry; 3085 } // newModule 3086 3087 /** 3088 * 3089 **/ 3090 private EnumEntry newEnumEntry (SymtabEntry oldEntry) 3091 { 3092 EnumEntry entry = stFactory.enumEntry (oldEntry, (IDLID)repIDStack.peek ()); 3093 entry.sourceFile (scanner.fileEntry ()); 3094 entry.name (token.name); 3095 pigeonhole (oldEntry, entry); 3096 return entry; 3097 } // newEnumEntry 3098 3099 /** 3100 * 3101 **/ 3102 private SequenceEntry newSequenceEntry (SymtabEntry oldEntry) 3103 { 3104 SequenceEntry entry = stFactory.sequenceEntry (oldEntry, (IDLID)repIDStack.peek ()); 3105 entry.sourceFile (scanner.fileEntry ()); 3106 entry.name (""); 3107 pigeonhole (oldEntry, entry); 3108 return entry; 3109 } // newSequenceEntry 3110 3111 private void updateSymbolTable( String fullName, SymtabEntry entry, boolean lcCheck ) 3112 { 3113 // Check for case-insensitive collision (IDL error). 3114 String lcFullName = fullName.toLowerCase(); 3115 if (lcCheck) 3116 if (lcSymbolTable.get (lcFullName) != null) { 3117 ParseException.alreadyDeclared (scanner, fullName); 3118 } 3119 symbolTable.put (fullName, entry); 3120 lcSymbolTable.put (lcFullName, entry); 3121 // <d59809> Allow fully-qualified CORBA types to be resolved by mapping 3122 // short name (e.g., CORBA/StringValue) to long name, actual name. 3123 String omgPrefix = "org/omg/CORBA" ; 3124 if (fullName.startsWith (omgPrefix)) { 3125 overrideNames.put ( 3126 "CORBA" + fullName.substring (omgPrefix.length()), fullName); 3127 } 3128 } 3129 3130 private void pigeonhole (SymtabEntry container, SymtabEntry entry) 3131 { 3132 if (entry.name().equals ("")) 3133 entry.name (unknownNamePrefix + ++sequence); 3134 3135 // If this object is not in the overrides list, then it is 3136 // ok to put it in the table (if it IS in the overrides list, 3137 // it is already in the table under a different name). 3138 String fullName = entry.fullName(); 3139 if (overrideNames.get (fullName) == null) { 3140 addToContainer (container, entry); 3141 3142 // It is an error is this name already exists in the symbol 3143 // table, unless this is a redefinition of a forward decl. 3144 // Re-opening a module is also legal, but not handled here. 3145 SymtabEntry oldEntry = (SymtabEntry) symbolTable.get (fullName); 3146 3147 if (oldEntry == null) { 3148 updateSymbolTable( fullName, entry, true ) ; 3149 } else if (oldEntry instanceof ForwardEntry && 3150 entry instanceof InterfaceEntry) { 3151 3152 String repIDPrefix = ((IDLID)entry.repositoryID ()).prefix (); 3153 String oldRepIDPrefix = ((IDLID)oldEntry.repositoryID ()).prefix (); 3154 if (repIDPrefix.equals (oldRepIDPrefix)) { 3155 updateSymbolTable( fullName, entry, false ) ; 3156 } else { 3157 ParseException.badRepIDPrefix (scanner, fullName, 3158 oldRepIDPrefix, repIDPrefix); 3159 } 3160 } else if (entry instanceof ForwardEntry && 3161 (oldEntry instanceof InterfaceEntry || 3162 oldEntry instanceof ForwardEntry)) { 3163 if (oldEntry instanceof ForwardEntry && 3164 entry.repositoryID () instanceof IDLID && 3165 oldEntry.repositoryID () instanceof IDLID) { 3166 3167 String repIDPrefix = 3168 ((IDLID)entry.repositoryID ()).prefix (); 3169 String oldRepIDPrefix = 3170 ((IDLID)oldEntry.repositoryID ()).prefix (); 3171 3172 if (!(repIDPrefix.equals (oldRepIDPrefix))) { 3173 // Disallow multiple ForwardEntry's having same Repository 3174 // ID prefixes (CORBA 2.3). 3175 ParseException.badRepIDPrefix (scanner, fullName, 3176 oldRepIDPrefix, repIDPrefix); 3177 } 3178 } 3179 } else if (cppModule && entry instanceof ModuleEntry && 3180 oldEntry instanceof ModuleEntry) { 3181 // Allow multiple ModuleEntrys when user submits 3182 // the -cppModule flag. 3183 } else if (fullName.startsWith ("org/omg/CORBA") || 3184 fullName.startsWith ("CORBA")) { 3185 // Ignore CORBA PIDL types entered at preParse() by generator. 3186 } else if (isForwardable( oldEntry, entry )) { 3187 // Both oldEntry and entry are structs or unions. 3188 // Legality depends on isReferencable on the two entries: 3189 // oldEntry Entry 3190 // T T ERROR alreadyDeclared 3191 // T F legal fwd decl 3192 // F T if defined in same file legal, 3193 // otherwise ERROR 3194 // F F legal fwd decl 3195 if (oldEntry.isReferencable() && entry.isReferencable()) 3196 ParseException.alreadyDeclared (scanner, fullName); 3197 3198 if (entry.isReferencable()) { 3199 String firstFile = 3200 oldEntry.sourceFile().absFilename() ; 3201 String defFile = 3202 entry.sourceFile().absFilename() ; 3203 if (!firstFile.equals( defFile )) 3204 ParseException.declNotInSameFile( scanner, 3205 fullName, firstFile ) ; 3206 else { 3207 updateSymbolTable( fullName, entry, false ) ; 3208 3209 List oldRefList ; 3210 3211 try { 3212 oldRefList = (List)oldEntry.dynamicVariable( 3213 ftlKey ) ; 3214 } catch (NoSuchFieldException exc) { 3215 throw new IllegalStateException() ; 3216 } 3217 3218 if (oldRefList != null) { 3219 // Update entries in backpatch list 3220 Iterator iter = oldRefList.iterator() ; 3221 while (iter.hasNext()) { 3222 SymtabEntry elem = (SymtabEntry)iter.next() ; 3223 elem.type( entry ) ; 3224 } 3225 } 3226 } 3227 } 3228 } else { 3229 ParseException.alreadyDeclared (scanner, fullName); 3230 } 3231 } 3232 } // pigeonhole 3233 3234 private boolean isForwardable( SymtabEntry oldEntry, 3235 SymtabEntry entry ) 3236 { 3237 return ((oldEntry instanceof StructEntry) && 3238 (entry instanceof StructEntry)) || 3239 ((oldEntry instanceof UnionEntry) && 3240 (entry instanceof UnionEntry)) ; 3241 } 3242 3243 // pigeonhole checks to see if this entry is already in the symbol 3244 // table and generates an error if it is. Methods must be checked 3245 // not only against the symbol table but also against their 3246 // interface's parent's methods. This is done in InterfaceEntry. 3247 // verifyMethod, so no checking need be done here. 3248 3249 /** 3250 * 3251 **/ 3252 private void pigeonholeMethod (InterfaceEntry container, MethodEntry entry) 3253 { 3254 if (entry.name ().equals ("")) 3255 entry.name (unknownNamePrefix + ++sequence); 3256 3257 // If this object is not in the overrides list, then it is 3258 // ok to put it in the table (if it IS in the overrides list, 3259 // it is already in the table under a different name). 3260 String fullName = entry.fullName (); 3261 if (overrideNames.get (fullName) == null) 3262 { 3263 addToContainer (container, entry); 3264 String lcFullName = fullName.toLowerCase (); 3265 symbolTable.put (fullName, entry); 3266 lcSymbolTable.put (lcFullName, entry); 3267 // <d59809> Allow fully-qualified CORBA types to be resolved by mapping 3268 // short name (e.g., CORBA/StringValue) to long name, actual name. 3269 if (fullName.startsWith ("org/omg/CORBA")) 3270 overrideNames.put ("CORBA" + fullName.substring (13), fullName); 3271 } 3272 } // pigeonholeMethod 3273 3274 /** 3275 * 3276 **/ 3277 private void addToContainer (SymtabEntry container, SymtabEntry contained) 3278 { 3279 if (container instanceof ModuleEntry) 3280 ((ModuleEntry)container).addContained (contained); 3281 else if (container instanceof InterfaceEntry) 3282 ((InterfaceEntry)container).addContained (contained); 3283 else if (container instanceof StructEntry) 3284 ((StructEntry)container).addContained (contained); 3285 else if (container instanceof UnionEntry) 3286 ((UnionEntry)container).addContained (contained); 3287 else if (container instanceof SequenceEntry) 3288 ((SequenceEntry)container).addContained (contained); 3289 } // addToContainer 3290 3291 // NOTE: qualifiedEntry/partlyQualifiedEntry/unqualifiedEntry and 3292 // their court could probably use some performance improvements, 3293 // but I'm scared to touch anything. It's the most complex bit of 3294 // code in this parser. 3295 3296 // The qualified named type is searched for in the following order: 3297 // 1. OverrideNames 3298 // 2. Global scope 3299 // 3. Inheritance scope (if container is an interface) 3300 // A qualified name is one which begins with :: or is assumed to be 3301 // in the global scope (like long, short, etc). 3302 3303 /** 3304 * 3305 **/ 3306 SymtabEntry qualifiedEntry (String typeName) 3307 { 3308 SymtabEntry type = recursiveQualifiedEntry (typeName); 3309 if (type == null) 3310 // Then it's not anywhere, report the error. 3311 ParseException.undeclaredType (scanner, typeName); 3312 3313 // <d57110> Relax this retriction when parsing ID pragma directive, e.g.. 3314 //else if (type instanceof ModuleEntry) { 3315 else if (type instanceof ModuleEntry && !_isModuleLegalType) 3316 { 3317 // Module's are not valid types. 3318 ParseException.moduleNotType (scanner, typeName); 3319 type = null; 3320 } 3321 return type; 3322 } // qualifiedEntry 3323 3324 /** 3325 * 3326 **/ 3327 SymtabEntry recursiveQualifiedEntry (String typeName) 3328 { 3329 SymtabEntry type = null; 3330 if (typeName != null && !typeName.equals ("void")) 3331 { 3332 int index = typeName.lastIndexOf ('/'); 3333 if (index >= 0) 3334 { 3335 // Figure out if the container of this thing exists, converting any typedefs to interfaces if necessary. 3336 type = recursiveQualifiedEntry (typeName.substring (0, index)); 3337 if (type == null) 3338 return null; 3339 else if (type instanceof TypedefEntry) 3340 typeName = typeOf (type).fullName () + typeName.substring (index); 3341 } 3342 3343 // If we got this far, a container exists, start over looking 3344 // for the thing itself (this is the meat of the method): 3345 type = searchOverrideNames (typeName); 3346 if (type == null) 3347 type = (SymtabEntry) symbolTable.get (typeName); // search global scope: 3348 if (type == null) 3349 type = searchGlobalInheritanceScope (typeName); 3350 } 3351 return type; 3352 } // recursiveQualifiedEntry 3353 3354 // A partially qualified name is of the form <scope>::<name>. 3355 // First the scope is defined (meaning it is fully qualified); 3356 // Then the name is searched for in the scope. 3357 3358 /** 3359 * 3360 **/ 3361 SymtabEntry partlyQualifiedEntry (String typeName, SymtabEntry container) 3362 { 3363 // This is the simple logic of this method: 3364 // type = searchModuleScope (typeName.substring (0, typeName.lastIndexOf ('/')), container); 3365 // type = qualifiedEntry (type.fullName () + typeName.substring (typeName.lastIndexOf ('/'))); 3366 // But searchModuleScope only finds the first module that fits. 3367 // The name might not be in that module but in one further out 3368 // in the module scope. Should others be searched? 3369 SymtabEntry type = null; 3370 if (typeName != null) 3371 { 3372 int index = typeName.lastIndexOf ('/'); 3373 3374 // Figure out if the container of this thing exists, converting any 3375 // typedefs to interfaces if necessary: 3376 type = recursivePQEntry (typeName.substring (0, index), container); 3377 if (type instanceof TypedefEntry) 3378 typeName = typeOf (type).fullName () + typeName.substring (index); 3379 3380 // If we got this far, a container exists, start over looking 3381 // for the thing itself. 3382 3383 if (container != null) 3384 type = searchModuleScope (typeName.substring (0, typeName.lastIndexOf ('/')), container); 3385 if (type == null) 3386 type = qualifiedEntry (typeName); 3387 else 3388 type = qualifiedEntry (type.fullName () + typeName.substring (typeName.lastIndexOf ('/'))); 3389 } 3390 return type; 3391 } // partlyQualifiedEntry 3392 3393 // partlyQualifiedEntry and recursivePQEntry are almost identical. 3394 // They are different because when the recursive one is looking for 3395 // the existence of containers, the error check for a module type 3396 // must not occur (this check is done in qualifiedEntry). Only 3397 // when the full partly qualified name is being processed must this 3398 // check be performed. 3399 3400 /** 3401 * 3402 **/ 3403 SymtabEntry recursivePQEntry (String typeName, SymtabEntry container) 3404 { 3405 SymtabEntry type = null; 3406 if (typeName != null) 3407 { 3408 int index = typeName.lastIndexOf ('/'); 3409 if (index < 0) 3410 type = searchModuleScope (typeName, container); 3411 else 3412 { 3413 // Figure out if the container of this thing exists, converting any 3414 // typedefs to interfaces if necessary: 3415 type = recursivePQEntry (typeName.substring (0, index), container); 3416 if (type == null) 3417 return null; 3418 else if (type instanceof TypedefEntry) 3419 typeName = typeOf (type).fullName () + typeName.substring (index); 3420 3421 // If we got this far, a container exists, start over, looking 3422 // for the thing itself (This is the meat of the method): 3423 if (container != null) 3424 type = searchModuleScope (typeName.substring (0, typeName.lastIndexOf ('/')), container); 3425 if (type == null) 3426 recursiveQualifiedEntry (typeName); 3427 else 3428 type = recursiveQualifiedEntry (type.fullName () + typeName.substring (typeName.lastIndexOf ('/'))); 3429 } 3430 } 3431 return type; 3432 } // recursivePQEntry 3433 3434 // The named type is searched for in the following order: 3435 // 1. Local scope 3436 // 2. Inheritance scope 3437 // 3. OverrideNames 3438 // 4. Module scope 3439 3440 /** 3441 * 3442 **/ 3443 SymtabEntry unqualifiedEntry (String typeName, SymtabEntry container) 3444 { 3445 SymtabEntry type = unqualifiedEntryWMod (typeName, container); 3446 3447 // <d57110> Relax this retriction in special cases, e.g., when 3448 // parsing a ID pragma directive. 3449 //if (type instanceof ModuleEntry) { 3450 if (type instanceof ModuleEntry && !_isModuleLegalType) 3451 { 3452 // Module's are not valid types: 3453 ParseException.moduleNotType (scanner, typeName); 3454 type = null; 3455 } 3456 return type; 3457 } // unqualifiedEntry 3458 3459 /** 3460 * 3461 **/ 3462 SymtabEntry unqualifiedEntryWMod (String typeName, SymtabEntry container) 3463 { 3464 SymtabEntry type = null; 3465 if ((typeName != null) && !typeName.equals ("void")) 3466 { 3467 // Search local scope: 3468 type = (SymtabEntry)symbolTable.get (container.fullName () + '/' + typeName); 3469 if (type == null) 3470 type = searchLocalInheritanceScope (typeName, container); 3471 if (type == null) 3472 type = searchOverrideNames (typeName); 3473 if ((type == null) && (container != null)) 3474 type = searchModuleScope (typeName, container); 3475 if (type == null) 3476 type = searchParentInheritanceScope (typeName, container); 3477 } 3478 if (type == null) 3479 // Then it's not anywhere, report the error: 3480 ParseException.undeclaredType (scanner, typeName); 3481 return type; 3482 } // unqualifiedEntryWMod 3483 3484 /** 3485 * Walks up the enclosing scopes until it finds an interface type. Then, 3486 * searches up that interface inheritance tree for the type definition. 3487 * 3488 * @param name type name to be searched for. 3489 * @param ptype parent type entry. 3490 **/ 3491 SymtabEntry searchParentInheritanceScope(String name, SymtabEntry ptype) { 3492 3493 String cname = ptype.fullName(); 3494 3495 while ((ptype != null) && !(cname.equals ("")) && 3496 !(ptype instanceof InterfaceEntry)) { 3497 int index = cname.lastIndexOf ('/'); 3498 if (index < 0) { 3499 cname = ""; 3500 } else { 3501 cname = cname.substring (0, index); 3502 ptype = (SymtabEntry) symbolTable.get(cname); 3503 } 3504 } 3505 3506 if ((ptype == null) || !(ptype instanceof InterfaceEntry)) { 3507 return null; // could not find an enclosing interface type - give up. 3508 } 3509 3510 // check if the enclosing interface supports the type definition. 3511 String fullName = ptype.fullName () + '/' + name; 3512 SymtabEntry type = (SymtabEntry) symbolTable.get (fullName); 3513 if (type != null) { 3514 return type; // found type definition. 3515 } 3516 3517 // search up the interface inheritance tree. 3518 return searchLocalInheritanceScope(name, ptype); 3519 } 3520 3521 /** 3522 * 3523 **/ 3524 SymtabEntry searchGlobalInheritanceScope (String name) 3525 { 3526 // See if the container of this named object is an interface: 3527 int index = name.lastIndexOf ('/'); 3528 SymtabEntry entry = null; 3529 if (index >= 0) 3530 { 3531 String containerName = name.substring (0, index); 3532 entry = (SymtabEntry)symbolTable.get (containerName); 3533 entry = (entry instanceof InterfaceEntry) 3534 // It's an interface, now look in its inheritance scope: 3535 ? searchLocalInheritanceScope (name.substring (index + 1), entry) 3536 : null; 3537 } 3538 return entry; 3539 } // searchGlobalInheritanceScope 3540 3541 /** 3542 * 3543 **/ 3544 SymtabEntry searchLocalInheritanceScope (String name, SymtabEntry container) 3545 { 3546 return (container instanceof InterfaceEntry) 3547 ? searchDerivedFrom (name, (InterfaceEntry) container) 3548 : null; 3549 } // searchLocalInheritanceScope 3550 3551 /** 3552 * 3553 **/ 3554 SymtabEntry searchOverrideNames (String name) 3555 { 3556 String overrideName = (String)overrideNames.get (name); 3557 return (overrideName != null) 3558 ? (SymtabEntry)symbolTable.get (overrideName) 3559 : null; 3560 } // searchOverrideNames 3561 3562 /** 3563 * 3564 **/ 3565 SymtabEntry searchModuleScope (String name, SymtabEntry container) 3566 { 3567 String module = container.fullName (); 3568 String fullName = module + '/' + name; 3569 SymtabEntry type = (SymtabEntry)symbolTable.get (fullName); 3570 while ((type == null) && !module.equals ("")) 3571 { 3572 int index = module.lastIndexOf ('/'); 3573 if (index < 0) 3574 module = ""; 3575 else 3576 { 3577 module = module.substring (0, index); 3578 fullName = module + '/' + name; 3579 type = (SymtabEntry)symbolTable.get (fullName); 3580 } 3581 } 3582 return (type == null) ? (SymtabEntry)symbolTable.get (name) : type; 3583 } // searchModuleScope 3584 3585 /** 3586 * 3587 **/ 3588 SymtabEntry searchDerivedFrom (String name, InterfaceEntry i) 3589 { 3590 for (Enumeration e = i.derivedFrom ().elements (); e.hasMoreElements ();) 3591 { 3592 SymtabEntry tmp = (SymtabEntry)e.nextElement (); 3593 if (tmp instanceof InterfaceEntry) 3594 { 3595 InterfaceEntry parent = (InterfaceEntry)tmp; 3596 String fullName = parent.fullName () + '/' + name; 3597 SymtabEntry type = (SymtabEntry)symbolTable.get (fullName); 3598 if (type != null) 3599 return type; 3600 type = searchDerivedFrom (name, parent); 3601 if (type != null) 3602 return type; 3603 } 3604 // else it is a ForwardEntry and nothing can be done at this point. 3605 } 3606 return null; 3607 } // searchDerivedFrom 3608 3609 /** 3610 * 3611 **/ 3612 String entryName (SymtabEntry entry) 3613 { 3614 if (entry instanceof AttributeEntry) 3615 return "attribute"; 3616 if (entry instanceof ConstEntry) 3617 return "constant"; 3618 if (entry instanceof EnumEntry) 3619 return "enumeration"; 3620 if (entry instanceof ExceptionEntry) 3621 return "exception"; 3622 if (entry instanceof ValueBoxEntry) 3623 return "value box"; 3624 if (entry instanceof ForwardValueEntry || entry instanceof ValueEntry) 3625 return "value"; 3626 if (entry instanceof ForwardEntry || entry instanceof InterfaceEntry) 3627 return "interface"; 3628 if (entry instanceof MethodEntry) 3629 return "method"; 3630 if (entry instanceof ModuleEntry) 3631 return "module"; 3632 if (entry instanceof ParameterEntry) 3633 return "parameter"; 3634 if (entry instanceof PrimitiveEntry) 3635 return "primitive"; 3636 if (entry instanceof SequenceEntry) 3637 return "sequence"; 3638 if (entry instanceof StringEntry) 3639 return "string"; 3640 if (entry instanceof StructEntry) 3641 return "struct"; 3642 if (entry instanceof TypedefEntry) 3643 return "typedef"; 3644 if (entry instanceof UnionEntry) 3645 return "union"; 3646 return "void"; 3647 } // entryName 3648 3649 /** 3650 * 3651 **/ 3652 private boolean isInterface (SymtabEntry entry) 3653 { 3654 return entry instanceof InterfaceEntry || (entry instanceof ForwardEntry 3655 && !(entry instanceof ForwardValueEntry)) ; 3656 } 3657 3658 private boolean isValue (SymtabEntry entry) 3659 { 3660 return entry instanceof ValueEntry ; // || entry instanceof ForwardValueEntry; 3661 } 3662 3663 private boolean isInterfaceOnly (SymtabEntry entry) 3664 { 3665 return entry instanceof InterfaceEntry ; 3666 } 3667 3668 private boolean isForward(SymtabEntry entry) 3669 { 3670 return entry instanceof ForwardEntry ; 3671 } 3672 3673 // list must be a vector of Strings. 3674 /** 3675 * 3676 **/ 3677 private boolean isntInStringList (Vector list, String name) 3678 { 3679 boolean isnt = true; 3680 Enumeration e = list.elements (); 3681 while (e.hasMoreElements ()) 3682 if (name.equals ((String)e.nextElement ())) 3683 { 3684 ParseException.alreadyDeclared (scanner, name); 3685 isnt = false; 3686 break; 3687 } 3688 return isnt; 3689 } // isntInStringList 3690 3691 // list must be a vector of SymtabEntry's. 3692 /** 3693 * 3694 **/ 3695 private boolean isntInList (Vector list, String name) 3696 { 3697 boolean isnt = true; 3698 for (Enumeration e = list.elements (); e.hasMoreElements ();) 3699 if (name.equals (((SymtabEntry)e.nextElement ()).name ())) 3700 { 3701 ParseException.alreadyDeclared (scanner, name); 3702 isnt = false; 3703 break; 3704 } 3705 return isnt; 3706 } // isntInList 3707 3708 // list must be a vector of SymtabEntry's. 3709 /** 3710 * 3711 **/ 3712 private boolean isntInList (Vector list, SymtabEntry entry) 3713 { 3714 boolean isnt = true; 3715 for (Enumeration e = list.elements (); e.hasMoreElements ();) 3716 { 3717 SymtabEntry eEntry = (SymtabEntry)e.nextElement (); 3718 if (entry == eEntry) // && entry.fullName().equals (eEntry.fullName())) 3719 { 3720 ParseException.alreadyDeclared (scanner, entry.fullName ()); 3721 isnt = false; 3722 break; 3723 } 3724 } 3725 return isnt; 3726 } // isntInList 3727 3728 /** 3729 * 3730 **/ 3731 public static SymtabEntry typeOf (SymtabEntry entry) 3732 { 3733 while (entry instanceof TypedefEntry) 3734 entry = entry.type (); 3735 return entry; 3736 } // typeOf 3737 3738 /** 3739 * 3740 **/ 3741 void forwardEntryCheck () 3742 { 3743 for (Enumeration e = symbolTable.elements (); e.hasMoreElements ();) 3744 { 3745 SymtabEntry entry = (SymtabEntry)e.nextElement (); 3746 if (entry instanceof ForwardEntry) 3747 ParseException.forwardEntry (scanner, entry.fullName ()); 3748 } 3749 } // forwardEntryCheck 3750 3751 // <46082.03> Revert to "IDL:"-style (i.e., regular) repository ID. 3752 /* 3753 void updateRepositoryIds () { 3754 for (Enumeration e = symbolTable.elements(); e.hasMoreElements();) { 3755 SymtabEntry entry = (SymtabEntry) e.nextElement(); 3756 if (entry instanceof ValueEntry) 3757 ((ValueEntry) entry).calcRepId(); 3758 } 3759 } // updateRepositoryIds 3760 */ 3761 3762 //////////////////// 3763 // Error Handling Methods 3764 3765 // A syntax error occurred. Skip until a semicolon is encountered. 3766 // Ignore semicolons within {...} blocks 3767 /** 3768 * 3769 **/ 3770 private void skipToSemicolon () throws IOException 3771 { 3772 while (!token.equals (Token.EOF) && !token.equals (Token.Semicolon)) 3773 { 3774 if (token.equals (Token.LeftBrace)) 3775 skipToRightBrace(); 3776 try 3777 { 3778 match (token.type); 3779 } 3780 catch (ParseException exception) 3781 { 3782 // The error has already been reported... 3783 } 3784 } 3785 if (token.equals (Token.EOF)) 3786 throw new EOFException (); 3787 try 3788 { 3789 match (Token.Semicolon); 3790 } 3791 catch (Exception exception) 3792 { 3793 } 3794 } // skipToSemicolon 3795 3796 /** 3797 * 3798 **/ 3799 private void skipToRightBrace () throws IOException 3800 { 3801 boolean firstTime = true; 3802 while (!token.equals (Token.EOF) && !token.equals (Token.RightBrace)) 3803 { 3804 if (firstTime) 3805 firstTime = false; 3806 else if (token.equals (Token.LeftBrace)) 3807 skipToRightBrace (); 3808 try 3809 { 3810 match (token.type); 3811 } 3812 catch (ParseException exception) 3813 { 3814 // The error has already been reported... 3815 } 3816 } 3817 if (token.equals (Token.EOF)) 3818 throw new EOFException(); 3819 } // skipToRightBrace 3820 3821 // Error Handling Methods 3822 //////////////////// 3823 3824 // <d56351> In CORBA 2.3, an IDL file provides a new scope for Repository IDs. 3825 // The following methods provide a means for other classes in the framework 3826 // to manage this scoping (see Preprocessor and Scanner). 3827 3828 // public static int nPush = 0; 3829 // public static int nPop = 0; 3830 3831 /** 3832 * 3833 **/ 3834 public static void enteringInclude () 3835 { 3836 repIDStack.push (new IDLID ()); 3837 } // enteringInclude 3838 3839 /** 3840 * 3841 **/ 3842 public static void exitingInclude () 3843 { 3844 repIDStack.pop (); 3845 } // exitingInclude 3846 3847 3848 public static final String unknownNamePrefix = "uN__"; 3849 3850 static Hashtable symbolTable; 3851 Hashtable lcSymbolTable = new Hashtable (); 3852 static Hashtable overrideNames; 3853 Vector emitList = new Vector (); 3854 boolean emitAll; 3855 // <f46082.46.01> 3856 boolean cppModule; 3857 // <d62023> 3858 boolean noWarn; 3859 Scanner scanner; 3860 // <f46082.40> No longer necessary due to new valueElement() algorithm. 3861 // Stack tokenStack = new Stack(); 3862 Hashtable symbols; 3863 Vector macros = new Vector (); 3864 Vector paths; 3865 3866 // Only needed for the pragma directive 3867 SymtabEntry currentModule = null; 3868 3869 // <d56351> Static field necessary to allow Scanner access to enterind/exiting 3870 // Include() methods. Must reset in Compile class, too! 3871 // Stack repIDStack = new Stack (); 3872 static Stack repIDStack = new Stack (); 3873 3874 // Dynamic variable key used for forward type lists. 3875 // A struct or union X entry may have this attached, 3876 // which always contains a List<SymtabEntry>. 3877 // The elements are entries E such that E.type() == X. 3878 // This list must be resolved in pigeonhole when the 3879 // type is finally defined. This is similar to 3880 // ForwardEntry.replaceForwardDecl. 3881 private static int ftlKey = SymtabEntry.getVariableKey() ; 3882 3883 int sequence = 0; 3884 Vector includes; 3885 Vector includeEntries; 3886 3887 // Only needed in primaryExpr. Set in Preprocessor.booleanConstExpr. 3888 boolean parsingConditionalExpr = false; 3889 3890 Token token; 3891 ModuleEntry topLevelModule; 3892 private Preprocessor prep; 3893 private boolean verbose; 3894 SymtabFactory stFactory; 3895 ExprFactory exprFactory; 3896 private String[] keywords; 3897 // <f46082.51> Remove -stateful feature. 3898 //private boolean parseStateful = false; 3899 3900 // Circular buffer containing most recent tokens, including the current token. 3901 private TokenBuffer tokenHistory = new TokenBuffer (); 3902 protected float corbaLevel; // <f60858.1> 3903 private Arguments arguments; 3904 3905} // class Parser 3906