/* * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * COMPONENT_NAME: idl.parser * * ORIGINS: 27 * * Licensed Materials - Property of IBM * 5639-D57 (C) COPYRIGHT International Business Machines Corp. 1997, 1999 * RMI-IIOP v1.0 * */ package com.sun.tools.corba.se.idl; // NOTES: // -F46082.51<daz> Remove -stateful feature. // -D52042<daz> Allow floating-point constants to be initialized with // integral as well as floating-point literals. No other variations allowed. // -D58058<daz> Set index array type to long rather than array element type. // -D56351<daz> Update computation of RepositoryIDs to CORBA 2.3 (see spec.). // -D57110<daz> Provide method() to set/clear ability for scoped names to // resolve to modules. Allows rep. ids to be assigned to modules. // -D46094<daz> Prohibit exceptions from appearing wihtin structs, unions, exceptions. // -D46094<daz> Prohibit attributes from appearing as operation parameter types, // operation return types, attribute types. // -D59067<daz> Prohibit nested value boxes. // -D59166<daz> Prohibit collisions between keywords and non-escaped identifiers. // -D59809<daz> At Pigeonhole(), add map short name of CORBA types to long name // (e.g., CORBA/StringValue --> org/omg/CORBA/StringValue), which allows fully- // qualified CORBA type names to resolve successfully. // -F60858.1<daz> Support "-corba" option, level <= 2.2: issue warning for // keyowrd collisions; // -D60942<daz> Prohibit operations from appearing within parameter types. // -D61643<daz> Repair pigeonhole() to correctly filter bad RepIDs. // -D62023<daz> Support -noWarn option; Issue warnings when tokens are // deprecated keywords or keywords in greater release version. // -D61919<daz> Emit entries for modules originally opened in #include files // appearing at global scope and then reopened in the main IDL file. Only // types appearing in the main IDL source will be emitted. import java.io.EOFException; import java.io.IOException; import java.util.Enumeration; import java.util.Hashtable; import java.util.Stack; import java.util.Vector; import java.util.List ; import java.util.ArrayList ; import java.util.Iterator ; import java.math.BigInteger; import com.sun.tools.corba.se.idl.constExpr.*; /** * **/ class Parser { /** * **/ Parser (Preprocessor preprocessor, Arguments arguments, Hashtable overrides, Hashtable symtab, SymtabFactory stFac, ExprFactory exprFac, String [] genKeywords) { this.arguments = arguments; noWarn = arguments.noWarn; // <d62023> corbaLevel = arguments.corbaLevel; // <f60858.1> paths = arguments.includePaths; symbols = arguments.definedSymbols; verbose = arguments.verbose; emitAll = arguments.emitAll; // <f46082.46.01> cppModule = arguments.cppModule; // <f46082.51> Remove -stateful feature. //parseStateful = arguments.parseStateful; overrideNames = (overrides == null) ? new Hashtable () : overrides; symbolTable = (symtab == null) ? new Hashtable () : symtab; keywords = (genKeywords == null) ? new String [0] : genKeywords; stFactory = stFac; exprFactory = exprFac; currentModule = topLevelModule = new ModuleEntry (); prep = preprocessor; repIDStack.push (new IDLID ()); addPrimEntries (); } // ctor /** * **/ void parse (String file) throws IOException { IncludeEntry fileEntry = stFactory.includeEntry (); fileEntry.name ('"' + file + '"'); try { // Set absolute file path fileEntry.absFilename (Util.getAbsolutePath (file, paths)); } catch (IOException ioe) {} // <f46082.51> Remove -stateful feature. //scanner = new Scanner (fileEntry, keywords, verbose, parseStateful, emitAll); // <f60585.1> Support "-corba [level]" option. //scanner = new Scanner (fileEntry, keywords, verbose, emitAll); scanner = new Scanner (fileEntry, keywords, verbose, emitAll, corbaLevel, arguments.scannerDebugFlag ); topLevelModule.sourceFile (fileEntry); // Prime the pump... // Match handles preprocessor directives, so use match to // call scanner.getToken just in case the first token is // such a directive. But match depends on the token // already having a value, so fudge something. token = new Token (0); tokenHistory.insert (token); // Initialize look back buffer <26jul1997daz>. try { match (0); if (token.equals (Token.EOF)) ParseException.nothing (file); else specification (topLevelModule); } catch (ParseException exception) // Match MIGHT throw this { // It has already been reported, just end. } catch (EOFException exception) // skipToSemicolon MIGHT throw this { // It has already been reported, just end. } } // parse /** * **/ private void addPrimEntries () { symbolTable.put ("short", stFactory.primitiveEntry ("short")); symbolTable.put ("long", stFactory.primitiveEntry ("long")); symbolTable.put ("long long", stFactory.primitiveEntry ("long long")); symbolTable.put ("unsigned short", stFactory.primitiveEntry ("unsigned short")); symbolTable.put ("unsigned long", stFactory.primitiveEntry ("unsigned long")); symbolTable.put ("unsigned long long", stFactory.primitiveEntry ("unsigned long long")); symbolTable.put ("char", stFactory.primitiveEntry ("char")); symbolTable.put ("wchar", stFactory.primitiveEntry ("wchar")); symbolTable.put ("float", stFactory.primitiveEntry ("float")); //Support fixed type: symbolTable.put ("fixed", stFactory.primitiveEntry ("fixed")); symbolTable.put ("double", stFactory.primitiveEntry ("double")); symbolTable.put ("boolean", stFactory.primitiveEntry ("boolean")); symbolTable.put ("octet", stFactory.primitiveEntry ("octet")); symbolTable.put ("any", stFactory.primitiveEntry ("any")); InterfaceEntry object = stFactory.interfaceEntry(); object.name ("Object"); symbolTable.put ("Object", object); ValueEntry valueBase = stFactory.valueEntry(); valueBase.name ("ValueBase"); symbolTable.put ("ValueBase", valueBase); // put these same entries in the lowercase symbol table lcSymbolTable.put ("short", stFactory.primitiveEntry ("short")); lcSymbolTable.put ("long", stFactory.primitiveEntry ("long")); lcSymbolTable.put ("long long", stFactory.primitiveEntry ("long long")); lcSymbolTable.put ("unsigned short", stFactory.primitiveEntry ("unsigned short")); lcSymbolTable.put ("unsigned long", stFactory.primitiveEntry ("unsigned long")); lcSymbolTable.put ("unsigned long long", stFactory.primitiveEntry ("unsigned long long")); lcSymbolTable.put ("char", stFactory.primitiveEntry ("char")); lcSymbolTable.put ("wchar", stFactory.primitiveEntry ("wchar")); lcSymbolTable.put ("float", stFactory.primitiveEntry ("float")); // Support fixed type: lcSymbolTable.put ("fixed", stFactory.primitiveEntry ("fixed")); lcSymbolTable.put ("double", stFactory.primitiveEntry ("double")); lcSymbolTable.put ("boolean", stFactory.primitiveEntry ("boolean")); lcSymbolTable.put ("octet", stFactory.primitiveEntry ("octet")); lcSymbolTable.put ("any", stFactory.primitiveEntry ("any")); lcSymbolTable.put ("object", object); lcSymbolTable.put ("valuebase", valueBase); } // addPrimEntries /** * **/ private void specification (ModuleEntry entry) throws IOException { while (!token.equals (Token.EOF)) { definition (entry); addToEmitList (entry); } } // specification // ModuleEntry is the topLevelModule; add its contained types to the emit list. /** * **/ private void addToEmitList (ModuleEntry entry) { for (Enumeration e = entry.contained ().elements (); e.hasMoreElements();) { SymtabEntry emitEntry = (SymtabEntry)e.nextElement (); if (emitEntry.emit ()) { emitList.addElement (emitEntry); // <d61919> I think the absence of the following statement was an // oversight. If module X.Y.Z first appears in an include file, then is // reopened in the main IDL source, this statement guarantees that X.Y.Z // definitions within the main IDL source are emitted. ///--------------------------------------------------------------------- // If any of this module's elements should be emitted, add // this module to the emit list. if (emitEntry instanceof ModuleEntry) checkContained ((ModuleEntry)emitEntry); if (emitEntry instanceof IncludeEntry) { includes.addElement (emitEntry.name ()); includeEntries.addElement (emitEntry); } } else // If any of this module's elements should be emitted, add // this module to the emit list. if (emitEntry instanceof ModuleEntry) checkContained ((ModuleEntry)emitEntry); } entry.contained ().removeAllElements (); } // addToEmitList /** * **/ private void checkContained (ModuleEntry entry) { // If any of this module's elements is to be emitted, // then add the module to the emit list. for (Enumeration e = entry.contained ().elements (); e.hasMoreElements ();) { SymtabEntry contained = (SymtabEntry)e.nextElement (); if (contained instanceof ModuleEntry) checkContained ((ModuleEntry)contained); if (contained.emit ()) { if (!emitList.contains (entry)) emitList.addElement (entry); entry.emit (true); break; } } } // checkContained /** * **/ private void definition (ModuleEntry entry) throws IOException { try { switch (token.type) { case Token.Typedef: case Token.Struct: case Token.Union: case Token.Enum: typeDcl (entry); break; case Token.Const: constDcl (entry); break; case Token.Native: nativeDcl (entry); break; case Token.Exception: exceptDcl (entry); break; case Token.Interface: interfaceProd (entry, InterfaceEntry.NORMAL); break; case Token.Local: match( Token.Local ) ; if (token.type == Token.Interface) interfaceProd( entry, InterfaceEntry.LOCAL ) ; else throw ParseException.syntaxError( scanner, new int[] { Token.Interface }, token.type ) ; break ; case Token.Module: module (entry); break; case Token.Abstract: match (Token.Abstract); if (token.type == Token.Interface) interfaceProd (entry, InterfaceEntry.ABSTRACT); else if (token.type == Token.Valuetype) valueProd (entry, true); else throw ParseException.syntaxError (scanner, new int[] { Token.Interface, Token.Valuetype }, token.type); break; case Token.Custom: case Token.Valuetype: valueProd (entry, false); break; default: throw ParseException.syntaxError (scanner, new int[] { Token.Typedef, Token.Struct, Token.Union, Token.Enum, Token.Const, Token.Exception, Token.Interface, Token.Valuetype, Token.Module }, token.type); } match (Token.Semicolon); } catch (ParseException e) { skipToSemicolon (); } } // definition /** * **/ private void module (ModuleEntry entry) throws IOException, ParseException { match (Token.Module); repIDStack.push (((IDLID)repIDStack.peek ()).clone ()); ModuleEntry newEntry = newModule (entry); ((IDLID)repIDStack.peek ()).appendToName (newEntry.name ()); // comment must immediately precede "module" keyword newEntry.comment (tokenHistory.lookBack (1).comment); currentModule = newEntry; match (Token.Identifier); prep.openScope (newEntry); match (Token.LeftBrace); definition (newEntry); while (!token.equals (Token.EOF) && !token.equals (Token.RightBrace)) definition (newEntry); prep.closeScope (newEntry); match (Token.RightBrace); currentModule = entry; repIDStack.pop (); } // module /** * **/ private void interfaceProd (ModuleEntry entry, int interfaceType) throws IOException, ParseException { match (Token.Interface); String name = token.name; match (Token.Identifier); interface2 (entry, name, interfaceType); } // interfaceProd /** * **/ private void interface2 (ModuleEntry module, String name, int interfaceType) throws IOException, ParseException { if (token.type == Token.Colon || token.type == Token.LeftBrace) { repIDStack.push (((IDLID)repIDStack.peek ()).clone ()); InterfaceEntry entry = stFactory.interfaceEntry (module, (IDLID)repIDStack.peek ()); entry.sourceFile (scanner.fileEntry ()); entry.name (name); entry.setInterfaceType(interfaceType); // Comment must immediately precede "[local | abstract] interface" keyword entry.comment (tokenHistory.lookBack ( entry.getInterfaceType() == InterfaceEntry.NORMAL ? 2 : 3).comment); if (!ForwardEntry.replaceForwardDecl (entry)) ParseException.badAbstract (scanner, entry.fullName ()); pigeonhole (module, entry); ((IDLID)repIDStack.peek ()).appendToName (name); currentModule = entry; interfaceDcl (entry); currentModule = module; repIDStack.pop (); } else { // This is a forward declaration ForwardEntry entry = stFactory.forwardEntry (module, (IDLID)repIDStack.peek ()); entry.sourceFile (scanner.fileEntry ()); entry.name (name); entry.setInterfaceType(interfaceType); // comment must immediately precede "interface" keyword. entry.comment (tokenHistory.lookBack ( entry.getInterfaceType() == InterfaceEntry.NORMAL ? 2 : 3).comment); pigeonhole (module, entry); } } // interface2 /** * **/ private void interfaceDcl (InterfaceEntry entry) throws IOException, ParseException { if (token.type != Token.LeftBrace) inheritanceSpec (entry); else if (!entry.isAbstract ()) { SymtabEntry objectEntry = qualifiedEntry ("Object"); SymtabEntry realOEntry = typeOf (objectEntry); if (objectEntry == null) ; // qualifiedEntry already generated an error message else if (!isInterface(realOEntry)) ParseException.wrongType (scanner, overrideName ("Object"), "interface", objectEntry.typeName ()); else entry.derivedFromAddElement (realOEntry, scanner); } prep.openScope (entry); match (Token.LeftBrace); while (token.type != Token.RightBrace) export (entry); prep.closeScope (entry); match (Token.RightBrace); } // interfaceDcl /** * **/ private void export (InterfaceEntry entry) throws IOException { try { switch (token.type) { case Token.Typedef: case Token.Struct: case Token.Union: case Token.Enum: typeDcl (entry); break; case Token.Const: constDcl (entry); break; case Token.Native: nativeDcl (entry); break; case Token.Exception: exceptDcl (entry); break; case Token.Readonly: case Token.Attribute: attrDcl (entry); break; case Token.Oneway: case Token.Float: case Token.Double: case Token.Long: case Token.Short: case Token.Unsigned: case Token.Char: case Token.Wchar: case Token.Boolean: case Token.Octet: case Token.Any: case Token.String: case Token.Wstring: case Token.Identifier: case Token.Object: // <f46082.40> Value base type. case Token.ValueBase: case Token.DoubleColon: case Token.Void: opDcl (entry); break; // <f46082.51> Remove -stateful feature. //case Token.State: if (parseStateful) { // stateDef (entry); // break; } default: throw ParseException.syntaxError(scanner, new int [] { Token.Typedef, Token.Struct, Token.Union, Token.Enum, Token.Const, Token.Exception, Token.Readonly, Token.Attribute, Token.Oneway, Token.Float, Token.Double, Token.Long, Token.Short, Token.Unsigned, Token.Char, Token.Wchar, Token.Boolean, Token.Octet, Token.Any, Token.String, Token.Wstring, Token.Identifier, Token.DoubleColon, Token.Void, Token.ValueBase }, token.type); } match (Token.Semicolon); } catch (ParseException exception) { skipToSemicolon (); } } // export private void inheritanceSpec (InterfaceEntry entry) throws IOException, ParseException { for (match (Token.Colon); ; match (Token.Comma)) { SymtabEntry parent = scopedName (entry.container (), stFactory.interfaceEntry ()); SymtabEntry realParent = typeOf (parent); if (isInterfaceOnly (realParent)) { boolean isInterface = (realParent instanceof InterfaceEntry); if (entry.derivedFrom ().contains (realParent)) ParseException.alreadyDerived (scanner, realParent.fullName (), entry.fullName ()); else if (!entry.isAbstract () || (((InterfaceType)realParent).getInterfaceType() == InterfaceType.ABSTRACT)) entry.derivedFromAddElement (realParent, scanner); else ParseException.nonAbstractParent (scanner, entry.fullName (), parent.fullName ()); } else if (isForward( realParent )) { ParseException.illegalForwardInheritance( scanner, entry.fullName(), parent.fullName() ) ; } else ParseException.wrongType (scanner, parent.fullName (), "interface", entryName (parent)); if ((parent instanceof InterfaceEntry) && (((InterfaceEntry)parent).state () != null)) if (entry.state () == null) entry.initState (); else throw ParseException.badState (scanner, entry.fullName ()); if (token.type != Token.Comma) break; } } // inheritanceSpec // <57110> Member _moduleIsLegalType may be set by any feature to allow // method scopedName() and any of its helper methods -- qualifiedName(), // partlyQualifiedName(), and unqualifiedName() -- to return a ModuleEntry // rather than a parse error in the event a name resolves to a module. The // flag must be cleared (set to false) to resume normal parsing behavior. // // Currently, this is used only when preprocessing the ID pragma directive. private boolean _isModuleLegalType = false; /** * **/ public boolean isModuleLegalType () { return _isModuleLegalType; }; // moduleIsLegaType /** * **/ public void isModuleLegalType (boolean b) { _isModuleLegalType = b; }; // moduleIsLegalType /** * **/ SymtabEntry scopedName (SymtabEntry container, SymtabEntry expected) throws IOException, ParseException { return scopedName( container, expected, true ) ; } SymtabEntry scopedName (SymtabEntry container, SymtabEntry expected, boolean mustBeReferencable ) throws IOException, ParseException { boolean globalScope = false; boolean partialScope = false; String name = null; if (token.type == Token.DoubleColon) globalScope = true; else { if (token.type == Token.Object) { name = "Object"; match (Token.Object); } else if (token.type == Token.ValueBase) // <f46082.40> { name = "ValueBase"; match (Token.ValueBase); } else { name = token.name; match (Token.Identifier); } } while (token.type == Token.DoubleColon) { match (Token.DoubleColon); partialScope = true; if (name != null) name += '/' + token.name; else name = token.name; match (Token.Identifier); } SymtabEntry entry = null; if (globalScope) entry = qualifiedEntry (name); else if (partialScope) entry = partlyQualifiedEntry (name, container); else entry = unqualifiedEntry (name, container); if (entry == null) // Make the entry the expected entry. The generators will // not be called now, since a semantic exception ocurred, but // the parse has to finish and something valid has to be // returned. (entry = expected).name (name); else if (!entry.isReferencable() && mustBeReferencable) throw ParseException.illegalIncompleteTypeReference( scanner, name ) ; return entry; } // scopedName private void valueProd (ModuleEntry entry, boolean isAbstract) throws IOException, ParseException { boolean isCustom = (token.type == Token.Custom); if (isCustom) match (Token.Custom); match (Token.Valuetype); String name = token.name; match (Token.Identifier); switch (token.type) { case Token.LeftBrace: case Token.Colon: case Token.Supports: value2 (entry, name, isAbstract, isCustom); return; case Token.Semicolon: if (isCustom) break; valueForwardDcl (entry, name, isAbstract); return; } if (isCustom) throw ParseException.badCustom (scanner); if (isAbstract) throw ParseException.abstractValueBox (scanner); valueBox (entry, name); } // valueProd /** * **/ private void value2 (ModuleEntry module, String name, boolean isAbstract, boolean isCustom) throws IOException, ParseException { repIDStack.push (((IDLID)repIDStack.peek ()).clone ()); // The 'actual' repository ID will be calculated at the end of the // parsing phase, since it is based on the entire contents of the // declaration, and needs to have all forward references resolved: ValueEntry entry = stFactory.valueEntry (module, (IDLID)repIDStack.peek ()); entry.sourceFile (scanner.fileEntry ()); entry.name (name); entry.setInterfaceType (isAbstract ? InterfaceType.ABSTRACT : InterfaceType.NORMAL); entry.setCustom (isCustom); // Comment must immediately precede "[abstract | custom] value" keyword entry.comment (tokenHistory.lookBack ((isAbstract || isCustom) ? 3 : 2).comment); // If this value has been forward declared, there are probably // other values which derive from a ForwardValueEntry. Replace // those ForwardValueEntry's with this ValueEntry: if (!ForwardEntry.replaceForwardDecl (entry)) ParseException.badAbstract (scanner, entry.fullName ()); pigeonhole (module, entry); ((IDLID)repIDStack.peek ()).appendToName (name); currentModule = entry; valueDcl (entry); entry.tagMethods (); currentModule = module; repIDStack.pop (); } // value2 /** * **/ private void valueDcl (ValueEntry entry) throws IOException, ParseException { if (token.type == Token.Colon) valueInheritanceSpec (entry); else if (!entry.isAbstract ()) { SymtabEntry objectEntry = qualifiedEntry ("ValueBase"); SymtabEntry realOEntry = typeOf (objectEntry); if (objectEntry == null) ; // qualifiedEntry already generated an error message else if (!isValue (realOEntry)) ParseException.wrongType (scanner, overrideName ("ValueBase"), "value", objectEntry.typeName ()); else entry.derivedFromAddElement (realOEntry, false, scanner); } if (token.type == Token.Supports) valueSupportsSpec (entry); prep.openScope (entry); match (Token.LeftBrace); while (token.type != Token.RightBrace) { valueElement (entry); } prep.closeScope (entry); match (Token.RightBrace); } // valueDcl /** * **/ private void valueInheritanceSpec (ValueEntry entry) throws IOException, ParseException { match (Token.Colon); boolean isTruncatable = (token.type == Token.Truncatable); if (isTruncatable) match (Token.Truncatable); for (; ; match (Token.Comma), isTruncatable = false) { SymtabEntry parent = scopedName (entry.container (), stFactory.valueEntry ()); SymtabEntry realParent = typeOf (parent); if (isValue (realParent) && !(realParent instanceof ValueBoxEntry)) entry.derivedFromAddElement (realParent, isTruncatable, scanner); else if (isForward(realParent)) ParseException.illegalForwardInheritance( scanner, entry.fullName(), parent.fullName() ) ; else ParseException.wrongType (scanner, parent.fullName (), "value", entryName (parent)); if (token.type != Token.Comma) break; } } // valueInheritanceSpec /** * **/ private void valueSupportsSpec (ValueEntry entry) throws IOException, ParseException { match (Token.Supports) ; for (; ; match( Token.Comma ) ) { SymtabEntry parent = scopedName (entry.container (), stFactory.interfaceEntry ()); SymtabEntry realParent = typeOf (parent); if (isInterface(realParent)) entry.derivedFromAddElement (realParent, scanner); else ParseException.wrongType (scanner, parent.fullName (), "interface", entryName (parent)); if (token.type != Token.Comma) break; } } // valueSupportsSpec private void valueElement (ValueEntry entry) throws IOException, ParseException { if (entry.isAbstract ()) export (entry); else switch (token.type) { case Token.Private: case Token.Public: valueStateMember (entry); break; case Token.Init: case Token.Factory: // <d62023> "factory" supplants "init" in 2.4RTF initDcl (entry); break; case Token.Typedef: case Token.Struct: case Token.Union: case Token.Enum: case Token.Const: case Token.Native: case Token.Exception: case Token.Readonly: case Token.Attribute: case Token.Oneway: case Token.Float: case Token.Double: case Token.Long: case Token.Short: case Token.Unsigned: case Token.Char: case Token.Wchar: case Token.Boolean: case Token.Octet: case Token.Any: case Token.String: case Token.Wstring: case Token.Identifier: case Token.Object: case Token.ValueBase: case Token.DoubleColon: case Token.Void: export (entry); break; default: throw ParseException.syntaxError(scanner, new int[] { Token.Private, Token.Public, Token.Init, Token.ValueBase, Token.Typedef, Token.Struct, Token.Union, Token.Enum, Token.Const, Token.Exception, Token.Readonly, Token.Attribute, Token.Oneway, Token.Float, Token.Double, Token.Long, Token.Short, Token.Unsigned, Token.Char, Token.Wchar, Token.Boolean, Token.Octet, Token.Any, Token.String, Token.Wstring, Token.Identifier, Token.DoubleColon, Token.Void }, token.type); } // switch } // valueElement // <f46082.40> /** * **/ private void valueStateMember (ValueEntry entry) throws IOException, ParseException { TypedefEntry typedefEntry = stFactory.typedefEntry (entry, (IDLID)repIDStack.peek ()); typedefEntry.sourceFile (scanner.fileEntry ()); // comment must immediately precede "public", "private" keywords typedefEntry.comment (token.comment); boolean isPublic = (token.type == Token.Public); if (isPublic) match (Token.Public); else match (Token.Private); // <f46082.40> Add constructed types declared "inline" to the contained // vector of this value entry. boolean isConstTypeSpec = (token.type == Token.Struct || token.type == Token.Union || token.type == Token.Enum); // <f46082.40> Make typedefEntry anonymous. If this line is removed, // the entry will be named incorrectly. See <d50618>. typedefEntry.name (""); typedefEntry.type (typeSpec (typedefEntry)); addDeclarators (entry, typedefEntry, isPublic); // <f46082.40> if (isConstTypeSpec) entry.addContained (typedefEntry); match (Token.Semicolon); } // valueStateMember private void addDeclarators (ValueEntry entry, TypedefEntry typedefEntry, boolean isPublic) throws IOException, ParseException { int modifier = isPublic ? InterfaceState.Public : InterfaceState.Private; try { Vector typedefList = new Vector (); declarators (typedefEntry, typedefList); for (Enumeration e = typedefList.elements (); e.hasMoreElements ();) entry.addStateElement ( new InterfaceState (modifier, (TypedefEntry)e.nextElement ()), scanner); } catch (ParseException exception) { skipToSemicolon (); } } // addDeclarators /** * **/ private void initDcl (ValueEntry entry) throws IOException, ParseException { MethodEntry method = stFactory.methodEntry (entry, (IDLID)repIDStack.peek ()); method.sourceFile (scanner.fileEntry ()); // Comment must immediately precede "init" keyword: method.comment (token.comment); repIDStack.push (((IDLID)repIDStack.peek ()).clone ()); ((IDLID)repIDStack.peek ()).appendToName (token.name); // <d62023> In 2.3 prelim, <init_dcl> ::= "init" "(" ... if (token.type == Token.Init) { method.name ("init"); match (Token.Init); match (Token.LeftParen); } else // <d62023> In 2.4rtf, <init_dcl> ::= "factory" <Indentifier> "(" ... { match (Token.Factory); method.name (token.name); if (token.type == Token.MacroIdentifier) match (Token.MacroIdentifier); // "(" already consumed. else { match (Token.Identifier); match (Token.LeftParen); } } if (token.type != Token.RightParen) for (;;) { initParamDcl (method); if (token.type == Token.RightParen) break; match (Token.Comma); } entry.initializersAddElement (method, scanner); match (Token.RightParen); match (Token.Semicolon); repIDStack.pop (); } // initDcl /** * **/ private void initParamDcl (MethodEntry entry) throws IOException, ParseException { ParameterEntry parmEntry = stFactory.parameterEntry (entry, (IDLID)repIDStack.peek ()); parmEntry.sourceFile (scanner.fileEntry()); // Comment must immediately precede parameter attribute parmEntry.comment (token.comment); match (Token.In); parmEntry.passType (ParameterEntry.In); parmEntry.type (paramTypeSpec (entry)); parmEntry.name (token.name); match (Token.Identifier); if (isntInList (entry.parameters (), parmEntry.name ())) entry.addParameter (parmEntry); } // initParamDcl /** * **/ private void valueBox (ModuleEntry module, String name) throws IOException, ParseException { repIDStack.push (((IDLID)repIDStack.peek ()).clone ()); // Note: The 'actual' repository ID will be calculated at the end of // the parsing phase, since it is based on the entire contents of the // declaration, and needs to have all forward references resolved: ValueEntry entry = stFactory.valueBoxEntry (module, (IDLID)repIDStack.peek ()); entry.sourceFile (scanner.fileEntry ()); entry.name (name); // comment must immediately precede "value" keyword entry.comment (tokenHistory.lookBack (2).comment); // <f46082.40> Value boxes may not be forwarded. // If this value has been forward declared, there are probably // other values which derive from a ForwardValueEntry. // Replace those ForwardValueEntry's with this ValueEntry: //if (!ForwardValueEntry.replaceForwardDecl (entry)) // ParseException.badAbstract (scanner, entry.fullName()); SymtabEntry valueForward = (SymtabEntry)Parser.symbolTable.get (entry.fullName ()); if (valueForward != null && valueForward instanceof ForwardEntry) ParseException.forwardedValueBox (scanner, entry.fullName ()); pigeonhole (module, entry); ((IDLID)repIDStack.peek ()).appendToName (name); currentModule = entry; TypedefEntry typedefEntry = stFactory.typedefEntry (entry, (IDLID)repIDStack.peek ()); typedefEntry.sourceFile (scanner.fileEntry ()); typedefEntry.comment (token.comment); // <d50237> Workaround to place typedefEntry in the _contained vector of // this value box entry ONLY when <type_spec> is a constructed type declared // at this point (i.e., not an identifier that resolves to a constructed // type), so that emitters may generate bindings for it. <daz> boolean isConstTypeSpec = token.type == Token.Struct || token.type == Token.Union || token.type == Token.Enum; // <d50618> Make typedefEntry anonymous. If this line is removed, the // entry will be named incorrectly. typedefEntry.name (""); typedefEntry.type (typeSpec (typedefEntry)); // <d59067> Value boxes cannot be nested. if (typedefEntry.type () instanceof ValueBoxEntry) ParseException.nestedValueBox (scanner); //typedefEntry.name (""); entry.addStateElement (new InterfaceState (InterfaceState.Public, typedefEntry), scanner); if (isConstTypeSpec) entry.addContained (typedefEntry); currentModule = module; repIDStack.pop (); } // valueBox /** * **/ private void valueForwardDcl (ModuleEntry module, String name, boolean isAbstract) throws IOException, ParseException { ForwardValueEntry entry = stFactory.forwardValueEntry (module, (IDLID)repIDStack.peek ()); entry.sourceFile (scanner.fileEntry ()); entry.name (name); entry.setInterfaceType(isAbstract ? InterfaceType.ABSTRACT : InterfaceType.NORMAL ); // Comment must immediately precede "[abstract] value" keyword[s] entry.comment (tokenHistory.lookBack (isAbstract? 3 : 2).comment); pigeonhole (module, entry); } // valueForwardDcl private void nativeDcl (SymtabEntry entry) throws IOException, ParseException { match (Token.Native); NativeEntry nativeEntry = stFactory.nativeEntry (entry, (IDLID)repIDStack.peek ()); nativeEntry.sourceFile (scanner.fileEntry ()); // Comment must immediately precede "native" keyword nativeEntry.comment (tokenHistory.lookBack (1).comment); nativeEntry.name (token.name); match (Token.Identifier); pigeonhole (entry, nativeEntry); } // nativeDcl /** * **/ private void constDcl (SymtabEntry entry) throws IOException, ParseException { match (Token.Const); ConstEntry constEntry = stFactory.constEntry (entry, (IDLID)repIDStack.peek ()); constEntry.sourceFile (scanner.fileEntry ()); // Comment must immediately precede "const" keyword constEntry.comment (tokenHistory.lookBack (1).comment); constType (constEntry); constEntry.name (token.name); match (Token.Identifier); match (Token.Equal); constEntry.value (constExp (constEntry)); verifyConstType (constEntry.value (), typeOf (constEntry.type ())); pigeonhole (entry, constEntry); } // constDcl /** * **/ private void constType (SymtabEntry entry) throws IOException, ParseException { switch (token.type) { case Token.Octet: entry.type( octetType()) ; break ; case Token.Long: case Token.Short: case Token.Unsigned: entry.type (integerType (entry)); break; case Token.Char: case Token.Wchar: entry.type (charType ()); break; case Token.Boolean: entry.type (booleanType ()); break; case Token.Float: case Token.Double: entry.type (floatingPtType ()); break; case Token.String: case Token.Wstring: entry.type (stringType (entry)); break; case Token.Identifier: case Token.DoubleColon: entry.type (scopedName (entry.container (), stFactory.primitiveEntry ())); if (hasArrayInfo (entry.type ())) ParseException.illegalArray (scanner, "const"); SymtabEntry entryType = typeOf (entry.type ()); if (!((entryType instanceof PrimitiveEntry) || (entryType instanceof StringEntry))) { ParseException.wrongType(scanner, entry.fullName (), "primitive or string", entryName (entry.type ())); entry.type (qualifiedEntry ("long")); } else if (entryType instanceof PrimitiveEntry) { String any = overrideName ("any"); if (entryType.name().equals (any)) { ParseException.wrongType (scanner, entry.fullName (), "primitive or string (except " + any + ')', any); entry.type (qualifiedEntry ("long")); } } break; default: throw ParseException.syntaxError (scanner, new int [] { Token.Long, Token.Short, Token.Unsigned, Token.Char, Token.Wchar, Token.Boolean, Token.Float, Token.Double, Token.String, Token.Wstring, Token.Identifier, Token.DoubleColon }, token.type); } } // constType /** * **/ private boolean hasArrayInfo (SymtabEntry entry) { while (entry instanceof TypedefEntry) { if (((TypedefEntry)entry).arrayInfo ().size () != 0) return true; entry = entry.type (); } return false; } // hasArrayInfo /** * **/ public static String overrideName (String string) { String name = (String)overrideNames.get (string); return (name == null) ? string : name; } // overrideName // If entry is boolean, expression value must be boolean // If entry is float/double, expression value must be float/double // If entry is integral, expression value must be integral // If entry is string, expression value must be string /** * **/ private void verifyConstType (Expression e, SymtabEntry t) { Object value = e.value (); if (value instanceof BigInteger) verifyIntegral ((Number)value, t); else if (value instanceof String) verifyString (e, t); else if (value instanceof Boolean) verifyBoolean (t); else if (value instanceof Character) verifyCharacter (e, t); else if (value instanceof Float || value instanceof Double) verifyFloat((Number)value, t); else if (value instanceof ConstEntry) verifyConstType (((ConstEntry)value).value (), t); else ParseException.wrongExprType (scanner, t.fullName (), (value == null) ? "" : value.toString ()); } // verifyConstType private static final int MAX_SHORT = 32767; private static final int MIN_SHORT = -32768; private static final int MAX_USHORT = 65535; /** * **/ private void verifyIntegral (Number n, SymtabEntry t) { boolean outOfRange = false; //KEEP: Useful for debugging com.sun.tools.corba.se.idl.constExpr package //System.out.println ("verifyIntegral, n = " + n.toString ()); if (t == qualifiedEntry( "octet" )) { if ((n.longValue() > 255) || (n.longValue() < 0)) outOfRange = true ; } else if (t == qualifiedEntry ("long")) { if (n.longValue () > Integer.MAX_VALUE || n.longValue() < Integer.MIN_VALUE) outOfRange = true; } else if (t == qualifiedEntry ("short")) { if (n.intValue () > Short.MAX_VALUE || n.intValue () < Short.MIN_VALUE) outOfRange = true; } else if (t == qualifiedEntry ("unsigned long")) { if (n.longValue () > (long)Integer.MAX_VALUE*2+1 || n.longValue() < 0) outOfRange = true; } else if (t == qualifiedEntry ("unsigned short")) { if (n.intValue () > (int) Short.MAX_VALUE*2+1 || n.intValue () < 0) outOfRange = true; } else if (t == qualifiedEntry ("long long")) { // BigInteger required because value being compared may exceed // java.lang.Long.MAX_VALUE/MIN_VALUE: BigInteger llMax = BigInteger.valueOf (Long.MAX_VALUE); BigInteger llMin = BigInteger.valueOf (Long.MIN_VALUE); if (((BigInteger)n).compareTo (llMax) > 0 || ((BigInteger)n).compareTo (llMin) < 0) outOfRange = true; } else if (t == qualifiedEntry ("unsigned long long")) { BigInteger ullMax = BigInteger.valueOf (Long.MAX_VALUE). multiply (BigInteger.valueOf (2)). add (BigInteger.valueOf (1)); BigInteger ullMin = BigInteger.valueOf (0); if (((BigInteger)n).compareTo (ullMax) > 0 || ((BigInteger)n).compareTo (ullMin) < 0) outOfRange = true; } else { String got = null; // THIS MUST BE CHANGED; BIGINTEGER IS ALWAYS THE CONTAINER /* if (n instanceof Short) got = "short"; else if (n instanceof Integer) got = "long"; else got = "long long"; */ got = "long"; ParseException.wrongExprType (scanner, t.fullName (), got); } if (outOfRange) ParseException.outOfRange (scanner, n.toString (), t.fullName ()); } // verifyIntegral /** * **/ private void verifyString (Expression e, SymtabEntry t) { String string = (String)(e.value()) ; if (!(t instanceof StringEntry)) { ParseException.wrongExprType (scanner, t.fullName (), e.type() ); } else if (((StringEntry)t).maxSize () != null) { Expression maxExp = ((StringEntry)t).maxSize (); try { Number max = (Number)maxExp.value (); if (string.length () > max.intValue ()) ParseException.stringTooLong (scanner, string, max.toString ()); } catch (Exception exception) { // If the above statement is not valid and throws an // exception, then an error occurred and was reported // earlier. Move on. } } if (!e.type().equals( t.name())) { // cannot mix strings and wide strings ParseException.wrongExprType (scanner, t.name(), e.type() ) ; } } // verifyString /** * **/ private void verifyBoolean (SymtabEntry t) { if (!t.name ().equals (overrideName ("boolean"))) ParseException.wrongExprType(scanner, t.name(), "boolean"); } // verifyBoolean /** * **/ private void verifyCharacter (Expression e, SymtabEntry t) { // Bug fix 4382578: Can't compile a wchar literal. // Allow a Character to be either a char or a wchar. if (!t.name ().equals (overrideName ("char")) && !t.name ().equals (overrideName ("wchar")) || !t.name().equals(e.type()) ) ParseException.wrongExprType (scanner, t.fullName(), e.type() ) ; } // verifyCharacter /** * **/ private void verifyFloat (Number f, SymtabEntry t) { // <d52042> Added range checking for floats. //if (!(t.name ().equals (overrideName ("float")) || // t.name ().equals (overrideName ("double")))) // ParseException.wrongExprType (scanner, // t.fullName (), (f instanceof Float) ? "float" : "double"); //KEEP: Useful for debugging com.sun.tools.corba.se.idl.constExpr package //System.out.println ("verifyFloat, f = " + f.toString ()); boolean outOfRange = false; if (t.name ().equals (overrideName ("float"))) { double absVal = (f.doubleValue () < 0.0) ? f.doubleValue () * -1.0 : f.doubleValue (); if ((absVal != 0.0) && (absVal > Float.MAX_VALUE || absVal < Float.MIN_VALUE)) outOfRange = true; } else if (t.name ().equals (overrideName ("double"))) { // Cannot check range of double until BigDecimal is the basis // of all floating-point types. Currently, it is Double. The // parser will fail when instantiating a Double with an exception. } else { ParseException.wrongExprType (scanner, t.fullName (), (f instanceof Float) ? "float" : "double"); } if (outOfRange) ParseException.outOfRange (scanner, f.toString (), t.fullName ()); } // verifyFloat /** * **/ Expression constExp (SymtabEntry entry) throws IOException, ParseException { // Parse the expression. Expression expr = orExpr (null, entry); // Set its target type. if (expr.type() == null) expr.type (entry.typeName ()); // Compute its value and <d53042> coerce it to the target type. try { expr.evaluate (); // <d54042> Coerces integral value to Double if an integer literal // was used to initialize a floating-point constant expression. if (expr instanceof Terminal && expr.value () instanceof BigInteger && (overrideName (expr.type ()).equals ("float") || overrideName (expr.type ()).indexOf ("double") >= 0)) { expr.value (new Double (((BigInteger)expr.value ()).doubleValue ())); } } catch (EvaluationException exception) { ParseException.evaluationError (scanner, exception.toString ()); } return expr; } // constExp /** * **/ private Expression orExpr (Expression e, SymtabEntry entry) throws IOException, ParseException { if (e == null) e = xorExpr (null, entry); else { BinaryExpr b = (BinaryExpr)e; b.right (xorExpr (null, entry)); e.rep (e.rep () + b.right ().rep ()); } if (token.equals (Token.Bar)) { match (token.type); Or or = exprFactory.or (e, null); or.type (entry.typeName ()); or.rep (e.rep () + " | "); return orExpr (or, entry); } return e; } // orExpr /** * **/ private Expression xorExpr (Expression e, SymtabEntry entry) throws IOException, ParseException { if (e == null) e = andExpr (null, entry); else { BinaryExpr b = (BinaryExpr)e; b.right (andExpr (null, entry)); e.rep (e.rep () + b.right ().rep ()); } if (token.equals (Token.Carat)) { match (token.type); Xor xor = exprFactory.xor (e, null); xor.rep (e.rep () + " ^ "); xor.type (entry.typeName ()); return xorExpr (xor, entry); } return e; } // xorExpr /** * **/ private Expression andExpr (Expression e, SymtabEntry entry) throws IOException, ParseException { if (e == null) e = shiftExpr (null, entry); else { BinaryExpr b = (BinaryExpr)e; b.right (shiftExpr (null, entry)); e.rep (e.rep () + b.right ().rep ()); } if (token.equals (Token.Ampersand)) { match (token.type); And and = exprFactory.and (e, null); and.rep(e.rep () + " & "); and.type (entry.typeName ()); return andExpr (and, entry); } return e; } // andExpr /** * **/ private Expression shiftExpr (Expression e, SymtabEntry entry) throws IOException, ParseException { if (e == null) e = addExpr (null, entry); else { BinaryExpr b = (BinaryExpr)e; b.right (addExpr (null, entry)); e.rep (e.rep () + b.right ().rep ()); } if (token.equals (Token.ShiftLeft)) { match (token.type); ShiftLeft sl = exprFactory.shiftLeft (e, null); sl.type (entry.typeName ()); sl.rep (e.rep () + " << "); return shiftExpr (sl, entry); } if (token.equals (Token.ShiftRight)) { match (token.type); ShiftRight sr = exprFactory.shiftRight (e, null); sr.type (entry.typeName ()); sr.rep (e.rep () + " >> "); return shiftExpr (sr, entry); } return e; } // shiftExpr /** * **/ private Expression addExpr (Expression e, SymtabEntry entry) throws IOException, ParseException { if (e == null) e = multExpr (null, entry); else { BinaryExpr b = (BinaryExpr)e; b.right (multExpr (null, entry)); e.rep (e.rep () + b.right ().rep ()); } if (token.equals (Token.Plus)) { match (token.type); Plus p = exprFactory.plus (e, null); p.type (entry.typeName ()); p.rep (e.rep () + " + "); return addExpr (p, entry); } if (token.equals (Token.Minus)) { match (token.type); Minus m = exprFactory.minus (e, null); m.type (entry.typeName ()); m.rep (e.rep () + " - "); return addExpr (m, entry); } return e; } // addExpr /** * **/ private Expression multExpr (Expression e, SymtabEntry entry) throws IOException, ParseException { if (e == null) e = unaryExpr (entry); else { BinaryExpr b = (BinaryExpr)e; b.right (unaryExpr (entry)); e.rep (e.rep () + b.right ().rep ()); } if (token.equals (Token.Star)) { match (token.type); Times t = exprFactory.times (e, null); t.type (entry.typeName ()); t.rep (e.rep () + " * "); return multExpr (t, entry); } if (token.equals (Token.Slash)) { match (token.type); Divide d = exprFactory.divide (e, null); d.type (entry.typeName ()); d.rep (e.rep () + " / "); return multExpr (d, entry); } if (token.equals (Token.Percent)) { match (token.type); Modulo m = exprFactory.modulo (e, null); m.type (entry.typeName ()); m.rep (e.rep () + " % "); return multExpr (m, entry); } return e; } // multExpr /** * **/ private Expression unaryExpr (SymtabEntry entry) throws IOException, ParseException { if (token.equals (Token.Plus)) { match (token.type); Expression e = primaryExpr (entry); Positive pos = exprFactory.positive (e); pos.type (entry.typeName()); pos.rep ('+' + e.rep()); return pos; } if (token.equals (Token.Minus)) { match (token.type); Expression e = primaryExpr (entry); Negative neg = exprFactory.negative (e); neg.type (entry.typeName()); neg.rep ('-' + e.rep()); return neg; } if (token.equals (Token.Tilde)) { match (token.type); Expression e = primaryExpr (entry); Not not = exprFactory.not (e); not.type (entry.typeName()); not.rep ('~' + e.rep()); return not; } return primaryExpr (entry); } // unaryExpr /** * **/ private Expression primaryExpr (SymtabEntry entry) throws IOException, ParseException { Expression primary = null; if (parsingConditionalExpr) { prep.token = token; // Give current token to preprocessor primary = prep.primaryExpr (entry); token = prep.token; // Get the current token from preprocessor } else switch (token.type) { case Token.Identifier: case Token.DoubleColon: ConstEntry expectedC = stFactory.constEntry (); expectedC.value (exprFactory.terminal ("1", BigInteger.valueOf (1))); SymtabEntry ref = scopedName (entry.container (), expectedC); if (!(ref instanceof ConstEntry)) { ParseException.invalidConst (scanner, ref.fullName ()); // An error occurred. Just give it some bogus value. <daz> //primary = exprFactory.terminal ("1", new Long (1)); primary = exprFactory.terminal ("1", BigInteger.valueOf (1)); } else primary = exprFactory.terminal ((ConstEntry)ref); break; case Token.BooleanLiteral: case Token.CharacterLiteral: case Token.IntegerLiteral: case Token.FloatingPointLiteral: case Token.StringLiteral: primary = literal (entry); break; case Token.LeftParen: match (Token.LeftParen); primary = constExp (entry); match (Token.RightParen); primary.rep ('(' + primary.rep () + ')'); break; default: throw ParseException.syntaxError (scanner, new int [] { Token.Identifier, Token.DoubleColon, Token.Literal, Token.LeftParen}, token.type); } return primary; } // primaryExpr /** * **/ Expression literal (SymtabEntry entry) throws IOException, ParseException { String string = token.name; Expression literal = null; switch (token.type) { case Token.IntegerLiteral: match (Token.IntegerLiteral); try { literal = exprFactory.terminal (string, parseString (string)); literal.type (entry.typeName ()); } catch (NumberFormatException exception) { ParseException.notANumber (scanner, string); literal = exprFactory.terminal ("0", BigInteger.valueOf (0)); } break; case Token.CharacterLiteral: boolean isWide = token.isWide(); match (Token.CharacterLiteral); literal = exprFactory.terminal ("'" + string.substring (1) + "'", new Character (string.charAt (0)), isWide ); break; case Token.FloatingPointLiteral: match (Token.FloatingPointLiteral); try { literal = exprFactory.terminal (string, new Double (string)); literal.type (entry.typeName ()); } catch (NumberFormatException e) { ParseException.notANumber (scanner, string); } break; case Token.BooleanLiteral: literal = booleanLiteral (); break; case Token.StringLiteral: literal = stringLiteral (); break; default: throw ParseException.syntaxError (scanner, Token.Literal,token.type); } return literal; } // literal /** * **/ private BigInteger parseString (String string) throws NumberFormatException { int radix = 10; if (string.length() > 1) if (string.charAt (0) == '0') if (string.charAt (1) == 'x' || string.charAt (1) == 'X') { string = string.substring (2); radix = 16; } else radix = 8; return new BigInteger (string, radix); } // parseString /** * **/ private Terminal booleanLiteral () throws IOException, ParseException { Boolean bool = null; if (token.name.equals ("TRUE")) bool = new Boolean (true); else if (token.name.equals ("FALSE")) bool = new Boolean (false); else { ParseException.invalidConst (scanner, token.name); bool = new Boolean (false); } String name = token.name; match (Token.BooleanLiteral); return exprFactory.terminal (name, bool); } // booleanLiteral /** * **/ private Expression stringLiteral () throws IOException, ParseException { // If string literals appear together, concatenate them. Ie: // "Twas " "brillig " "and " "the " "slithy " "toves" // becomes // "Twas brillig and the slithy toves" boolean isWide = token.isWide() ; String literal = ""; do { literal += token.name; match (Token.StringLiteral); } while (token.equals (Token.StringLiteral)); Expression stringExpr = exprFactory.terminal (literal, isWide ); stringExpr.rep ('"' + literal + '"'); return stringExpr; } // stringLiteral /** * **/ private Expression positiveIntConst (SymtabEntry entry) throws IOException, ParseException { Expression e = constExp (entry); Object value = e.value (); while (value instanceof ConstEntry) value = ((ConstEntry)value).value ().value (); if (!(value instanceof Number) || value instanceof Float || value instanceof Double) { ParseException.notPositiveInt (scanner, e.rep ()); //e = exprFactory.terminal ("1", new Long (1)); e = exprFactory.terminal ("1", BigInteger.valueOf (1)); } //else if (((Number)value).longValue () <= 0) { // ParseException.notPositiveInt (scanner, value.toString ()); // e = exprFactory.terminal ("1", new Long (1)); } else if (((BigInteger)value).compareTo (BigInteger.valueOf (0)) <= 0) { ParseException.notPositiveInt (scanner, value.toString ()); //e = exprFactory.terminal ("1", new Long (1)); <daz> e = exprFactory.terminal ("1", BigInteger.valueOf (1)); } return e; } // positiveIntConst /** * **/ private SymtabEntry typeDcl (SymtabEntry entry) throws IOException, ParseException { switch (token.type) { case Token.Typedef: match (Token.Typedef); return typeDeclarator (entry); case Token.Struct: return structType (entry); case Token.Union: return unionType (entry); case Token.Enum: return enumType (entry); default: throw ParseException.syntaxError (scanner, new int [] { Token.Typedef, Token.Struct, Token.Union, Token.Enum}, token.type); } } // typeDcl /** * **/ private TypedefEntry typeDeclarator (SymtabEntry entry) throws IOException, ParseException { TypedefEntry typedefEntry = stFactory.typedefEntry (entry, (IDLID)repIDStack.peek ()); typedefEntry.sourceFile (scanner.fileEntry ()); // Comment must immediately precede "typedef" keyword typedefEntry.comment (tokenHistory.lookBack (1).comment); typedefEntry.type (typeSpec (entry)); Vector typedefList = new Vector (); declarators (typedefEntry, typedefList); for (Enumeration e = typedefList.elements(); e.hasMoreElements();) pigeonhole (entry, (SymtabEntry)e.nextElement ()); return typedefEntry; } // typeDeclarator /** * **/ private SymtabEntry typeSpec (SymtabEntry entry) throws IOException, ParseException { return ((token.type == Token.Struct) || (token.type == Token.Union) || (token.type == Token.Enum)) ? constrTypeSpec (entry) : simpleTypeSpec (entry, true); } // typeSpec /** * **/ private SymtabEntry simpleTypeSpec (SymtabEntry entry, boolean mustBeReferencable ) throws IOException, ParseException { // <f46082.40> //if ((token.type == Token.Identifier) || // (token.type == Token.DoubleColon) || // (token.type == Token.Object)) { if ((token.type == Token.Identifier) || (token.type == Token.DoubleColon) || (token.type == Token.Object) || (token.type == Token.ValueBase)) { SymtabEntry container = ((entry instanceof InterfaceEntry) || (entry instanceof ModuleEntry) || (entry instanceof StructEntry) || (entry instanceof UnionEntry)) ? entry : entry.container (); return scopedName (container, stFactory.primitiveEntry (), mustBeReferencable); } return ((token.type == Token.Sequence) || (token.type == Token.String) || (token.type == Token.Wstring)) ? templateTypeSpec (entry) : baseTypeSpec (entry); } // simpleTypeSpec /** * **/ private SymtabEntry baseTypeSpec (SymtabEntry entry) throws IOException, ParseException { switch (token.type) { case Token.Float: case Token.Double: return floatingPtType (); case Token.Long: case Token.Short: case Token.Unsigned: return integerType (entry); case Token.Char: case Token.Wchar: return charType (); case Token.Boolean: return booleanType (); case Token.Octet: return octetType (); case Token.Any: return anyType (); // NOTE: Object and ValueBase are <base_type_spec>s, but both // are processed at simpleTypeSpec(), not here. parmTypeSpec() // directly checks for these types. Could make baseTypeSpec() do // the same default: throw ParseException.syntaxError (scanner, new int [] { Token.Float, Token.Double, Token.Long, Token.Short, Token.Unsigned, Token.Char, Token.Wchar, Token.Boolean, Token.Octet, Token.Any}, token.type); } } // baseTypeSpec /** * **/ private SymtabEntry templateTypeSpec (SymtabEntry entry) throws IOException, ParseException { switch (token.type) { case Token.Sequence: return sequenceType (entry); case Token.String: case Token.Wstring: return stringType (entry); } throw ParseException.syntaxError (scanner, new int [] {Token.Sequence, Token.String, Token.Wstring}, token.type); } // templateTypeSpec /** * **/ private SymtabEntry constrTypeSpec (SymtabEntry entry) throws IOException, ParseException { switch (token.type) { case Token.Struct: return structType (entry); case Token.Union: return unionType (entry); case Token.Enum: return enumType (entry); } throw ParseException.syntaxError (scanner, new int [] {Token.Struct, Token.Union, Token.Enum}, token.type); } // constrTypeSpec /** * **/ private void declarators (TypedefEntry entry, Vector list) throws IOException, ParseException { for (; ; match (Token.Comma)) { TypedefEntry newEntry = (TypedefEntry)entry.clone (); declarator (newEntry); if (isntInList (list, newEntry.name ())) list.addElement (newEntry); if (token.type != Token.Comma) break; } } // declarators /** * **/ private void declarator (TypedefEntry entry) throws IOException, ParseException { entry.name (token.name); // If the declarator is commented then override the comment cloned from the parent // entry. <08aug1997daz> if (!token.comment.text ().equals ("")) entry.comment (token.comment); match (Token.Identifier); while (token.type == Token.LeftBracket) fixedArraySize (entry); } // declarator /** * **/ private PrimitiveEntry floatingPtType () throws IOException, ParseException { String name = "double"; if (token.type == Token.Float) { match (Token.Float); name = "float"; } else if (token.type == Token.Double) match (Token.Double); else { int [] expected = {Token.Float, Token.Double}; ParseException.syntaxError (scanner, new int [] {Token.Float, Token.Double }, token.type); } PrimitiveEntry ret = null; try { ret = (PrimitiveEntry)qualifiedEntry (name); } catch (ClassCastException exception) { ParseException.undeclaredType (scanner, name); } return ret; } // floatingPtType /** * **/ private PrimitiveEntry integerType (SymtabEntry entry) throws IOException, ParseException { String name = ""; if (token.type == Token.Unsigned) { match (Token.Unsigned); name = "unsigned "; } name += signedInt(); PrimitiveEntry ret = null; try { ret = (PrimitiveEntry) qualifiedEntry (name); } catch (ClassCastException exception) { ParseException.undeclaredType (scanner, name); } return ret; } // integerType /** * **/ private String signedInt () throws IOException, ParseException { String ret = "long"; if (token.type == Token.Long) { match (Token.Long); // <signedInt'> ::= "long" | e if (token.type == Token.Long) { ret = "long long"; match (Token.Long); } } else if (token.type == Token.Short) { ret = "short"; match (Token.Short); } else ParseException.syntaxError (scanner, new int [] {Token.Long, Token.Short}, token.type); return ret; } // signedInt /** * **/ private PrimitiveEntry charType () throws IOException, ParseException { String tokenName; if (token.type == Token.Char) { match (Token.Char); tokenName = "char"; } else { match (Token.Wchar); tokenName = "wchar"; } PrimitiveEntry ret = null; try { ret = (PrimitiveEntry) qualifiedEntry (tokenName); } catch (ClassCastException exception) { ParseException.undeclaredType (scanner, overrideName (tokenName)); } return ret; } // charType /** * **/ private PrimitiveEntry booleanType () throws IOException, ParseException { PrimitiveEntry ret = null; match (Token.Boolean); try { ret = (PrimitiveEntry) qualifiedEntry ("boolean"); } catch (ClassCastException exception) { ParseException.undeclaredType (scanner, overrideName ("boolean")); } return ret; } // booleanType /** * **/ private PrimitiveEntry octetType () throws IOException, ParseException { PrimitiveEntry ret = null; match (Token.Octet); try { ret = (PrimitiveEntry) qualifiedEntry ("octet"); } catch (ClassCastException exception) { ParseException.undeclaredType (scanner, overrideName ("octet")); } return ret; } // octetType /** * **/ private SymtabEntry anyType () throws IOException, ParseException { match (Token.Any); try { return qualifiedEntry ("any"); } catch (ClassCastException exception) { ParseException.undeclaredType (scanner, overrideName ("any")); return null; } } // anyType /** * **/ private StructEntry structType (SymtabEntry entry) throws IOException, ParseException { match (Token.Struct); String name = token.name; match (Token.Identifier); StructEntry structEntry = null ; if (token.type == Token.LeftBrace) { repIDStack.push(((IDLID)repIDStack.peek ()).clone ()) ; structEntry = makeStructEntry( name, entry, false ) ; ((IDLID)repIDStack.peek ()).appendToName (name); prep.openScope (structEntry); match (Token.LeftBrace) ; member (structEntry) ; memberList2 (structEntry) ; prep.closeScope (structEntry); match (Token.RightBrace) ; repIDStack.pop() ; } else if (token.equals( Token.Semicolon )) { structEntry = makeStructEntry( name, entry, true ) ; } else { throw ParseException.syntaxError (scanner, new int[] { Token.Semicolon, Token.LeftBrace }, token.type); } return structEntry; } // structType private StructEntry makeStructEntry( String name, SymtabEntry entry, boolean isForward ) { StructEntry structEntry = stFactory.structEntry (entry, (IDLID)repIDStack.peek () ); structEntry.isReferencable( !isForward ) ; structEntry.sourceFile (scanner.fileEntry ()); structEntry.name (name); // Comment must immediately preceed "struct" keyword structEntry.comment (tokenHistory.lookBack (1).comment); pigeonhole( entry, structEntry ) ; return structEntry ; } /** * **/ private void memberList2 (StructEntry entry) throws IOException { while (token.type != Token.RightBrace) member (entry); } // memberList2 /** * **/ private void member (StructEntry entry) throws IOException { TypedefEntry newEntry = stFactory.typedefEntry(entry, (IDLID)repIDStack.peek()); newEntry.sourceFile (scanner.fileEntry ()); // comment must immediately precede <type_spec> lexeme newEntry.comment (token.comment); try { newEntry.type (typeSpec (entry)); if (newEntry.type () == entry) throw ParseException.recursive (scanner, entry.fullName (), (token.name == null) ? "" : token.name); // <d46094> Exception cannot appear within a struct, union, or exception if (typeOf (newEntry) instanceof ExceptionEntry) throw ParseException.illegalException (scanner, entryName (entry)); declarators (newEntry, entry.members ()); match (Token.Semicolon); } catch (ParseException exception) { skipToSemicolon (); } } // member /** * **/ private final boolean isConstTypeSpec (Token t) { return (t.type == Token.Struct || t.type == Token.Union || t.type == Token.Enum); } // isConstTypeSpec /** * **/ private UnionEntry unionType (SymtabEntry entry) throws IOException, ParseException { match (Token.Union) ; String name = token.name ; match (Token.Identifier) ; UnionEntry unionEntry = null ; if (token.type == Token.Switch) { repIDStack.push (((IDLID)repIDStack.peek ()).clone ()); unionEntry = makeUnionEntry( name, entry, false ) ; ((IDLID)repIDStack.peek ()).appendToName (name); match (Token.Switch); match (Token.LeftParen); unionEntry.type (switchTypeSpec (unionEntry)); match (Token.RightParen); prep.openScope (unionEntry); match (Token.LeftBrace); switchBody (unionEntry); verifyUnion (unionEntry); prep.closeScope (unionEntry); match (Token.RightBrace); repIDStack.pop (); } else if (token.equals( Token.Semicolon )) { unionEntry = makeUnionEntry( name, entry, true ) ; } else { throw ParseException.syntaxError (scanner, new int[] { Token.Semicolon, Token.Switch }, token.type); } return unionEntry ; } // unionType private UnionEntry makeUnionEntry( String name, SymtabEntry entry, boolean isForward ) { UnionEntry unionEntry = stFactory.unionEntry (entry, (IDLID)repIDStack.peek () ); unionEntry.isReferencable( !isForward ) ; unionEntry.sourceFile (scanner.fileEntry ()); unionEntry.name (name); // Comment must immediately preceed "union" keyword unionEntry.comment (tokenHistory.lookBack (1).comment); pigeonhole( entry, unionEntry ) ; return unionEntry ; } /** * **/ private void verifyUnion (UnionEntry u) { if (u.typeName ().equals (overrideName ("boolean"))) { if (caseCount (u) > 2) ParseException.noDefault (scanner); } else if (u.type () instanceof EnumEntry) { if (caseCount (u) > ((EnumEntry)u.type ()).elements ().size ()) ParseException.noDefault (scanner); } } // verifyUnion /** * **/ private long caseCount (UnionEntry u) { long cases = 0; Enumeration branches = u.branches ().elements (); while (branches.hasMoreElements ()) { UnionBranch branch = (UnionBranch)branches.nextElement (); cases += branch.labels.size (); if (branch.isDefault) ++cases; } return cases; } // caseCount /** * **/ private SymtabEntry switchTypeSpec (UnionEntry entry) throws IOException, ParseException { SymtabEntry ret = null; switch (token.type) { case Token.Long: case Token.Short: case Token.Unsigned: return integerType (entry); case Token.Char: case Token.Wchar: return charType(); case Token.Boolean: return booleanType(); case Token.Enum: return enumType (entry); case Token.Identifier: case Token.DoubleColon: ret = scopedName (entry, stFactory.primitiveEntry ()); if (hasArrayInfo (entry.type ())) ParseException.illegalArray (scanner, "switch"); SymtabEntry retType = typeOf (ret); if (!(retType instanceof EnumEntry || retType instanceof PrimitiveEntry)) ParseException.wrongType (scanner, ret.fullName (), "long, unsigned long, short, unsigned short, char, boolean, enum", entryName (ret.type ())); else if (ret instanceof PrimitiveEntry) { SymtabEntry octet = qualifiedEntry ("octet"); SymtabEntry flt = qualifiedEntry ("float"); SymtabEntry dbl = qualifiedEntry ("double"); if (retType == octet || retType == flt || retType == dbl) ParseException.wrongType (scanner, ret.fullName(), "long, unsigned long, short, unsigned short, char, boolean, enum", entryName(ret.type ())); } break; default: throw ParseException.syntaxError (scanner, new int [] { Token.Long, Token.Short, Token.Unsigned, Token.Char, Token.Boolean, Token.Enum, Token.Identifier, Token.DoubleColon }, token.type); } return ret; } // switchTypeSpec // This is only used by the union methods UnionBranch defaultBranch = null; /** * **/ private void switchBody (UnionEntry entry) throws IOException, ParseException { caseProd (entry); while (!token.equals (Token.RightBrace)) caseProd (entry); entry.defaultBranch ((defaultBranch == null) ? null : defaultBranch.typedef); defaultBranch = null; } // switchBody /** * **/ private void caseProd (UnionEntry entry) throws IOException, ParseException { UnionBranch branch = new UnionBranch (); entry.addBranch (branch); caseLabel (entry, branch); while (token.equals (Token.Case) || token.equals (Token.Default)) caseLabel (entry, branch); elementSpec (entry, branch); match (Token.Semicolon); } // caseProd /** * **/ private void caseLabel (UnionEntry entry, UnionBranch branch) throws IOException, ParseException { if (token.type == Token.Case) { match (Token.Case); ConstEntry tmpEntry = stFactory.constEntry (entry, (IDLID)repIDStack.peek ()); tmpEntry.sourceFile (scanner.fileEntry ()); tmpEntry.type (entry); Expression label; SymtabEntry type = typeOf (entry.type ()); if (type instanceof EnumEntry) label = matchEnum ((EnumEntry)type); else { label = constExp (tmpEntry); verifyConstType (label, type); } if (entry.has (label)) ParseException.branchLabel (scanner, label.rep ()); branch.labels.addElement (label); match (Token.Colon); } else if (token.type == Token.Default) { match (Token.Default); match (Token.Colon); if (entry.defaultBranch () != null) ParseException.alreadyDefaulted (scanner); branch.isDefault = true; defaultBranch = branch; } else throw ParseException.syntaxError (scanner, new int [] { Token.Case, Token.Default }, token.type); } // caselabel /** * **/ private Expression matchEnum (EnumEntry entry) throws IOException, ParseException { // Get the symbol table entry for the case label based on the // scope of the EnumEntry, NOT the UnionEntry (the union could be // in a different scope than the enum). Given // module M { enum E {A, B, C, D}; }; // a case label for A could be one of the following: // case A: // case M::A: // case ::M::A: SymtabEntry label = scopedName (entry.container(), new SymtabEntry ()); return exprFactory.terminal (label.name (), false); } // matchEnum /** * **/ private void elementSpec (UnionEntry entry, UnionBranch branch) throws IOException, ParseException { TypedefEntry typedef = stFactory.typedefEntry (entry, (IDLID)repIDStack.peek ()); typedef.sourceFile (scanner.fileEntry ()); // Comment must immediately precede <type_spec> lexeme typedef.comment (token.comment); typedef.type (typeSpec (entry)); if (typedef.type () == entry) throw ParseException.recursive (scanner, entry.fullName (), (token.name == null)? "" : token.name); // <d46094> Exception cannot appear within a struct, union, or exception if (typeOf (typedef) instanceof ExceptionEntry) throw ParseException.illegalException (scanner, entryName (entry)); declarator (typedef); branch.typedef = typedef; // Ensure a branch with the same name doesn't already exist. if (entry.has (typedef)) ParseException.branchName (scanner, typedef.name ()); } // elementSpec /** * **/ private EnumEntry enumType (SymtabEntry entry) throws IOException, ParseException { match (Token.Enum); EnumEntry enumEntry = newEnumEntry (entry); // comment must immediately precede "enum" keyword enumEntry.comment (tokenHistory.lookBack (1).comment); enumEntry.name (token.name); match (Token.Identifier); prep.openScope (enumEntry); match (Token.LeftBrace); if (isntInStringList (enumEntry.elements (), token.name)) { enumEntry.addElement (token.name); SymtabEntry element = new SymtabEntry (entry, (IDLID)repIDStack.peek ()); // if block taken from EnumEntry ctor if (element.module ().equals ("")) element.module (element.name ()); else if (!element.name ().equals ("")) element.module (element.module () + "/" + element.name ()); element.name (token.name); // <d50237> Place the SymtabEntry representing this enumeration // contant into the SymtabEntry defining its scope (e.g., InterfaceEntry, // ValueEntry, etc.) rather than the SymtabEntry passed in, which // may not define the contant's scope (e.g., TypedefEntry). //pigeonhole (entry, element); } <daz> pigeonhole (enumEntry.container (), element); } match (Token.Identifier); enumType2 (enumEntry); prep.closeScope (enumEntry); match (Token.RightBrace); return enumEntry; } // enumType /** * **/ private void enumType2 (EnumEntry entry) throws IOException, ParseException { while (token.type == Token.Comma) { match (Token.Comma); String name = token.name; match (Token.Identifier); if (isntInStringList (entry.elements (), name)) { entry.addElement (name); SymtabEntry element = new SymtabEntry (entry.container (), (IDLID)repIDStack.peek ()); // if block taken from EnumEntry ctor: if (element.module ().equals ("")) element.module (element.name ()); else if (!element.name().equals ("")) element.module (element.module () + "/" + element.name ()); element.name (name); pigeonhole (entry.container (), element); } } } // enumType2 /** * **/ private SequenceEntry sequenceType (SymtabEntry entry) throws IOException, ParseException { match (Token.Sequence); match (Token.LessThan); SequenceEntry newEntry = newSequenceEntry (entry); SymtabEntry tsentry = simpleTypeSpec (newEntry, false ); newEntry.type (tsentry); if (!tsentry.isReferencable()) { // This is a sequence type that is referencing an // incomplete forward declaration of a struct or // union. Save the sequence in a list for later // backpatching. try { List fwdTypes = (List)tsentry.dynamicVariable( ftlKey ) ; if (fwdTypes == null) { fwdTypes = new ArrayList() ; tsentry.dynamicVariable( ftlKey, fwdTypes ) ; } fwdTypes.add( newEntry ) ; } catch (NoSuchFieldException exc) { throw new IllegalStateException() ; } } if (token.type == Token.Comma) { match (Token.Comma); ConstEntry tmpEntry = stFactory.constEntry (newEntry, (IDLID)repIDStack.peek ()); tmpEntry.sourceFile (scanner.fileEntry ()); tmpEntry.type (qualifiedEntry ("long")); newEntry.maxSize (positiveIntConst (tmpEntry)); verifyConstType (newEntry.maxSize(), qualifiedEntry ("long")); } match (Token.GreaterThan); return newEntry; } // sequenceType /** * **/ private StringEntry stringType (SymtabEntry entry) throws IOException, ParseException { StringEntry string = stFactory.stringEntry (); if (token.type == Token.String) { string.name (overrideName ("string")); match (Token.String); } else { string.name (overrideName ("wstring")); match (Token.Wstring); } string.maxSize (stringType2 (entry)); return string; } // stringType /** * **/ private Expression stringType2 (SymtabEntry entry) throws IOException, ParseException { if (token.type == Token.LessThan) { match (Token.LessThan); // START IBM.11417 failure in the IDL compiler //Expression maxSize = positiveIntConst (entry); IBM.11417 ConstEntry tmpEntry = stFactory.constEntry (entry, (IDLID)repIDStack.peek ()); tmpEntry.sourceFile (scanner.fileEntry ()); tmpEntry.type (qualifiedEntry ("long")); Expression maxSize = positiveIntConst (tmpEntry); // END IBM.11417 verifyConstType (maxSize, qualifiedEntry ("long")); match (Token.GreaterThan); return maxSize; } return null; } // stringType2 /** * **/ private void fixedArraySize (TypedefEntry entry) throws IOException, ParseException { match (Token.LeftBracket); ConstEntry tmpEntry = stFactory.constEntry (entry, (IDLID)repIDStack.peek ()); tmpEntry.sourceFile (scanner.fileEntry ()); // <d58058> Set type of tmpExpr to "long", which is the array index type. // Previously, this type was erroneously set to the array element type. //tmpEntry.type (entry.type ()); tmpEntry.type (qualifiedEntry ("long")); Expression expr = positiveIntConst (tmpEntry); entry.addArrayInfo (expr); verifyConstType (expr, qualifiedEntry ("long")); match (Token.RightBracket); } // fixedArraySize /** * **/ private void attrDcl (InterfaceEntry entry) throws IOException, ParseException { AttributeEntry attribute = stFactory.attributeEntry (entry, (IDLID)repIDStack.peek ()); attribute.sourceFile (scanner.fileEntry ()); // Comment must immediately precede the "attribute" keyword. Save the // comment preceding the declaration for use below. attribute.comment (token.comment); Comment dclComment = attribute.comment (); if (token.type == Token.Readonly) { match (Token.Readonly); attribute.readOnly (true); } match (Token.Attribute); attribute.type (paramTypeSpec (attribute)); attribute.name (token.name); // Override declaration comment if attribute identifier is commented if (!token.comment.text ().equals ("")) attribute.comment (token.comment); entry.methodsAddElement (attribute, scanner); pigeonholeMethod (entry, attribute); // Declaration comment was overriden: if (!token.comment.text ().equals ("")) { // Create a temporary attribute with declaration comment so cloning in // attrdcl2() can use declaration comment as default. AttributeEntry attributeClone = (AttributeEntry) attribute.clone (); attributeClone.comment (dclComment); match (Token.Identifier); attrDcl2 (entry, attributeClone); } else { match (Token.Identifier); attrDcl2 (entry, attribute); } //match (Token.Identifier); //attrDcl2 (entry, attribute); } // attrDcl /** * **/ private void attrDcl2 (InterfaceEntry entry, AttributeEntry clone) throws IOException, ParseException { while (token.type == Token.Comma) { match (Token.Comma); AttributeEntry attribute = (AttributeEntry)clone.clone (); attribute.name (token.name); // Override the declaration comment (i.e., that preceding the // "attribute" keyword) if the attribute identifier is commented. if (!token.comment.text ().equals ("")) attribute.comment (token.comment); entry.methodsAddElement (attribute, scanner); pigeonholeMethod (entry, attribute); match (Token.Identifier); } } // attrDcl2 /** * **/ private void exceptDcl (SymtabEntry entry) throws IOException, ParseException { match (Token.Exception); repIDStack.push (((IDLID)repIDStack.peek ()).clone ()); ExceptionEntry exceptEntry = stFactory.exceptionEntry (entry, (IDLID)repIDStack.peek ()); ((IDLID)repIDStack.peek ()).appendToName (token.name); exceptEntry.sourceFile (scanner.fileEntry ()); // Comment must immediately precede "exception" keyword exceptEntry.comment (tokenHistory.lookBack (1).comment); exceptEntry.name (token.name); match (Token.Identifier); pigeonhole (entry, exceptEntry); if (token.equals (Token.LeftBrace)) { prep.openScope (exceptEntry); match (Token.LeftBrace); memberList2 (exceptEntry); prep.closeScope (exceptEntry); match (Token.RightBrace); repIDStack.pop (); } else throw ParseException.syntaxError (scanner, Token.LeftBrace,token.type); } // exceptDcl /** * **/ private void opDcl (InterfaceEntry entry) throws IOException, ParseException { MethodEntry method = stFactory.methodEntry (entry, (IDLID)repIDStack.peek ()); method.sourceFile (scanner.fileEntry ()); // Comment must immediately precede "oneway" keyword or <return_type_spec> method.comment (token.comment); if (token.type == Token.Oneway) { match (Token.Oneway); method.oneway (true); } method.type (opTypeSpec (method)); repIDStack.push (((IDLID)repIDStack.peek ()).clone ()); ((IDLID)repIDStack.peek ()).appendToName (token.name); method.name (token.name); entry.methodsAddElement (method, scanner); pigeonholeMethod (entry, method); opDcl2 (method); if (method.oneway ()) checkIfOpLegalForOneway (method); repIDStack.pop (); } // opDcl /** * **/ private void checkIfOpLegalForOneway (MethodEntry method) { boolean notLegal = false; if ((method.type() != null) || (method.exceptions().size() != 0)) notLegal = true; else { for (Enumeration e = method.parameters().elements(); e.hasMoreElements();) { if (((ParameterEntry)e.nextElement ()).passType () != ParameterEntry.In) { notLegal = true; break; } } } if (notLegal) ParseException.oneway (scanner, method.name ()); } // checkifOpLegalForOneway /** * **/ private void opDcl2 (MethodEntry method) throws IOException, ParseException { if (token.equals (Token.MacroIdentifier)) { match (Token.MacroIdentifier); parameterDcls2 (method); } else { match (Token.Identifier); parameterDcls (method); } opDcl3 (method); } // opDcl2 /** * **/ private void opDcl3 (MethodEntry entry) throws IOException, ParseException { if (token.type != Token.Semicolon) { if (!token.equals (Token.Raises) && !token.equals (Token.Context)) throw ParseException.syntaxError (scanner, new int [] { Token.Raises, Token.Context, Token.Semicolon }, token.type); if (token.type == Token.Raises) raisesExpr (entry); if (token.type == Token.Context) contextExpr (entry); } } // opDcl3 /** * **/ private SymtabEntry opTypeSpec (SymtabEntry entry) throws IOException, ParseException { SymtabEntry ret = null; if (token.type == Token.Void) match (Token.Void); else ret = paramTypeSpec (entry); return ret; } // opTypeSpec /** * **/ private void parameterDcls (MethodEntry entry) throws IOException, ParseException { match (Token.LeftParen); parameterDcls2 (entry); } // parameterDcls /** * **/ private void parameterDcls2 (MethodEntry entry) throws IOException, ParseException { if (token.type == Token.RightParen) match (Token.RightParen); else { paramDcl (entry); while (token.type == Token.Comma) { match (Token.Comma); paramDcl (entry); } match (Token.RightParen); } } // paraneterDcls2 /** * **/ private void paramDcl (MethodEntry entry) throws IOException, ParseException { ParameterEntry parmEntry = stFactory.parameterEntry (entry, (IDLID)repIDStack.peek ()); parmEntry.sourceFile (scanner.fileEntry ()); // Comment must immeiately precede the parameter attribute parmEntry.comment (token.comment); paramAttribute (parmEntry); parmEntry.type (paramTypeSpec (entry)); parmEntry.name (token.name); match (Token.Identifier); if (isntInList (entry.parameters (), parmEntry.name ())) entry.addParameter (parmEntry); } // paramDcl /** * **/ private void paramAttribute (ParameterEntry entry) throws IOException, ParseException { if (token.type == Token.In) { entry.passType (ParameterEntry.In); match (Token.In); } else if (token.type == Token.Out) { entry.passType (ParameterEntry.Out); match (Token.Out); } else if (token.type == Token.Inout) { entry.passType (ParameterEntry.Inout); match (Token.Inout); } else throw ParseException.syntaxError (scanner, new int [] { Token.In, Token.Out, Token.Inout }, token.type); } // paramAttribute /** * **/ private void raisesExpr (MethodEntry entry) throws IOException, ParseException { match (Token.Raises); match (Token.LeftParen); // Comment must immediately precede <scoped_name> for exception Comment tempComment = token.comment; SymtabEntry exception = scopedName(entry.container (), stFactory.exceptionEntry ()); if (typeOf (exception) instanceof ExceptionEntry) { // Comment must immediately precede <scoped_name> for exception exception.comment (tempComment); if (isntInList (entry.exceptions (), exception)) entry.exceptionsAddElement ((ExceptionEntry) exception); } else ParseException.wrongType (scanner, exception.fullName(), "exception", entryName (exception.type ())); raisesExpr2 (entry); match (Token.RightParen); } // raisesExpr /** * **/ private void raisesExpr2 (MethodEntry entry) throws IOException, ParseException { while (token.type == Token.Comma) { match (Token.Comma); // Comment must immediately precede <scoped_name> of exception Comment tempComment = token.comment; SymtabEntry exception = scopedName (entry.container (), stFactory.exceptionEntry ()); if (typeOf (exception) instanceof ExceptionEntry) { // Comment must immediately precede <scoped_name> of exception exception.comment (tempComment); if (isntInList (entry.exceptions (), exception)) entry.addException ((ExceptionEntry)exception); } else ParseException.wrongType (scanner, exception.fullName (), "exception", entryName (exception.type ())); } } // raisesExpr2 /** * **/ private void contextExpr (MethodEntry entry) throws IOException, ParseException { match (Token.Context); match (Token.LeftParen); String stringLit = (String)stringLiteral ().value (); if (isntInStringList (entry.contexts (), stringLit)) entry.addContext (stringLit); contextExpr2 (entry); match (Token.RightParen); } // contextExpr private void contextExpr2 (MethodEntry entry) throws IOException, ParseException { while (token.type == Token.Comma) { match (Token.Comma); String stringLit = (String)stringLiteral ().value (); if (isntInStringList (entry.contexts (), stringLit)) entry.addContext (stringLit); } } // contextExpr2 /** * **/ private SymtabEntry paramTypeSpec (SymtabEntry entry) throws IOException, ParseException { SymtabEntry ret = null; switch (token.type) { case Token.Float: case Token.Double: case Token.Long: case Token.Short: case Token.Unsigned: case Token.Char: case Token.Wchar: case Token.Boolean: case Token.Octet: case Token.Any: return baseTypeSpec (entry); case Token.String: case Token.Wstring: return stringType (entry); case Token.Identifier: case Token.Object: // <f46082.40> case Token.ValueBase: case Token.DoubleColon: ret = scopedName (entry.container (), stFactory.primitiveEntry ()); if (typeOf (ret) instanceof AttributeEntry) //ParseException.attributeParamType (scanner); ParseException.attributeNotType (scanner, ret.name ()); else // <d60942> if (typeOf (ret) instanceof MethodEntry) ParseException.operationNotType (scanner, ret.name ()); //if (!(returnType instanceof PrimitiveEntry || // returnType instanceof StringEntry)) //ParseException.wrongType (scanner, ret.fullName(), // "primitive or string", entryName (ret.type())); break; default: throw ParseException.syntaxError (scanner, new int [] { Token.Float, Token.Double, Token.Long, Token.Short, Token.Unsigned, Token.Char, Token.Wchar, Token.Boolean, Token.Octet, Token.Any, Token.String, Token.Wstring, Token.Identifier, Token.DoubleColon, Token.ValueBase }, token.type); } return ret; } // paramTypeSpec /** * **/ private void match (int type) throws IOException, ParseException { ParseException exception = null; if (!token.equals (type)) { exception = ParseException.syntaxError (scanner, type, token.type); // Missing a semicolon is a common error. If a semicolon was expected, // assume it exists and keep the current token (don't get the next one). // BEWARE!!! THIS HAS THE POTENTIAL FOR AN INFINITE LOOP! if (type == Token.Semicolon) return; } // <f46082.40> Unecessary due to new valueElement() algorithm. //if (!tokenStack.empty()) //{ // token = (Token)tokenStack.pop (); // return; //} // Fetch the next token. token = scanner.getToken (); // <d62023> Issue warnings about tokens. issueTokenWarnings (); // Maintain history of most recent tokens. tokenHistory.insert (token); // <d59166> Identifiers that collide with keywords are illegal. Note // that escaped identifers never collide! /* if (token.collidesWithKeyword ()) { // <f60858.1> Issue a warning only if (corbaLevel <= 2.2f) ParseException.keywordCollisionWarning (scanner, token.name); else exception = ParseException.keywordCollision (scanner, token.name); } */ while (token.isDirective ()) token = prep.process (token); // If the token is a defined thingy, scan the defined string // instead of the input stream for a while. if (token.equals (Token.Identifier) || token.equals (Token.MacroIdentifier)) { String string = (String)symbols.get (token.name); if (string != null && !string.equals ("")) { // If this is a macro, parse the macro if (macros.contains (token.name)) { scanner.scanString (prep.expandMacro (string, token)); match (token.type); } else // This is just a normal define. { scanner.scanString (string); match (token.type); } } } if (exception != null) throw exception; } // match // <d62023> /** * Issue warnings according to attributes of current Token. **/ private void issueTokenWarnings () { if (noWarn) return; if ((token.equals (Token.Identifier) || token.equals (Token.MacroIdentifier)) && !token.isEscaped ()) { // Identifier collision with keyword in another release. // Identifier collision with keyword in letter, but not in case. if (token.collidesWithKeyword ()) ParseException.warning (scanner, Util.getMessage ("Migration.keywordCollision", token.name)); } // Deprecated keyword. if (token.isKeyword () && token.isDeprecated ()) ParseException.warning (scanner, Util.getMessage ("Deprecated.keyword", token.toString ())); } // issueTokenWarnings /** * **/ private ModuleEntry newModule (ModuleEntry oldEntry) { ModuleEntry entry = stFactory.moduleEntry (oldEntry, (IDLID)repIDStack.peek ()); entry.sourceFile (scanner.fileEntry ()); entry.name (token.name); // If this named module already exists, just reopen it. /* <46082.46.01> if cppModule, always create new module entry */ SymtabEntry prevEntry = (SymtabEntry) symbolTable.get (entry.fullName ()); if (!cppModule && prevEntry != null && prevEntry instanceof ModuleEntry) { // A module has been reopened, return that ModuleEntry. entry = (ModuleEntry) prevEntry; if (oldEntry == topLevelModule) { // Do a little checking: if (!entry.emit ()) // The entry module is being reopened to put new stuff into it. // The module itself is not marked as "emit", but the new stuff // may be, so put the module on the emitList (add it to topLevelModule). addToContainer (oldEntry, entry); else if (!oldEntry.contained().contains (entry)) // <d50767> The entry module being reopened is to be emitted, but // will not be placed on the emitList! I.E., it was not added to // topLevelModule. Occurs when a generator manually inserts // ModuleEntrys into the symbol table (e.g., org; see preParse() // in ...idl.toJava.Compile). <daz> addToContainer (oldEntry, entry); } } else pigeonhole (oldEntry, entry); return entry; } // newModule /** * **/ private EnumEntry newEnumEntry (SymtabEntry oldEntry) { EnumEntry entry = stFactory.enumEntry (oldEntry, (IDLID)repIDStack.peek ()); entry.sourceFile (scanner.fileEntry ()); entry.name (token.name); pigeonhole (oldEntry, entry); return entry; } // newEnumEntry /** * **/ private SequenceEntry newSequenceEntry (SymtabEntry oldEntry) { SequenceEntry entry = stFactory.sequenceEntry (oldEntry, (IDLID)repIDStack.peek ()); entry.sourceFile (scanner.fileEntry ()); entry.name (""); pigeonhole (oldEntry, entry); return entry; } // newSequenceEntry private void updateSymbolTable( String fullName, SymtabEntry entry, boolean lcCheck ) { // Check for case-insensitive collision (IDL error). String lcFullName = fullName.toLowerCase(); if (lcCheck) if (lcSymbolTable.get (lcFullName) != null) { ParseException.alreadyDeclared (scanner, fullName); } symbolTable.put (fullName, entry); lcSymbolTable.put (lcFullName, entry); // <d59809> Allow fully-qualified CORBA types to be resolved by mapping // short name (e.g., CORBA/StringValue) to long name, actual name. String omgPrefix = "org/omg/CORBA" ; if (fullName.startsWith (omgPrefix)) { overrideNames.put ( "CORBA" + fullName.substring (omgPrefix.length()), fullName); } } private void pigeonhole (SymtabEntry container, SymtabEntry entry) { if (entry.name().equals ("")) entry.name (unknownNamePrefix + ++sequence); // If this object is not in the overrides list, then it is // ok to put it in the table (if it IS in the overrides list, // it is already in the table under a different name). String fullName = entry.fullName(); if (overrideNames.get (fullName) == null) { addToContainer (container, entry); // It is an error is this name already exists in the symbol // table, unless this is a redefinition of a forward decl. // Re-opening a module is also legal, but not handled here. SymtabEntry oldEntry = (SymtabEntry) symbolTable.get (fullName); if (oldEntry == null) { updateSymbolTable( fullName, entry, true ) ; } else if (oldEntry instanceof ForwardEntry && entry instanceof InterfaceEntry) { String repIDPrefix = ((IDLID)entry.repositoryID ()).prefix (); String oldRepIDPrefix = ((IDLID)oldEntry.repositoryID ()).prefix (); if (repIDPrefix.equals (oldRepIDPrefix)) { updateSymbolTable( fullName, entry, false ) ; } else { ParseException.badRepIDPrefix (scanner, fullName, oldRepIDPrefix, repIDPrefix); } } else if (entry instanceof ForwardEntry && (oldEntry instanceof InterfaceEntry || oldEntry instanceof ForwardEntry)) { if (oldEntry instanceof ForwardEntry && entry.repositoryID () instanceof IDLID && oldEntry.repositoryID () instanceof IDLID) { String repIDPrefix = ((IDLID)entry.repositoryID ()).prefix (); String oldRepIDPrefix = ((IDLID)oldEntry.repositoryID ()).prefix (); if (!(repIDPrefix.equals (oldRepIDPrefix))) { // Disallow multiple ForwardEntry's having same Repository // ID prefixes (CORBA 2.3). ParseException.badRepIDPrefix (scanner, fullName, oldRepIDPrefix, repIDPrefix); } } } else if (cppModule && entry instanceof ModuleEntry && oldEntry instanceof ModuleEntry) { // Allow multiple ModuleEntrys when user submits // the -cppModule flag. } else if (fullName.startsWith ("org/omg/CORBA") || fullName.startsWith ("CORBA")) { // Ignore CORBA PIDL types entered at preParse() by generator. } else if (isForwardable( oldEntry, entry )) { // Both oldEntry and entry are structs or unions. // Legality depends on isReferencable on the two entries: // oldEntry Entry // T T ERROR alreadyDeclared // T F legal fwd decl // F T if defined in same file legal, // otherwise ERROR // F F legal fwd decl if (oldEntry.isReferencable() && entry.isReferencable()) ParseException.alreadyDeclared (scanner, fullName); if (entry.isReferencable()) { String firstFile = oldEntry.sourceFile().absFilename() ; String defFile = entry.sourceFile().absFilename() ; if (!firstFile.equals( defFile )) ParseException.declNotInSameFile( scanner, fullName, firstFile ) ; else { updateSymbolTable( fullName, entry, false ) ; List oldRefList ; try { oldRefList = (List)oldEntry.dynamicVariable( ftlKey ) ; } catch (NoSuchFieldException exc) { throw new IllegalStateException() ; } if (oldRefList != null) { // Update entries in backpatch list Iterator iter = oldRefList.iterator() ; while (iter.hasNext()) { SymtabEntry elem = (SymtabEntry)iter.next() ; elem.type( entry ) ; } } } } } else { ParseException.alreadyDeclared (scanner, fullName); } } } // pigeonhole private boolean isForwardable( SymtabEntry oldEntry, SymtabEntry entry ) { return ((oldEntry instanceof StructEntry) && (entry instanceof StructEntry)) || ((oldEntry instanceof UnionEntry) && (entry instanceof UnionEntry)) ; } // pigeonhole checks to see if this entry is already in the symbol // table and generates an error if it is. Methods must be checked // not only against the symbol table but also against their // interface's parent's methods. This is done in InterfaceEntry. // verifyMethod, so no checking need be done here. /** * **/ private void pigeonholeMethod (InterfaceEntry container, MethodEntry entry) { if (entry.name ().equals ("")) entry.name (unknownNamePrefix + ++sequence); // If this object is not in the overrides list, then it is // ok to put it in the table (if it IS in the overrides list, // it is already in the table under a different name). String fullName = entry.fullName (); if (overrideNames.get (fullName) == null) { addToContainer (container, entry); String lcFullName = fullName.toLowerCase (); symbolTable.put (fullName, entry); lcSymbolTable.put (lcFullName, entry); // <d59809> Allow fully-qualified CORBA types to be resolved by mapping // short name (e.g., CORBA/StringValue) to long name, actual name. if (fullName.startsWith ("org/omg/CORBA")) overrideNames.put ("CORBA" + fullName.substring (13), fullName); } } // pigeonholeMethod /** * **/ private void addToContainer (SymtabEntry container, SymtabEntry contained) { if (container instanceof ModuleEntry) ((ModuleEntry)container).addContained (contained); else if (container instanceof InterfaceEntry) ((InterfaceEntry)container).addContained (contained); else if (container instanceof StructEntry) ((StructEntry)container).addContained (contained); else if (container instanceof UnionEntry) ((UnionEntry)container).addContained (contained); else if (container instanceof SequenceEntry) ((SequenceEntry)container).addContained (contained); } // addToContainer // NOTE: qualifiedEntry/partlyQualifiedEntry/unqualifiedEntry and // their court could probably use some performance improvements, // but I'm scared to touch anything. It's the most complex bit of // code in this parser. // The qualified named type is searched for in the following order: // 1. OverrideNames // 2. Global scope // 3. Inheritance scope (if container is an interface) // A qualified name is one which begins with :: or is assumed to be // in the global scope (like long, short, etc). /** * **/ SymtabEntry qualifiedEntry (String typeName) { SymtabEntry type = recursiveQualifiedEntry (typeName); if (type == null) // Then it's not anywhere, report the error. ParseException.undeclaredType (scanner, typeName); // <d57110> Relax this retriction when parsing ID pragma directive, e.g.. //else if (type instanceof ModuleEntry) { else if (type instanceof ModuleEntry && !_isModuleLegalType) { // Module's are not valid types. ParseException.moduleNotType (scanner, typeName); type = null; } return type; } // qualifiedEntry /** * **/ SymtabEntry recursiveQualifiedEntry (String typeName) { SymtabEntry type = null; if (typeName != null && !typeName.equals ("void")) { int index = typeName.lastIndexOf ('/'); if (index >= 0) { // Figure out if the container of this thing exists, converting any typedefs to interfaces if necessary. type = recursiveQualifiedEntry (typeName.substring (0, index)); if (type == null) return null; else if (type instanceof TypedefEntry) typeName = typeOf (type).fullName () + typeName.substring (index); } // If we got this far, a container exists, start over looking // for the thing itself (this is the meat of the method): type = searchOverrideNames (typeName); if (type == null) type = (SymtabEntry) symbolTable.get (typeName); // search global scope: if (type == null) type = searchGlobalInheritanceScope (typeName); } return type; } // recursiveQualifiedEntry // A partially qualified name is of the form <scope>::<name>. // First the scope is defined (meaning it is fully qualified); // Then the name is searched for in the scope. /** * **/ SymtabEntry partlyQualifiedEntry (String typeName, SymtabEntry container) { // This is the simple logic of this method: // type = searchModuleScope (typeName.substring (0, typeName.lastIndexOf ('/')), container); // type = qualifiedEntry (type.fullName () + typeName.substring (typeName.lastIndexOf ('/'))); // But searchModuleScope only finds the first module that fits. // The name might not be in that module but in one further out // in the module scope. Should others be searched? SymtabEntry type = null; if (typeName != null) { int index = typeName.lastIndexOf ('/'); // Figure out if the container of this thing exists, converting any // typedefs to interfaces if necessary: type = recursivePQEntry (typeName.substring (0, index), container); if (type instanceof TypedefEntry) typeName = typeOf (type).fullName () + typeName.substring (index); // If we got this far, a container exists, start over looking // for the thing itself. if (container != null) type = searchModuleScope (typeName.substring (0, typeName.lastIndexOf ('/')), container); if (type == null) type = qualifiedEntry (typeName); else type = qualifiedEntry (type.fullName () + typeName.substring (typeName.lastIndexOf ('/'))); } return type; } // partlyQualifiedEntry // partlyQualifiedEntry and recursivePQEntry are almost identical. // They are different because when the recursive one is looking for // the existence of containers, the error check for a module type // must not occur (this check is done in qualifiedEntry). Only // when the full partly qualified name is being processed must this // check be performed. /** * **/ SymtabEntry recursivePQEntry (String typeName, SymtabEntry container) { SymtabEntry type = null; if (typeName != null) { int index = typeName.lastIndexOf ('/'); if (index < 0) type = searchModuleScope (typeName, container); else { // Figure out if the container of this thing exists, converting any // typedefs to interfaces if necessary: type = recursivePQEntry (typeName.substring (0, index), container); if (type == null) return null; else if (type instanceof TypedefEntry) typeName = typeOf (type).fullName () + typeName.substring (index); // If we got this far, a container exists, start over, looking // for the thing itself (This is the meat of the method): if (container != null) type = searchModuleScope (typeName.substring (0, typeName.lastIndexOf ('/')), container); if (type == null) recursiveQualifiedEntry (typeName); else type = recursiveQualifiedEntry (type.fullName () + typeName.substring (typeName.lastIndexOf ('/'))); } } return type; } // recursivePQEntry // The named type is searched for in the following order: // 1. Local scope // 2. Inheritance scope // 3. OverrideNames // 4. Module scope /** * **/ SymtabEntry unqualifiedEntry (String typeName, SymtabEntry container) { SymtabEntry type = unqualifiedEntryWMod (typeName, container); // <d57110> Relax this retriction in special cases, e.g., when // parsing a ID pragma directive. //if (type instanceof ModuleEntry) { if (type instanceof ModuleEntry && !_isModuleLegalType) { // Module's are not valid types: ParseException.moduleNotType (scanner, typeName); type = null; } return type; } // unqualifiedEntry /** * **/ SymtabEntry unqualifiedEntryWMod (String typeName, SymtabEntry container) { SymtabEntry type = null; if ((typeName != null) && !typeName.equals ("void")) { // Search local scope: type = (SymtabEntry)symbolTable.get (container.fullName () + '/' + typeName); if (type == null) type = searchLocalInheritanceScope (typeName, container); if (type == null) type = searchOverrideNames (typeName); if ((type == null) && (container != null)) type = searchModuleScope (typeName, container); if (type == null) type = searchParentInheritanceScope (typeName, container); } if (type == null) // Then it's not anywhere, report the error: ParseException.undeclaredType (scanner, typeName); return type; } // unqualifiedEntryWMod /** * Walks up the enclosing scopes until it finds an interface type. Then, * searches up that interface inheritance tree for the type definition. * * @param name type name to be searched for. * @param ptype parent type entry. **/ SymtabEntry searchParentInheritanceScope(String name, SymtabEntry ptype) { String cname = ptype.fullName(); while ((ptype != null) && !(cname.equals ("")) && !(ptype instanceof InterfaceEntry)) { int index = cname.lastIndexOf ('/'); if (index < 0) { cname = ""; } else { cname = cname.substring (0, index); ptype = (SymtabEntry) symbolTable.get(cname); } } if ((ptype == null) || !(ptype instanceof InterfaceEntry)) { return null; // could not find an enclosing interface type - give up. } // check if the enclosing interface supports the type definition. String fullName = ptype.fullName () + '/' + name; SymtabEntry type = (SymtabEntry) symbolTable.get (fullName); if (type != null) { return type; // found type definition. } // search up the interface inheritance tree. return searchLocalInheritanceScope(name, ptype); } /** * **/ SymtabEntry searchGlobalInheritanceScope (String name) { // See if the container of this named object is an interface: int index = name.lastIndexOf ('/'); SymtabEntry entry = null; if (index >= 0) { String containerName = name.substring (0, index); entry = (SymtabEntry)symbolTable.get (containerName); entry = (entry instanceof InterfaceEntry) // It's an interface, now look in its inheritance scope: ? searchLocalInheritanceScope (name.substring (index + 1), entry) : null; } return entry; } // searchGlobalInheritanceScope /** * **/ SymtabEntry searchLocalInheritanceScope (String name, SymtabEntry container) { return (container instanceof InterfaceEntry) ? searchDerivedFrom (name, (InterfaceEntry) container) : null; } // searchLocalInheritanceScope /** * **/ SymtabEntry searchOverrideNames (String name) { String overrideName = (String)overrideNames.get (name); return (overrideName != null) ? (SymtabEntry)symbolTable.get (overrideName) : null; } // searchOverrideNames /** * **/ SymtabEntry searchModuleScope (String name, SymtabEntry container) { String module = container.fullName (); String fullName = module + '/' + name; SymtabEntry type = (SymtabEntry)symbolTable.get (fullName); while ((type == null) && !module.equals ("")) { int index = module.lastIndexOf ('/'); if (index < 0) module = ""; else { module = module.substring (0, index); fullName = module + '/' + name; type = (SymtabEntry)symbolTable.get (fullName); } } return (type == null) ? (SymtabEntry)symbolTable.get (name) : type; } // searchModuleScope /** * **/ SymtabEntry searchDerivedFrom (String name, InterfaceEntry i) { for (Enumeration e = i.derivedFrom ().elements (); e.hasMoreElements ();) { SymtabEntry tmp = (SymtabEntry)e.nextElement (); if (tmp instanceof InterfaceEntry) { InterfaceEntry parent = (InterfaceEntry)tmp; String fullName = parent.fullName () + '/' + name; SymtabEntry type = (SymtabEntry)symbolTable.get (fullName); if (type != null) return type; type = searchDerivedFrom (name, parent); if (type != null) return type; } // else it is a ForwardEntry and nothing can be done at this point. } return null; } // searchDerivedFrom /** * **/ String entryName (SymtabEntry entry) { if (entry instanceof AttributeEntry) return "attribute"; if (entry instanceof ConstEntry) return "constant"; if (entry instanceof EnumEntry) return "enumeration"; if (entry instanceof ExceptionEntry) return "exception"; if (entry instanceof ValueBoxEntry) return "value box"; if (entry instanceof ForwardValueEntry || entry instanceof ValueEntry) return "value"; if (entry instanceof ForwardEntry || entry instanceof InterfaceEntry) return "interface"; if (entry instanceof MethodEntry) return "method"; if (entry instanceof ModuleEntry) return "module"; if (entry instanceof ParameterEntry) return "parameter"; if (entry instanceof PrimitiveEntry) return "primitive"; if (entry instanceof SequenceEntry) return "sequence"; if (entry instanceof StringEntry) return "string"; if (entry instanceof StructEntry) return "struct"; if (entry instanceof TypedefEntry) return "typedef"; if (entry instanceof UnionEntry) return "union"; return "void"; } // entryName /** * **/ private boolean isInterface (SymtabEntry entry) { return entry instanceof InterfaceEntry || (entry instanceof ForwardEntry && !(entry instanceof ForwardValueEntry)) ; } private boolean isValue (SymtabEntry entry) { return entry instanceof ValueEntry ; // || entry instanceof ForwardValueEntry; } private boolean isInterfaceOnly (SymtabEntry entry) { return entry instanceof InterfaceEntry ; } private boolean isForward(SymtabEntry entry) { return entry instanceof ForwardEntry ; } // list must be a vector of Strings. /** * **/ private boolean isntInStringList (Vector list, String name) { boolean isnt = true; Enumeration e = list.elements (); while (e.hasMoreElements ()) if (name.equals ((String)e.nextElement ())) { ParseException.alreadyDeclared (scanner, name); isnt = false; break; } return isnt; } // isntInStringList // list must be a vector of SymtabEntry's. /** * **/ private boolean isntInList (Vector list, String name) { boolean isnt = true; for (Enumeration e = list.elements (); e.hasMoreElements ();) if (name.equals (((SymtabEntry)e.nextElement ()).name ())) { ParseException.alreadyDeclared (scanner, name); isnt = false; break; } return isnt; } // isntInList // list must be a vector of SymtabEntry's. /** * **/ private boolean isntInList (Vector list, SymtabEntry entry) { boolean isnt = true; for (Enumeration e = list.elements (); e.hasMoreElements ();) { SymtabEntry eEntry = (SymtabEntry)e.nextElement (); if (entry == eEntry) // && entry.fullName().equals (eEntry.fullName())) { ParseException.alreadyDeclared (scanner, entry.fullName ()); isnt = false; break; } } return isnt; } // isntInList /** * **/ public static SymtabEntry typeOf (SymtabEntry entry) { while (entry instanceof TypedefEntry) entry = entry.type (); return entry; } // typeOf /** * **/ void forwardEntryCheck () { for (Enumeration e = symbolTable.elements (); e.hasMoreElements ();) { SymtabEntry entry = (SymtabEntry)e.nextElement (); if (entry instanceof ForwardEntry) ParseException.forwardEntry (scanner, entry.fullName ()); } } // forwardEntryCheck // <46082.03> Revert to "IDL:"-style (i.e., regular) repository ID. /* void updateRepositoryIds () { for (Enumeration e = symbolTable.elements(); e.hasMoreElements();) { SymtabEntry entry = (SymtabEntry) e.nextElement(); if (entry instanceof ValueEntry) ((ValueEntry) entry).calcRepId(); } } // updateRepositoryIds */ //////////////////// // Error Handling Methods // A syntax error occurred. Skip until a semicolon is encountered. // Ignore semicolons within {...} blocks /** * **/ private void skipToSemicolon () throws IOException { while (!token.equals (Token.EOF) && !token.equals (Token.Semicolon)) { if (token.equals (Token.LeftBrace)) skipToRightBrace(); try { match (token.type); } catch (ParseException exception) { // The error has already been reported... } } if (token.equals (Token.EOF)) throw new EOFException (); try { match (Token.Semicolon); } catch (Exception exception) { } } // skipToSemicolon /** * **/ private void skipToRightBrace () throws IOException { boolean firstTime = true; while (!token.equals (Token.EOF) && !token.equals (Token.RightBrace)) { if (firstTime) firstTime = false; else if (token.equals (Token.LeftBrace)) skipToRightBrace (); try { match (token.type); } catch (ParseException exception) { // The error has already been reported... } } if (token.equals (Token.EOF)) throw new EOFException(); } // skipToRightBrace // Error Handling Methods //////////////////// // <d56351> In CORBA 2.3, an IDL file provides a new scope for Repository IDs. // The following methods provide a means for other classes in the framework // to manage this scoping (see Preprocessor and Scanner). // public static int nPush = 0; // public static int nPop = 0; /** * **/ public static void enteringInclude () { repIDStack.push (new IDLID ()); } // enteringInclude /** * **/ public static void exitingInclude () { repIDStack.pop (); } // exitingInclude public static final String unknownNamePrefix = "uN__"; static Hashtable symbolTable; Hashtable lcSymbolTable = new Hashtable (); static Hashtable overrideNames; Vector emitList = new Vector (); boolean emitAll; // <f46082.46.01> boolean cppModule; // <d62023> boolean noWarn; Scanner scanner; // <f46082.40> No longer necessary due to new valueElement() algorithm. // Stack tokenStack = new Stack(); Hashtable symbols; Vector macros = new Vector (); Vector paths; // Only needed for the pragma directive SymtabEntry currentModule = null; // <d56351> Static field necessary to allow Scanner access to enterind/exiting // Include() methods. Must reset in Compile class, too! // Stack repIDStack = new Stack (); static Stack repIDStack = new Stack (); // Dynamic variable key used for forward type lists. // A struct or union X entry may have this attached, // which always contains a List<SymtabEntry>. // The elements are entries E such that E.type() == X. // This list must be resolved in pigeonhole when the // type is finally defined. This is similar to // ForwardEntry.replaceForwardDecl. private static int ftlKey = SymtabEntry.getVariableKey() ; int sequence = 0; Vector includes; Vector includeEntries; // Only needed in primaryExpr. Set in Preprocessor.booleanConstExpr. boolean parsingConditionalExpr = false; Token token; ModuleEntry topLevelModule; private Preprocessor prep; private boolean verbose; SymtabFactory stFactory; ExprFactory exprFactory; private String[] keywords; // <f46082.51> Remove -stateful feature. //private boolean parseStateful = false; // Circular buffer containing most recent tokens, including the current token. private TokenBuffer tokenHistory = new TokenBuffer (); protected float corbaLevel; // <f60858.1> private Arguments arguments; } // class Parser