0001: /*
0002: * Copyright 1999-2004 Sun Microsystems, Inc. All Rights Reserved.
0003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004: *
0005: * This code is free software; you can redistribute it and/or modify it
0006: * under the terms of the GNU General Public License version 2 only, as
0007: * published by the Free Software Foundation. Sun designates this
0008: * particular file as subject to the "Classpath" exception as provided
0009: * by Sun in the LICENSE file that accompanied this code.
0010: *
0011: * This code is distributed in the hope that it will be useful, but WITHOUT
0012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014: * version 2 for more details (a copy is included in the LICENSE file that
0015: * accompanied this code).
0016: *
0017: * You should have received a copy of the GNU General Public License version
0018: * 2 along with this work; if not, write to the Free Software Foundation,
0019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020: *
0021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022: * CA 95054 USA or visit www.sun.com if you need additional information or
0023: * have any questions.
0024: */
0025: /*
0026: * COMPONENT_NAME: idl.parser
0027: *
0028: * ORIGINS: 27
0029: *
0030: * Licensed Materials - Property of IBM
0031: * 5639-D57 (C) COPYRIGHT International Business Machines Corp. 1997, 1999
0032: * RMI-IIOP v1.0
0033: *
0034: * @(#)Parser.java 1.32 07/05/05
0035: */
0036:
0037: package com.sun.tools.corba.se.idl;
0038:
0039: // NOTES:
0040: // -F46082.51<daz> Remove -stateful feature.
0041: // -D52042<daz> Allow floating-point constants to be initialized with
0042: // integral as well as floating-point literals. No other variations allowed.
0043: // -D58058<daz> Set index array type to long rather than array element type.
0044: // -D56351<daz> Update computation of RepositoryIDs to CORBA 2.3 (see spec.).
0045: // -D57110<daz> Provide method() to set/clear ability for scoped names to
0046: // resolve to modules. Allows rep. ids to be assigned to modules.
0047: // -D46094<daz> Prohibit exceptions from appearing wihtin structs, unions, exceptions.
0048: // -D46094<daz> Prohibit attributes from appearing as operation parameter types,
0049: // operation return types, attribute types.
0050: // -D59067<daz> Prohibit nested value boxes.
0051: // -D59166<daz> Prohibit collisions between keywords and non-escaped identifiers.
0052: // -D59809<daz> At Pigeonhole(), add map short name of CORBA types to long name
0053: // (e.g., CORBA/StringValue --> org/omg/CORBA/StringValue), which allows fully-
0054: // qualified CORBA type names to resolve successfully.
0055: // -F60858.1<daz> Support "-corba" option, level <= 2.2: issue warning for
0056: // keyowrd collisions;
0057: // -D60942<daz> Prohibit operations from appearing within parameter types.
0058: // -D61643<daz> Repair pigeonhole() to correctly filter bad RepIDs.
0059: // -D62023<daz> Support -noWarn option; Issue warnings when tokens are
0060: // deprecated keywords or keywords in greater release version.
0061: // -D61919<daz> Emit entries for modules originally opened in #include files
0062: // appearing at global scope and then reopened in the main IDL file. Only
0063: // types appearing in the main IDL source will be emitted.
0064:
0065: import java.io.EOFException;
0066: import java.io.IOException;
0067:
0068: import java.util.Enumeration;
0069: import java.util.Hashtable;
0070: import java.util.Stack;
0071: import java.util.Vector;
0072: import java.util.List;
0073: import java.util.ArrayList;
0074: import java.util.Iterator;
0075:
0076: import java.math.BigInteger;
0077:
0078: import com.sun.tools.corba.se.idl.constExpr.*;
0079:
0080: /**
0081: *
0082: **/
0083: class Parser {
0084: /**
0085: *
0086: **/
0087: Parser(Preprocessor preprocessor, Arguments arguments,
0088: Hashtable overrides, Hashtable symtab, SymtabFactory stFac,
0089: ExprFactory exprFac, String[] genKeywords) {
0090: this .arguments = arguments;
0091: noWarn = arguments.noWarn; // <d62023>
0092: corbaLevel = arguments.corbaLevel; // <f60858.1>
0093: paths = arguments.includePaths;
0094: symbols = arguments.definedSymbols;
0095: verbose = arguments.verbose;
0096: emitAll = arguments.emitAll;
0097: // <f46082.46.01>
0098: cppModule = arguments.cppModule;
0099: // <f46082.51> Remove -stateful feature.
0100: //parseStateful = arguments.parseStateful;
0101: overrideNames = (overrides == null) ? new Hashtable()
0102: : overrides;
0103: symbolTable = (symtab == null) ? new Hashtable() : symtab;
0104: keywords = (genKeywords == null) ? new String[0] : genKeywords;
0105: stFactory = stFac;
0106: exprFactory = exprFac;
0107: currentModule = topLevelModule = new ModuleEntry();
0108: prep = preprocessor;
0109: repIDStack.push(new IDLID());
0110: addPrimEntries();
0111: } // ctor
0112:
0113: /**
0114: *
0115: **/
0116: void parse(String file) throws IOException {
0117: IncludeEntry fileEntry = stFactory.includeEntry();
0118: fileEntry.name('"' + file + '"');
0119: try {
0120: // Set absolute file path
0121: fileEntry.absFilename(Util.getAbsolutePath(file, paths));
0122: } catch (IOException ioe) {
0123: }
0124:
0125: // <f46082.51> Remove -stateful feature.
0126: //scanner = new Scanner (fileEntry, keywords, verbose, parseStateful, emitAll);
0127: // <f60585.1> Support "-corba [level]" option.
0128: //scanner = new Scanner (fileEntry, keywords, verbose, emitAll);
0129: scanner = new Scanner(fileEntry, keywords, verbose, emitAll,
0130: corbaLevel, arguments.scannerDebugFlag);
0131: topLevelModule.sourceFile(fileEntry);
0132:
0133: // Prime the pump...
0134: // Match handles preprocessor directives, so use match to
0135: // call scanner.getToken just in case the first token is
0136: // such a directive. But match depends on the token
0137: // already having a value, so fudge something.
0138: token = new Token(0);
0139: tokenHistory.insert(token); // Initialize look back buffer <26jul1997daz>.
0140: try {
0141: match(0);
0142: if (token.equals(Token.EOF))
0143: ParseException.nothing(file);
0144: else
0145: specification(topLevelModule);
0146: } catch (ParseException exception) // Match MIGHT throw this
0147: {
0148: // It has already been reported, just end.
0149: } catch (EOFException exception) // skipToSemicolon MIGHT throw this
0150: {
0151: // It has already been reported, just end.
0152: }
0153: } // parse
0154:
0155: /**
0156: *
0157: **/
0158: private void addPrimEntries() {
0159: symbolTable.put("short", stFactory.primitiveEntry("short"));
0160: symbolTable.put("long", stFactory.primitiveEntry("long"));
0161: symbolTable.put("long long", stFactory
0162: .primitiveEntry("long long"));
0163: symbolTable.put("unsigned short", stFactory
0164: .primitiveEntry("unsigned short"));
0165: symbolTable.put("unsigned long", stFactory
0166: .primitiveEntry("unsigned long"));
0167: symbolTable.put("unsigned long long", stFactory
0168: .primitiveEntry("unsigned long long"));
0169: symbolTable.put("char", stFactory.primitiveEntry("char"));
0170: symbolTable.put("wchar", stFactory.primitiveEntry("wchar"));
0171: symbolTable.put("float", stFactory.primitiveEntry("float"));
0172: //Support fixed type: symbolTable.put ("fixed", stFactory.primitiveEntry ("fixed"));
0173: symbolTable.put("double", stFactory.primitiveEntry("double"));
0174: symbolTable.put("boolean", stFactory.primitiveEntry("boolean"));
0175: symbolTable.put("octet", stFactory.primitiveEntry("octet"));
0176: symbolTable.put("any", stFactory.primitiveEntry("any"));
0177:
0178: InterfaceEntry object = stFactory.interfaceEntry();
0179: object.name("Object");
0180: symbolTable.put("Object", object);
0181:
0182: ValueEntry valueBase = stFactory.valueEntry();
0183: valueBase.name("ValueBase");
0184: symbolTable.put("ValueBase", valueBase);
0185:
0186: // put these same entries in the lowercase symbol table
0187: lcSymbolTable.put("short", stFactory.primitiveEntry("short"));
0188: lcSymbolTable.put("long", stFactory.primitiveEntry("long"));
0189: lcSymbolTable.put("long long", stFactory
0190: .primitiveEntry("long long"));
0191: lcSymbolTable.put("unsigned short", stFactory
0192: .primitiveEntry("unsigned short"));
0193: lcSymbolTable.put("unsigned long", stFactory
0194: .primitiveEntry("unsigned long"));
0195: lcSymbolTable.put("unsigned long long", stFactory
0196: .primitiveEntry("unsigned long long"));
0197: lcSymbolTable.put("char", stFactory.primitiveEntry("char"));
0198: lcSymbolTable.put("wchar", stFactory.primitiveEntry("wchar"));
0199: lcSymbolTable.put("float", stFactory.primitiveEntry("float"));
0200: // Support fixed type: lcSymbolTable.put ("fixed", stFactory.primitiveEntry ("fixed"));
0201: lcSymbolTable.put("double", stFactory.primitiveEntry("double"));
0202: lcSymbolTable.put("boolean", stFactory
0203: .primitiveEntry("boolean"));
0204: lcSymbolTable.put("octet", stFactory.primitiveEntry("octet"));
0205: lcSymbolTable.put("any", stFactory.primitiveEntry("any"));
0206: lcSymbolTable.put("object", object);
0207: lcSymbolTable.put("valuebase", valueBase);
0208: } // addPrimEntries
0209:
0210: /**
0211: *
0212: **/
0213: private void specification(ModuleEntry entry) throws IOException {
0214: while (!token.equals(Token.EOF)) {
0215: definition(entry);
0216: addToEmitList(entry);
0217: }
0218: } // specification
0219:
0220: // ModuleEntry is the topLevelModule; add its contained types to the emit list.
0221: /**
0222: *
0223: **/
0224: private void addToEmitList(ModuleEntry entry) {
0225: for (Enumeration e = entry.contained().elements(); e
0226: .hasMoreElements();) {
0227: SymtabEntry emitEntry = (SymtabEntry) e.nextElement();
0228: if (emitEntry.emit()) {
0229: emitList.addElement(emitEntry);
0230:
0231: // <d61919> I think the absence of the following statement was an
0232: // oversight. If module X.Y.Z first appears in an include file, then is
0233: // reopened in the main IDL source, this statement guarantees that X.Y.Z
0234: // definitions within the main IDL source are emitted.
0235: ///---------------------------------------------------------------------
0236: // If any of this module's elements should be emitted, add
0237: // this module to the emit list.
0238: if (emitEntry instanceof ModuleEntry)
0239: checkContained((ModuleEntry) emitEntry);
0240: if (emitEntry instanceof IncludeEntry) {
0241: includes.addElement(emitEntry.name());
0242: includeEntries.addElement(emitEntry);
0243: }
0244: } else
0245: // If any of this module's elements should be emitted, add
0246: // this module to the emit list.
0247: if (emitEntry instanceof ModuleEntry)
0248: checkContained((ModuleEntry) emitEntry);
0249: }
0250: entry.contained().removeAllElements();
0251: } // addToEmitList
0252:
0253: /**
0254: *
0255: **/
0256: private void checkContained(ModuleEntry entry) {
0257: // If any of this module's elements is to be emitted,
0258: // then add the module to the emit list.
0259: for (Enumeration e = entry.contained().elements(); e
0260: .hasMoreElements();) {
0261: SymtabEntry contained = (SymtabEntry) e.nextElement();
0262: if (contained instanceof ModuleEntry)
0263: checkContained((ModuleEntry) contained);
0264: if (contained.emit()) {
0265: if (!emitList.contains(entry))
0266: emitList.addElement(entry);
0267: entry.emit(true);
0268: break;
0269: }
0270: }
0271: } // checkContained
0272:
0273: /**
0274: *
0275: **/
0276: private void definition(ModuleEntry entry) throws IOException {
0277: try {
0278: switch (token.type) {
0279: case Token.Typedef:
0280: case Token.Struct:
0281: case Token.Union:
0282: case Token.Enum:
0283: typeDcl(entry);
0284: break;
0285: case Token.Const:
0286: constDcl(entry);
0287: break;
0288: case Token.Native:
0289: nativeDcl(entry);
0290: break;
0291: case Token.Exception:
0292: exceptDcl(entry);
0293: break;
0294: case Token.Interface:
0295: interfaceProd(entry, InterfaceEntry.NORMAL);
0296: break;
0297: case Token.Local:
0298: match(Token.Local);
0299: if (token.type == Token.Interface)
0300: interfaceProd(entry, InterfaceEntry.LOCAL);
0301: else
0302: throw ParseException.syntaxError(scanner,
0303: new int[] { Token.Interface }, token.type);
0304: break;
0305: case Token.Module:
0306: module(entry);
0307: break;
0308: case Token.Abstract:
0309: match(Token.Abstract);
0310: if (token.type == Token.Interface)
0311: interfaceProd(entry, InterfaceEntry.ABSTRACT);
0312: else if (token.type == Token.Valuetype)
0313: valueProd(entry, true);
0314: else
0315: throw ParseException.syntaxError(scanner,
0316: new int[] { Token.Interface,
0317: Token.Valuetype }, token.type);
0318: break;
0319: case Token.Custom:
0320: case Token.Valuetype:
0321: valueProd(entry, false);
0322: break;
0323: default:
0324: throw ParseException.syntaxError(scanner,
0325: new int[] { Token.Typedef, Token.Struct,
0326: Token.Union, Token.Enum, Token.Const,
0327: Token.Exception, Token.Interface,
0328: Token.Valuetype, Token.Module },
0329: token.type);
0330: }
0331: match(Token.Semicolon);
0332: } catch (ParseException e) {
0333: skipToSemicolon();
0334: }
0335: } // definition
0336:
0337: /**
0338: *
0339: **/
0340: private void module(ModuleEntry entry) throws IOException,
0341: ParseException {
0342: match(Token.Module);
0343: repIDStack.push(((IDLID) repIDStack.peek()).clone());
0344: ModuleEntry newEntry = newModule(entry);
0345: ((IDLID) repIDStack.peek()).appendToName(newEntry.name());
0346: // comment must immediately precede "module" keyword
0347: newEntry.comment(tokenHistory.lookBack(1).comment);
0348: currentModule = newEntry;
0349: match(Token.Identifier);
0350: prep.openScope(newEntry);
0351: match(Token.LeftBrace);
0352: definition(newEntry);
0353: while (!token.equals(Token.EOF)
0354: && !token.equals(Token.RightBrace))
0355: definition(newEntry);
0356: prep.closeScope(newEntry);
0357: match(Token.RightBrace);
0358: currentModule = entry;
0359: repIDStack.pop();
0360: } // module
0361:
0362: /**
0363: *
0364: **/
0365: private void interfaceProd(ModuleEntry entry, int interfaceType)
0366: throws IOException, ParseException {
0367: match(Token.Interface);
0368: String name = token.name;
0369: match(Token.Identifier);
0370: interface2(entry, name, interfaceType);
0371: } // interfaceProd
0372:
0373: /**
0374: *
0375: **/
0376: private void interface2(ModuleEntry module, String name,
0377: int interfaceType) throws IOException, ParseException {
0378: if (token.type == Token.Colon || token.type == Token.LeftBrace) {
0379: repIDStack.push(((IDLID) repIDStack.peek()).clone());
0380: InterfaceEntry entry = stFactory.interfaceEntry(module,
0381: (IDLID) repIDStack.peek());
0382: entry.sourceFile(scanner.fileEntry());
0383: entry.name(name);
0384: entry.setInterfaceType(interfaceType);
0385: // Comment must immediately precede "[local | abstract] interface" keyword
0386: entry.comment(tokenHistory.lookBack(entry
0387: .getInterfaceType() == InterfaceEntry.NORMAL ? 2
0388: : 3).comment);
0389:
0390: if (!ForwardEntry.replaceForwardDecl(entry))
0391: ParseException.badAbstract(scanner, entry.fullName());
0392: pigeonhole(module, entry);
0393: ((IDLID) repIDStack.peek()).appendToName(name);
0394: currentModule = entry;
0395: interfaceDcl(entry);
0396: currentModule = module;
0397: repIDStack.pop();
0398: } else { // This is a forward declaration
0399: ForwardEntry entry = stFactory.forwardEntry(module,
0400: (IDLID) repIDStack.peek());
0401: entry.sourceFile(scanner.fileEntry());
0402: entry.name(name);
0403: entry.setInterfaceType(interfaceType);
0404: // comment must immediately precede "interface" keyword.
0405: entry.comment(tokenHistory.lookBack(entry
0406: .getInterfaceType() == InterfaceEntry.NORMAL ? 2
0407: : 3).comment);
0408: pigeonhole(module, entry);
0409: }
0410: } // interface2
0411:
0412: /**
0413: *
0414: **/
0415: private void interfaceDcl(InterfaceEntry entry) throws IOException,
0416: ParseException {
0417: if (token.type != Token.LeftBrace)
0418: inheritanceSpec(entry);
0419: else if (!entry.isAbstract()) {
0420: SymtabEntry objectEntry = qualifiedEntry("Object");
0421: SymtabEntry realOEntry = typeOf(objectEntry);
0422: if (objectEntry == null)
0423: ; // qualifiedEntry already generated an error message
0424: else if (!isInterface(realOEntry))
0425: ParseException.wrongType(scanner,
0426: overrideName("Object"), "interface",
0427: objectEntry.typeName());
0428: else
0429: entry.derivedFromAddElement(realOEntry, scanner);
0430: }
0431:
0432: prep.openScope(entry);
0433: match(Token.LeftBrace);
0434: while (token.type != Token.RightBrace)
0435: export(entry);
0436: prep.closeScope(entry);
0437: match(Token.RightBrace);
0438: } // interfaceDcl
0439:
0440: /**
0441: *
0442: **/
0443: private void export(InterfaceEntry entry) throws IOException {
0444: try {
0445: switch (token.type) {
0446: case Token.Typedef:
0447: case Token.Struct:
0448: case Token.Union:
0449: case Token.Enum:
0450: typeDcl(entry);
0451: break;
0452: case Token.Const:
0453: constDcl(entry);
0454: break;
0455: case Token.Native:
0456: nativeDcl(entry);
0457: break;
0458: case Token.Exception:
0459: exceptDcl(entry);
0460: break;
0461: case Token.Readonly:
0462: case Token.Attribute:
0463: attrDcl(entry);
0464: break;
0465: case Token.Oneway:
0466: case Token.Float:
0467: case Token.Double:
0468: case Token.Long:
0469: case Token.Short:
0470: case Token.Unsigned:
0471: case Token.Char:
0472: case Token.Wchar:
0473: case Token.Boolean:
0474: case Token.Octet:
0475: case Token.Any:
0476: case Token.String:
0477: case Token.Wstring:
0478: case Token.Identifier:
0479: case Token.Object:
0480: // <f46082.40> Value base type.
0481: case Token.ValueBase:
0482: case Token.DoubleColon:
0483: case Token.Void:
0484: opDcl(entry);
0485: break;
0486: // <f46082.51> Remove -stateful feature.
0487: //case Token.State: if (parseStateful) {
0488: // stateDef (entry);
0489: // break; }
0490: default:
0491: throw ParseException.syntaxError(scanner, new int[] {
0492: Token.Typedef, Token.Struct, Token.Union,
0493: Token.Enum, Token.Const, Token.Exception,
0494: Token.Readonly, Token.Attribute, Token.Oneway,
0495: Token.Float, Token.Double, Token.Long,
0496: Token.Short, Token.Unsigned, Token.Char,
0497: Token.Wchar, Token.Boolean, Token.Octet,
0498: Token.Any, Token.String, Token.Wstring,
0499: Token.Identifier, Token.DoubleColon,
0500: Token.Void, Token.ValueBase }, token.type);
0501: }
0502: match(Token.Semicolon);
0503: } catch (ParseException exception) {
0504: skipToSemicolon();
0505: }
0506: } // export
0507:
0508: private void inheritanceSpec(InterfaceEntry entry)
0509: throws IOException, ParseException {
0510: for (match(Token.Colon);; match(Token.Comma)) {
0511: SymtabEntry parent = scopedName(entry.container(),
0512: stFactory.interfaceEntry());
0513: SymtabEntry realParent = typeOf(parent);
0514:
0515: if (isInterfaceOnly(realParent)) {
0516: boolean isInterface = (realParent instanceof InterfaceEntry);
0517: if (entry.derivedFrom().contains(realParent))
0518: ParseException.alreadyDerived(scanner, realParent
0519: .fullName(), entry.fullName());
0520: else if (!entry.isAbstract()
0521: || (((InterfaceType) realParent)
0522: .getInterfaceType() == InterfaceType.ABSTRACT))
0523: entry.derivedFromAddElement(realParent, scanner);
0524: else
0525: ParseException.nonAbstractParent(scanner, entry
0526: .fullName(), parent.fullName());
0527: } else if (isForward(realParent)) {
0528: ParseException.illegalForwardInheritance(scanner, entry
0529: .fullName(), parent.fullName());
0530: } else
0531: ParseException.wrongType(scanner, parent.fullName(),
0532: "interface", entryName(parent));
0533:
0534: if ((parent instanceof InterfaceEntry)
0535: && (((InterfaceEntry) parent).state() != null))
0536: if (entry.state() == null)
0537: entry.initState();
0538: else
0539: throw ParseException.badState(scanner, entry
0540: .fullName());
0541:
0542: if (token.type != Token.Comma)
0543: break;
0544: }
0545: } // inheritanceSpec
0546:
0547: // <57110> Member _moduleIsLegalType may be set by any feature to allow
0548: // method scopedName() and any of its helper methods -- qualifiedName(),
0549: // partlyQualifiedName(), and unqualifiedName() -- to return a ModuleEntry
0550: // rather than a parse error in the event a name resolves to a module. The
0551: // flag must be cleared (set to false) to resume normal parsing behavior.
0552: //
0553: // Currently, this is used only when preprocessing the ID pragma directive.
0554:
0555: private boolean _isModuleLegalType = false;
0556:
0557: /**
0558: *
0559: **/
0560: public boolean isModuleLegalType() {
0561: return _isModuleLegalType;
0562: }; // moduleIsLegaType
0563:
0564: /**
0565: *
0566: **/
0567: public void isModuleLegalType(boolean b) {
0568: _isModuleLegalType = b;
0569: }; // moduleIsLegalType
0570:
0571: /**
0572: *
0573: **/
0574: SymtabEntry scopedName(SymtabEntry container, SymtabEntry expected)
0575: throws IOException, ParseException {
0576: return scopedName(container, expected, true);
0577: }
0578:
0579: SymtabEntry scopedName(SymtabEntry container, SymtabEntry expected,
0580: boolean mustBeReferencable) throws IOException,
0581: ParseException {
0582: boolean globalScope = false;
0583: boolean partialScope = false;
0584: String name = null;
0585: if (token.type == Token.DoubleColon)
0586: globalScope = true;
0587: else {
0588: if (token.type == Token.Object) {
0589: name = "Object";
0590: match(Token.Object);
0591: } else if (token.type == Token.ValueBase) // <f46082.40>
0592: {
0593: name = "ValueBase";
0594: match(Token.ValueBase);
0595: } else {
0596: name = token.name;
0597: match(Token.Identifier);
0598: }
0599: }
0600: while (token.type == Token.DoubleColon) {
0601: match(Token.DoubleColon);
0602: partialScope = true;
0603: if (name != null)
0604: name += '/' + token.name;
0605: else
0606: name = token.name;
0607: match(Token.Identifier);
0608: }
0609: SymtabEntry entry = null;
0610: if (globalScope)
0611: entry = qualifiedEntry(name);
0612: else if (partialScope)
0613: entry = partlyQualifiedEntry(name, container);
0614: else
0615: entry = unqualifiedEntry(name, container);
0616:
0617: if (entry == null)
0618: // Make the entry the expected entry. The generators will
0619: // not be called now, since a semantic exception ocurred, but
0620: // the parse has to finish and something valid has to be
0621: // returned.
0622: (entry = expected).name(name);
0623: else if (!entry.isReferencable() && mustBeReferencable)
0624: throw ParseException.illegalIncompleteTypeReference(
0625: scanner, name);
0626:
0627: return entry;
0628: } // scopedName
0629:
0630: private void valueProd(ModuleEntry entry, boolean isAbstract)
0631: throws IOException, ParseException {
0632: boolean isCustom = (token.type == Token.Custom);
0633: if (isCustom)
0634: match(Token.Custom);
0635: match(Token.Valuetype);
0636: String name = token.name;
0637: match(Token.Identifier);
0638:
0639: switch (token.type) {
0640: case Token.LeftBrace:
0641: case Token.Colon:
0642: case Token.Supports:
0643: value2(entry, name, isAbstract, isCustom);
0644: return;
0645: case Token.Semicolon:
0646: if (isCustom)
0647: break;
0648: valueForwardDcl(entry, name, isAbstract);
0649: return;
0650: }
0651: if (isCustom)
0652: throw ParseException.badCustom(scanner);
0653: if (isAbstract)
0654: throw ParseException.abstractValueBox(scanner);
0655: valueBox(entry, name);
0656: } // valueProd
0657:
0658: /**
0659: *
0660: **/
0661: private void value2(ModuleEntry module, String name,
0662: boolean isAbstract, boolean isCustom) throws IOException,
0663: ParseException {
0664: repIDStack.push(((IDLID) repIDStack.peek()).clone());
0665: // The 'actual' repository ID will be calculated at the end of the
0666: // parsing phase, since it is based on the entire contents of the
0667: // declaration, and needs to have all forward references resolved:
0668: ValueEntry entry = stFactory.valueEntry(module,
0669: (IDLID) repIDStack.peek());
0670: entry.sourceFile(scanner.fileEntry());
0671: entry.name(name);
0672: entry.setInterfaceType(isAbstract ? InterfaceType.ABSTRACT
0673: : InterfaceType.NORMAL);
0674: entry.setCustom(isCustom);
0675: // Comment must immediately precede "[abstract | custom] value" keyword
0676: entry.comment(tokenHistory
0677: .lookBack((isAbstract || isCustom) ? 3 : 2).comment);
0678: // If this value has been forward declared, there are probably
0679: // other values which derive from a ForwardValueEntry. Replace
0680: // those ForwardValueEntry's with this ValueEntry:
0681: if (!ForwardEntry.replaceForwardDecl(entry))
0682: ParseException.badAbstract(scanner, entry.fullName());
0683: pigeonhole(module, entry);
0684: ((IDLID) repIDStack.peek()).appendToName(name);
0685: currentModule = entry;
0686: valueDcl(entry);
0687: entry.tagMethods();
0688: currentModule = module;
0689: repIDStack.pop();
0690: } // value2
0691:
0692: /**
0693: *
0694: **/
0695: private void valueDcl(ValueEntry entry) throws IOException,
0696: ParseException {
0697: if (token.type == Token.Colon)
0698: valueInheritanceSpec(entry);
0699: else if (!entry.isAbstract()) {
0700: SymtabEntry objectEntry = qualifiedEntry("ValueBase");
0701: SymtabEntry realOEntry = typeOf(objectEntry);
0702: if (objectEntry == null)
0703: ; // qualifiedEntry already generated an error message
0704: else if (!isValue(realOEntry))
0705: ParseException.wrongType(scanner,
0706: overrideName("ValueBase"), "value", objectEntry
0707: .typeName());
0708: else
0709: entry.derivedFromAddElement(realOEntry, false, scanner);
0710: }
0711: if (token.type == Token.Supports)
0712: valueSupportsSpec(entry);
0713: prep.openScope(entry);
0714: match(Token.LeftBrace);
0715: while (token.type != Token.RightBrace) {
0716: valueElement(entry);
0717: }
0718: prep.closeScope(entry);
0719: match(Token.RightBrace);
0720: } // valueDcl
0721:
0722: /**
0723: *
0724: **/
0725: private void valueInheritanceSpec(ValueEntry entry)
0726: throws IOException, ParseException {
0727: match(Token.Colon);
0728: boolean isTruncatable = (token.type == Token.Truncatable);
0729: if (isTruncatable)
0730: match(Token.Truncatable);
0731: for (;; match(Token.Comma), isTruncatable = false) {
0732: SymtabEntry parent = scopedName(entry.container(),
0733: stFactory.valueEntry());
0734: SymtabEntry realParent = typeOf(parent);
0735: if (isValue(realParent)
0736: && !(realParent instanceof ValueBoxEntry))
0737: entry.derivedFromAddElement(realParent, isTruncatable,
0738: scanner);
0739: else if (isForward(realParent))
0740: ParseException.illegalForwardInheritance(scanner, entry
0741: .fullName(), parent.fullName());
0742: else
0743: ParseException.wrongType(scanner, parent.fullName(),
0744: "value", entryName(parent));
0745: if (token.type != Token.Comma)
0746: break;
0747: }
0748: } // valueInheritanceSpec
0749:
0750: /**
0751: *
0752: **/
0753: private void valueSupportsSpec(ValueEntry entry)
0754: throws IOException, ParseException {
0755: match(Token.Supports);
0756: for (;; match(Token.Comma)) {
0757: SymtabEntry parent = scopedName(entry.container(),
0758: stFactory.interfaceEntry());
0759: SymtabEntry realParent = typeOf(parent);
0760: if (isInterface(realParent))
0761: entry.derivedFromAddElement(realParent, scanner);
0762: else
0763: ParseException.wrongType(scanner, parent.fullName(),
0764: "interface", entryName(parent));
0765:
0766: if (token.type != Token.Comma)
0767: break;
0768: }
0769: } // valueSupportsSpec
0770:
0771: private void valueElement(ValueEntry entry) throws IOException,
0772: ParseException {
0773: if (entry.isAbstract())
0774: export(entry);
0775: else
0776: switch (token.type) {
0777: case Token.Private:
0778: case Token.Public:
0779: valueStateMember(entry);
0780: break;
0781: case Token.Init:
0782: case Token.Factory: // <d62023> "factory" supplants "init" in 2.4RTF
0783: initDcl(entry);
0784: break;
0785: case Token.Typedef:
0786: case Token.Struct:
0787: case Token.Union:
0788: case Token.Enum:
0789: case Token.Const:
0790: case Token.Native:
0791: case Token.Exception:
0792: case Token.Readonly:
0793: case Token.Attribute:
0794: case Token.Oneway:
0795: case Token.Float:
0796: case Token.Double:
0797: case Token.Long:
0798: case Token.Short:
0799: case Token.Unsigned:
0800: case Token.Char:
0801: case Token.Wchar:
0802: case Token.Boolean:
0803: case Token.Octet:
0804: case Token.Any:
0805: case Token.String:
0806: case Token.Wstring:
0807: case Token.Identifier:
0808: case Token.Object:
0809: case Token.ValueBase:
0810: case Token.DoubleColon:
0811: case Token.Void:
0812: export(entry);
0813: break;
0814: default:
0815: throw ParseException.syntaxError(scanner, new int[] {
0816: Token.Private, Token.Public, Token.Init,
0817: Token.ValueBase, Token.Typedef, Token.Struct,
0818: Token.Union, Token.Enum, Token.Const,
0819: Token.Exception, Token.Readonly,
0820: Token.Attribute, Token.Oneway, Token.Float,
0821: Token.Double, Token.Long, Token.Short,
0822: Token.Unsigned, Token.Char, Token.Wchar,
0823: Token.Boolean, Token.Octet, Token.Any,
0824: Token.String, Token.Wstring, Token.Identifier,
0825: Token.DoubleColon, Token.Void }, token.type);
0826: } // switch
0827: } // valueElement
0828:
0829: // <f46082.40>
0830: /**
0831: *
0832: **/
0833: private void valueStateMember(ValueEntry entry) throws IOException,
0834: ParseException {
0835: TypedefEntry typedefEntry = stFactory.typedefEntry(entry,
0836: (IDLID) repIDStack.peek());
0837: typedefEntry.sourceFile(scanner.fileEntry());
0838: // comment must immediately precede "public", "private" keywords
0839: typedefEntry.comment(token.comment);
0840: boolean isPublic = (token.type == Token.Public);
0841: if (isPublic)
0842: match(Token.Public);
0843: else
0844: match(Token.Private);
0845: // <f46082.40> Add constructed types declared "inline" to the contained
0846: // vector of this value entry.
0847: boolean isConstTypeSpec = (token.type == Token.Struct
0848: || token.type == Token.Union || token.type == Token.Enum);
0849: // <f46082.40> Make typedefEntry anonymous. If this line is removed,
0850: // the entry will be named incorrectly. See <d50618>.
0851: typedefEntry.name("");
0852: typedefEntry.type(typeSpec(typedefEntry));
0853: addDeclarators(entry, typedefEntry, isPublic);
0854: // <f46082.40>
0855: if (isConstTypeSpec)
0856: entry.addContained(typedefEntry);
0857: match(Token.Semicolon);
0858: } // valueStateMember
0859:
0860: private void addDeclarators(ValueEntry entry,
0861: TypedefEntry typedefEntry, boolean isPublic)
0862: throws IOException, ParseException {
0863: int modifier = isPublic ? InterfaceState.Public
0864: : InterfaceState.Private;
0865: try {
0866: Vector typedefList = new Vector();
0867: declarators(typedefEntry, typedefList);
0868: for (Enumeration e = typedefList.elements(); e
0869: .hasMoreElements();)
0870: entry.addStateElement(new InterfaceState(modifier,
0871: (TypedefEntry) e.nextElement()), scanner);
0872: } catch (ParseException exception) {
0873: skipToSemicolon();
0874: }
0875: } // addDeclarators
0876:
0877: /**
0878: *
0879: **/
0880: private void initDcl(ValueEntry entry) throws IOException,
0881: ParseException {
0882: MethodEntry method = stFactory.methodEntry(entry,
0883: (IDLID) repIDStack.peek());
0884: method.sourceFile(scanner.fileEntry());
0885: // Comment must immediately precede "init" keyword:
0886: method.comment(token.comment);
0887: repIDStack.push(((IDLID) repIDStack.peek()).clone());
0888: ((IDLID) repIDStack.peek()).appendToName(token.name);
0889:
0890: // <d62023> In 2.3 prelim, <init_dcl> ::= "init" "(" ...
0891: if (token.type == Token.Init) {
0892: method.name("init");
0893: match(Token.Init);
0894: match(Token.LeftParen);
0895: } else // <d62023> In 2.4rtf, <init_dcl> ::= "factory" <Indentifier> "(" ...
0896: {
0897: match(Token.Factory);
0898: method.name(token.name);
0899: if (token.type == Token.MacroIdentifier)
0900: match(Token.MacroIdentifier); // "(" already consumed.
0901: else {
0902: match(Token.Identifier);
0903: match(Token.LeftParen);
0904: }
0905: }
0906:
0907: if (token.type != Token.RightParen)
0908: for (;;) {
0909: initParamDcl(method);
0910: if (token.type == Token.RightParen)
0911: break;
0912: match(Token.Comma);
0913: }
0914: entry.initializersAddElement(method, scanner);
0915: match(Token.RightParen);
0916: match(Token.Semicolon);
0917: repIDStack.pop();
0918: } // initDcl
0919:
0920: /**
0921: *
0922: **/
0923: private void initParamDcl(MethodEntry entry) throws IOException,
0924: ParseException {
0925: ParameterEntry parmEntry = stFactory.parameterEntry(entry,
0926: (IDLID) repIDStack.peek());
0927: parmEntry.sourceFile(scanner.fileEntry());
0928: // Comment must immediately precede parameter attribute
0929: parmEntry.comment(token.comment);
0930: match(Token.In);
0931: parmEntry.passType(ParameterEntry.In);
0932: parmEntry.type(paramTypeSpec(entry));
0933: parmEntry.name(token.name);
0934: match(Token.Identifier);
0935: if (isntInList(entry.parameters(), parmEntry.name()))
0936: entry.addParameter(parmEntry);
0937: } // initParamDcl
0938:
0939: /**
0940: *
0941: **/
0942: private void valueBox(ModuleEntry module, String name)
0943: throws IOException, ParseException {
0944: repIDStack.push(((IDLID) repIDStack.peek()).clone());
0945: // Note: The 'actual' repository ID will be calculated at the end of
0946: // the parsing phase, since it is based on the entire contents of the
0947: // declaration, and needs to have all forward references resolved:
0948: ValueEntry entry = stFactory.valueBoxEntry(module,
0949: (IDLID) repIDStack.peek());
0950: entry.sourceFile(scanner.fileEntry());
0951: entry.name(name);
0952: // comment must immediately precede "value" keyword
0953: entry.comment(tokenHistory.lookBack(2).comment);
0954: // <f46082.40> Value boxes may not be forwarded.
0955: // If this value has been forward declared, there are probably
0956: // other values which derive from a ForwardValueEntry.
0957: // Replace those ForwardValueEntry's with this ValueEntry:
0958: //if (!ForwardValueEntry.replaceForwardDecl (entry))
0959: // ParseException.badAbstract (scanner, entry.fullName());
0960: SymtabEntry valueForward = (SymtabEntry) Parser.symbolTable
0961: .get(entry.fullName());
0962: if (valueForward != null
0963: && valueForward instanceof ForwardEntry)
0964: ParseException.forwardedValueBox(scanner, entry.fullName());
0965: pigeonhole(module, entry);
0966: ((IDLID) repIDStack.peek()).appendToName(name);
0967: currentModule = entry;
0968: TypedefEntry typedefEntry = stFactory.typedefEntry(entry,
0969: (IDLID) repIDStack.peek());
0970: typedefEntry.sourceFile(scanner.fileEntry());
0971: typedefEntry.comment(token.comment);
0972: // <d50237> Workaround to place typedefEntry in the _contained vector of
0973: // this value box entry ONLY when <type_spec> is a constructed type declared
0974: // at this point (i.e., not an identifier that resolves to a constructed
0975: // type), so that emitters may generate bindings for it. <daz>
0976: boolean isConstTypeSpec = token.type == Token.Struct
0977: || token.type == Token.Union
0978: || token.type == Token.Enum;
0979: // <d50618> Make typedefEntry anonymous. If this line is removed, the
0980: // entry will be named incorrectly.
0981: typedefEntry.name("");
0982: typedefEntry.type(typeSpec(typedefEntry));
0983: // <d59067> Value boxes cannot be nested.
0984: if (typedefEntry.type() instanceof ValueBoxEntry)
0985: ParseException.nestedValueBox(scanner);
0986: //typedefEntry.name ("");
0987: entry.addStateElement(new InterfaceState(InterfaceState.Public,
0988: typedefEntry), scanner);
0989: if (isConstTypeSpec)
0990: entry.addContained(typedefEntry);
0991: currentModule = module;
0992: repIDStack.pop();
0993: } // valueBox
0994:
0995: /**
0996: *
0997: **/
0998: private void valueForwardDcl(ModuleEntry module, String name,
0999: boolean isAbstract) throws IOException, ParseException {
1000: ForwardValueEntry entry = stFactory.forwardValueEntry(module,
1001: (IDLID) repIDStack.peek());
1002: entry.sourceFile(scanner.fileEntry());
1003: entry.name(name);
1004: entry.setInterfaceType(isAbstract ? InterfaceType.ABSTRACT
1005: : InterfaceType.NORMAL);
1006: // Comment must immediately precede "[abstract] value" keyword[s]
1007: entry
1008: .comment(tokenHistory.lookBack(isAbstract ? 3 : 2).comment);
1009: pigeonhole(module, entry);
1010: } // valueForwardDcl
1011:
1012: private void nativeDcl(SymtabEntry entry) throws IOException,
1013: ParseException {
1014: match(Token.Native);
1015: NativeEntry nativeEntry = stFactory.nativeEntry(entry,
1016: (IDLID) repIDStack.peek());
1017: nativeEntry.sourceFile(scanner.fileEntry());
1018: // Comment must immediately precede "native" keyword
1019: nativeEntry.comment(tokenHistory.lookBack(1).comment);
1020: nativeEntry.name(token.name);
1021: match(Token.Identifier);
1022: pigeonhole(entry, nativeEntry);
1023: } // nativeDcl
1024:
1025: /**
1026: *
1027: **/
1028: private void constDcl(SymtabEntry entry) throws IOException,
1029: ParseException {
1030: match(Token.Const);
1031: ConstEntry constEntry = stFactory.constEntry(entry,
1032: (IDLID) repIDStack.peek());
1033: constEntry.sourceFile(scanner.fileEntry());
1034: // Comment must immediately precede "const" keyword
1035: constEntry.comment(tokenHistory.lookBack(1).comment);
1036: constType(constEntry);
1037: constEntry.name(token.name);
1038: match(Token.Identifier);
1039: match(Token.Equal);
1040: constEntry.value(constExp(constEntry));
1041: verifyConstType(constEntry.value(), typeOf(constEntry.type()));
1042: pigeonhole(entry, constEntry);
1043: } // constDcl
1044:
1045: /**
1046: *
1047: **/
1048: private void constType(SymtabEntry entry) throws IOException,
1049: ParseException {
1050: switch (token.type) {
1051: case Token.Octet:
1052: entry.type(octetType());
1053: break;
1054: case Token.Long:
1055: case Token.Short:
1056: case Token.Unsigned:
1057: entry.type(integerType(entry));
1058: break;
1059: case Token.Char:
1060: case Token.Wchar:
1061: entry.type(charType());
1062: break;
1063: case Token.Boolean:
1064: entry.type(booleanType());
1065: break;
1066: case Token.Float:
1067: case Token.Double:
1068: entry.type(floatingPtType());
1069: break;
1070: case Token.String:
1071: case Token.Wstring:
1072: entry.type(stringType(entry));
1073: break;
1074: case Token.Identifier:
1075: case Token.DoubleColon:
1076: entry.type(scopedName(entry.container(), stFactory
1077: .primitiveEntry()));
1078: if (hasArrayInfo(entry.type()))
1079: ParseException.illegalArray(scanner, "const");
1080: SymtabEntry entryType = typeOf(entry.type());
1081: if (!((entryType instanceof PrimitiveEntry) || (entryType instanceof StringEntry))) {
1082: ParseException.wrongType(scanner, entry.fullName(),
1083: "primitive or string", entryName(entry.type()));
1084: entry.type(qualifiedEntry("long"));
1085: } else if (entryType instanceof PrimitiveEntry) {
1086: String any = overrideName("any");
1087: if (entryType.name().equals(any)) {
1088: ParseException.wrongType(scanner, entry.fullName(),
1089: "primitive or string (except " + any + ')',
1090: any);
1091: entry.type(qualifiedEntry("long"));
1092: }
1093: }
1094: break;
1095: default:
1096: throw ParseException.syntaxError(scanner,
1097: new int[] { Token.Long, Token.Short,
1098: Token.Unsigned, Token.Char, Token.Wchar,
1099: Token.Boolean, Token.Float, Token.Double,
1100: Token.String, Token.Wstring,
1101: Token.Identifier, Token.DoubleColon },
1102: token.type);
1103: }
1104: } // constType
1105:
1106: /**
1107: *
1108: **/
1109: private boolean hasArrayInfo(SymtabEntry entry) {
1110: while (entry instanceof TypedefEntry) {
1111: if (((TypedefEntry) entry).arrayInfo().size() != 0)
1112: return true;
1113: entry = entry.type();
1114: }
1115: return false;
1116: } // hasArrayInfo
1117:
1118: /**
1119: *
1120: **/
1121: public static String overrideName(String string) {
1122: String name = (String) overrideNames.get(string);
1123: return (name == null) ? string : name;
1124: } // overrideName
1125:
1126: // If entry is boolean, expression value must be boolean
1127: // If entry is float/double, expression value must be float/double
1128: // If entry is integral, expression value must be integral
1129: // If entry is string, expression value must be string
1130:
1131: /**
1132: *
1133: **/
1134: private void verifyConstType(Expression e, SymtabEntry t) {
1135: Object value = e.value();
1136: if (value instanceof BigInteger)
1137: verifyIntegral((Number) value, t);
1138: else if (value instanceof String)
1139: verifyString(e, t);
1140: else if (value instanceof Boolean)
1141: verifyBoolean(t);
1142: else if (value instanceof Character)
1143: verifyCharacter(e, t);
1144: else if (value instanceof Float || value instanceof Double)
1145: verifyFloat((Number) value, t);
1146: else if (value instanceof ConstEntry)
1147: verifyConstType(((ConstEntry) value).value(), t);
1148: else
1149: ParseException.wrongExprType(scanner, t.fullName(),
1150: (value == null) ? "" : value.toString());
1151: } // verifyConstType
1152:
1153: private static final int MAX_SHORT = 32767;
1154: private static final int MIN_SHORT = -32768;
1155: private static final int MAX_USHORT = 65535;
1156:
1157: /**
1158: *
1159: **/
1160: private void verifyIntegral(Number n, SymtabEntry t) {
1161: boolean outOfRange = false;
1162: //KEEP: Useful for debugging com.sun.tools.corba.se.idl.constExpr package
1163: //System.out.println ("verifyIntegral, n = " + n.toString ());
1164:
1165: if (t == qualifiedEntry("octet")) {
1166: if ((n.longValue() > 255) || (n.longValue() < 0))
1167: outOfRange = true;
1168: } else if (t == qualifiedEntry("long")) {
1169: if (n.longValue() > Integer.MAX_VALUE
1170: || n.longValue() < Integer.MIN_VALUE)
1171: outOfRange = true;
1172: } else if (t == qualifiedEntry("short")) {
1173: if (n.intValue() > Short.MAX_VALUE
1174: || n.intValue() < Short.MIN_VALUE)
1175: outOfRange = true;
1176: } else if (t == qualifiedEntry("unsigned long")) {
1177: if (n.longValue() > (long) Integer.MAX_VALUE * 2 + 1
1178: || n.longValue() < 0)
1179: outOfRange = true;
1180: } else if (t == qualifiedEntry("unsigned short")) {
1181: if (n.intValue() > (int) Short.MAX_VALUE * 2 + 1
1182: || n.intValue() < 0)
1183: outOfRange = true;
1184: } else if (t == qualifiedEntry("long long")) {
1185: // BigInteger required because value being compared may exceed
1186: // java.lang.Long.MAX_VALUE/MIN_VALUE:
1187: BigInteger llMax = BigInteger.valueOf(Long.MAX_VALUE);
1188: BigInteger llMin = BigInteger.valueOf(Long.MIN_VALUE);
1189: if (((BigInteger) n).compareTo(llMax) > 0
1190: || ((BigInteger) n).compareTo(llMin) < 0)
1191: outOfRange = true;
1192: } else if (t == qualifiedEntry("unsigned long long")) {
1193: BigInteger ullMax = BigInteger.valueOf(Long.MAX_VALUE)
1194: .multiply(BigInteger.valueOf(2)).add(
1195: BigInteger.valueOf(1));
1196: BigInteger ullMin = BigInteger.valueOf(0);
1197: if (((BigInteger) n).compareTo(ullMax) > 0
1198: || ((BigInteger) n).compareTo(ullMin) < 0)
1199: outOfRange = true;
1200: } else {
1201: String got = null;
1202: // THIS MUST BE CHANGED; BIGINTEGER IS ALWAYS THE CONTAINER
1203: /*
1204: if (n instanceof Short)
1205: got = "short";
1206: else if (n instanceof Integer)
1207: got = "long";
1208: else
1209: got = "long long";
1210: */
1211: got = "long";
1212: ParseException.wrongExprType(scanner, t.fullName(), got);
1213: }
1214:
1215: if (outOfRange)
1216: ParseException.outOfRange(scanner, n.toString(), t
1217: .fullName());
1218: } // verifyIntegral
1219:
1220: /**
1221: *
1222: **/
1223: private void verifyString(Expression e, SymtabEntry t) {
1224: String string = (String) (e.value());
1225: if (!(t instanceof StringEntry)) {
1226: ParseException.wrongExprType(scanner, t.fullName(), e
1227: .type());
1228: } else if (((StringEntry) t).maxSize() != null) {
1229: Expression maxExp = ((StringEntry) t).maxSize();
1230: try {
1231: Number max = (Number) maxExp.value();
1232: if (string.length() > max.intValue())
1233: ParseException.stringTooLong(scanner, string, max
1234: .toString());
1235: } catch (Exception exception) {
1236: // If the above statement is not valid and throws an
1237: // exception, then an error occurred and was reported
1238: // earlier. Move on.
1239: }
1240: }
1241:
1242: if (!e.type().equals(t.name())) {
1243: // cannot mix strings and wide strings
1244: ParseException.wrongExprType(scanner, t.name(), e.type());
1245: }
1246: } // verifyString
1247:
1248: /**
1249: *
1250: **/
1251: private void verifyBoolean(SymtabEntry t) {
1252: if (!t.name().equals(overrideName("boolean")))
1253: ParseException.wrongExprType(scanner, t.name(), "boolean");
1254: } // verifyBoolean
1255:
1256: /**
1257: *
1258: **/
1259: private void verifyCharacter(Expression e, SymtabEntry t) {
1260: // Bug fix 4382578: Can't compile a wchar literal.
1261: // Allow a Character to be either a char or a wchar.
1262: if (!t.name().equals(overrideName("char"))
1263: && !t.name().equals(overrideName("wchar"))
1264: || !t.name().equals(e.type()))
1265: ParseException.wrongExprType(scanner, t.fullName(), e
1266: .type());
1267: } // verifyCharacter
1268:
1269: /**
1270: *
1271: **/
1272: private void verifyFloat(Number f, SymtabEntry t) {
1273: // <d52042> Added range checking for floats.
1274: //if (!(t.name ().equals (overrideName ("float")) ||
1275: // t.name ().equals (overrideName ("double"))))
1276: // ParseException.wrongExprType (scanner,
1277: // t.fullName (), (f instanceof Float) ? "float" : "double");
1278: //KEEP: Useful for debugging com.sun.tools.corba.se.idl.constExpr package
1279: //System.out.println ("verifyFloat, f = " + f.toString ());
1280: boolean outOfRange = false;
1281: if (t.name().equals(overrideName("float"))) {
1282: double absVal = (f.doubleValue() < 0.0) ? f.doubleValue()
1283: * -1.0 : f.doubleValue();
1284: if ((absVal != 0.0)
1285: && (absVal > Float.MAX_VALUE || absVal < Float.MIN_VALUE))
1286: outOfRange = true;
1287: } else if (t.name().equals(overrideName("double"))) {
1288: // Cannot check range of double until BigDecimal is the basis
1289: // of all floating-point types. Currently, it is Double. The
1290: // parser will fail when instantiating a Double with an exception.
1291: } else {
1292: ParseException.wrongExprType(scanner, t.fullName(),
1293: (f instanceof Float) ? "float" : "double");
1294: }
1295: if (outOfRange)
1296: ParseException.outOfRange(scanner, f.toString(), t
1297: .fullName());
1298: } // verifyFloat
1299:
1300: /**
1301: *
1302: **/
1303: Expression constExp(SymtabEntry entry) throws IOException,
1304: ParseException {
1305: // Parse the expression.
1306: Expression expr = orExpr(null, entry);
1307:
1308: // Set its target type.
1309: if (expr.type() == null)
1310: expr.type(entry.typeName());
1311: // Compute its value and <d53042> coerce it to the target type.
1312: try {
1313: expr.evaluate();
1314:
1315: // <d54042> Coerces integral value to Double if an integer literal
1316: // was used to initialize a floating-point constant expression.
1317: if (expr instanceof Terminal
1318: && expr.value() instanceof BigInteger
1319: && (overrideName(expr.type()).equals("float") || overrideName(
1320: expr.type()).indexOf("double") >= 0)) {
1321: expr.value(new Double(((BigInteger) expr.value())
1322: .doubleValue()));
1323: }
1324: } catch (EvaluationException exception) {
1325: ParseException.evaluationError(scanner, exception
1326: .toString());
1327: }
1328: return expr;
1329: } // constExp
1330:
1331: /**
1332: *
1333: **/
1334: private Expression orExpr(Expression e, SymtabEntry entry)
1335: throws IOException, ParseException {
1336: if (e == null)
1337: e = xorExpr(null, entry);
1338: else {
1339: BinaryExpr b = (BinaryExpr) e;
1340: b.right(xorExpr(null, entry));
1341: e.rep(e.rep() + b.right().rep());
1342: }
1343: if (token.equals(Token.Bar)) {
1344: match(token.type);
1345: Or or = exprFactory.or(e, null);
1346: or.type(entry.typeName());
1347: or.rep(e.rep() + " | ");
1348: return orExpr(or, entry);
1349: }
1350: return e;
1351: } // orExpr
1352:
1353: /**
1354: *
1355: **/
1356: private Expression xorExpr(Expression e, SymtabEntry entry)
1357: throws IOException, ParseException {
1358: if (e == null)
1359: e = andExpr(null, entry);
1360: else {
1361: BinaryExpr b = (BinaryExpr) e;
1362: b.right(andExpr(null, entry));
1363: e.rep(e.rep() + b.right().rep());
1364: }
1365: if (token.equals(Token.Carat)) {
1366: match(token.type);
1367: Xor xor = exprFactory.xor(e, null);
1368: xor.rep(e.rep() + " ^ ");
1369: xor.type(entry.typeName());
1370: return xorExpr(xor, entry);
1371: }
1372: return e;
1373: } // xorExpr
1374:
1375: /**
1376: *
1377: **/
1378: private Expression andExpr(Expression e, SymtabEntry entry)
1379: throws IOException, ParseException {
1380: if (e == null)
1381: e = shiftExpr(null, entry);
1382: else {
1383: BinaryExpr b = (BinaryExpr) e;
1384: b.right(shiftExpr(null, entry));
1385: e.rep(e.rep() + b.right().rep());
1386: }
1387: if (token.equals(Token.Ampersand)) {
1388: match(token.type);
1389: And and = exprFactory.and(e, null);
1390: and.rep(e.rep() + " & ");
1391: and.type(entry.typeName());
1392: return andExpr(and, entry);
1393: }
1394: return e;
1395: } // andExpr
1396:
1397: /**
1398: *
1399: **/
1400: private Expression shiftExpr(Expression e, SymtabEntry entry)
1401: throws IOException, ParseException {
1402: if (e == null)
1403: e = addExpr(null, entry);
1404: else {
1405: BinaryExpr b = (BinaryExpr) e;
1406: b.right(addExpr(null, entry));
1407: e.rep(e.rep() + b.right().rep());
1408: }
1409: if (token.equals(Token.ShiftLeft)) {
1410: match(token.type);
1411: ShiftLeft sl = exprFactory.shiftLeft(e, null);
1412: sl.type(entry.typeName());
1413: sl.rep(e.rep() + " << ");
1414: return shiftExpr(sl, entry);
1415: }
1416: if (token.equals(Token.ShiftRight)) {
1417: match(token.type);
1418: ShiftRight sr = exprFactory.shiftRight(e, null);
1419: sr.type(entry.typeName());
1420: sr.rep(e.rep() + " >> ");
1421: return shiftExpr(sr, entry);
1422: }
1423: return e;
1424: } // shiftExpr
1425:
1426: /**
1427: *
1428: **/
1429: private Expression addExpr(Expression e, SymtabEntry entry)
1430: throws IOException, ParseException {
1431: if (e == null)
1432: e = multExpr(null, entry);
1433: else {
1434: BinaryExpr b = (BinaryExpr) e;
1435: b.right(multExpr(null, entry));
1436: e.rep(e.rep() + b.right().rep());
1437: }
1438: if (token.equals(Token.Plus)) {
1439: match(token.type);
1440: Plus p = exprFactory.plus(e, null);
1441: p.type(entry.typeName());
1442: p.rep(e.rep() + " + ");
1443: return addExpr(p, entry);
1444: }
1445: if (token.equals(Token.Minus)) {
1446: match(token.type);
1447: Minus m = exprFactory.minus(e, null);
1448: m.type(entry.typeName());
1449: m.rep(e.rep() + " - ");
1450: return addExpr(m, entry);
1451: }
1452: return e;
1453: } // addExpr
1454:
1455: /**
1456: *
1457: **/
1458: private Expression multExpr(Expression e, SymtabEntry entry)
1459: throws IOException, ParseException {
1460: if (e == null)
1461: e = unaryExpr(entry);
1462: else {
1463: BinaryExpr b = (BinaryExpr) e;
1464: b.right(unaryExpr(entry));
1465: e.rep(e.rep() + b.right().rep());
1466: }
1467: if (token.equals(Token.Star)) {
1468: match(token.type);
1469: Times t = exprFactory.times(e, null);
1470: t.type(entry.typeName());
1471: t.rep(e.rep() + " * ");
1472: return multExpr(t, entry);
1473: }
1474: if (token.equals(Token.Slash)) {
1475: match(token.type);
1476: Divide d = exprFactory.divide(e, null);
1477: d.type(entry.typeName());
1478: d.rep(e.rep() + " / ");
1479: return multExpr(d, entry);
1480: }
1481: if (token.equals(Token.Percent)) {
1482: match(token.type);
1483: Modulo m = exprFactory.modulo(e, null);
1484: m.type(entry.typeName());
1485: m.rep(e.rep() + " % ");
1486: return multExpr(m, entry);
1487: }
1488: return e;
1489: } // multExpr
1490:
1491: /**
1492: *
1493: **/
1494: private Expression unaryExpr(SymtabEntry entry) throws IOException,
1495: ParseException {
1496: if (token.equals(Token.Plus)) {
1497: match(token.type);
1498: Expression e = primaryExpr(entry);
1499: Positive pos = exprFactory.positive(e);
1500: pos.type(entry.typeName());
1501: pos.rep('+' + e.rep());
1502: return pos;
1503: }
1504: if (token.equals(Token.Minus)) {
1505: match(token.type);
1506: Expression e = primaryExpr(entry);
1507: Negative neg = exprFactory.negative(e);
1508: neg.type(entry.typeName());
1509: neg.rep('-' + e.rep());
1510: return neg;
1511: }
1512: if (token.equals(Token.Tilde)) {
1513: match(token.type);
1514: Expression e = primaryExpr(entry);
1515: Not not = exprFactory.not(e);
1516: not.type(entry.typeName());
1517: not.rep('~' + e.rep());
1518: return not;
1519: }
1520: return primaryExpr(entry);
1521: } // unaryExpr
1522:
1523: /**
1524: *
1525: **/
1526: private Expression primaryExpr(SymtabEntry entry)
1527: throws IOException, ParseException {
1528: Expression primary = null;
1529: if (parsingConditionalExpr) {
1530: prep.token = token; // Give current token to preprocessor
1531: primary = prep.primaryExpr(entry);
1532: token = prep.token; // Get the current token from preprocessor
1533: } else
1534: switch (token.type) {
1535: case Token.Identifier:
1536: case Token.DoubleColon:
1537: ConstEntry expectedC = stFactory.constEntry();
1538: expectedC.value(exprFactory.terminal("1", BigInteger
1539: .valueOf(1)));
1540: SymtabEntry ref = scopedName(entry.container(),
1541: expectedC);
1542: if (!(ref instanceof ConstEntry)) {
1543: ParseException
1544: .invalidConst(scanner, ref.fullName());
1545: // An error occurred. Just give it some bogus value. <daz>
1546: //primary = exprFactory.terminal ("1", new Long (1));
1547: primary = exprFactory.terminal("1", BigInteger
1548: .valueOf(1));
1549: } else
1550: primary = exprFactory.terminal((ConstEntry) ref);
1551: break;
1552: case Token.BooleanLiteral:
1553: case Token.CharacterLiteral:
1554: case Token.IntegerLiteral:
1555: case Token.FloatingPointLiteral:
1556: case Token.StringLiteral:
1557: primary = literal(entry);
1558: break;
1559: case Token.LeftParen:
1560: match(Token.LeftParen);
1561: primary = constExp(entry);
1562: match(Token.RightParen);
1563: primary.rep('(' + primary.rep() + ')');
1564: break;
1565: default:
1566: throw ParseException.syntaxError(scanner, new int[] {
1567: Token.Identifier, Token.DoubleColon,
1568: Token.Literal, Token.LeftParen }, token.type);
1569: }
1570: return primary;
1571: } // primaryExpr
1572:
1573: /**
1574: *
1575: **/
1576: Expression literal(SymtabEntry entry) throws IOException,
1577: ParseException {
1578: String string = token.name;
1579: Expression literal = null;
1580: switch (token.type) {
1581: case Token.IntegerLiteral:
1582: match(Token.IntegerLiteral);
1583: try {
1584: literal = exprFactory.terminal(string,
1585: parseString(string));
1586: literal.type(entry.typeName());
1587: } catch (NumberFormatException exception) {
1588: ParseException.notANumber(scanner, string);
1589: literal = exprFactory.terminal("0", BigInteger
1590: .valueOf(0));
1591: }
1592: break;
1593: case Token.CharacterLiteral:
1594: boolean isWide = token.isWide();
1595: match(Token.CharacterLiteral);
1596: literal = exprFactory.terminal("'" + string.substring(1)
1597: + "'", new Character(string.charAt(0)), isWide);
1598: break;
1599: case Token.FloatingPointLiteral:
1600: match(Token.FloatingPointLiteral);
1601: try {
1602: literal = exprFactory.terminal(string, new Double(
1603: string));
1604: literal.type(entry.typeName());
1605: } catch (NumberFormatException e) {
1606: ParseException.notANumber(scanner, string);
1607: }
1608: break;
1609: case Token.BooleanLiteral:
1610: literal = booleanLiteral();
1611: break;
1612: case Token.StringLiteral:
1613: literal = stringLiteral();
1614: break;
1615: default:
1616: throw ParseException.syntaxError(scanner, Token.Literal,
1617: token.type);
1618: }
1619: return literal;
1620: } // literal
1621:
1622: /**
1623: *
1624: **/
1625: private BigInteger parseString(String string)
1626: throws NumberFormatException {
1627: int radix = 10;
1628: if (string.length() > 1)
1629: if (string.charAt(0) == '0')
1630: if (string.charAt(1) == 'x' || string.charAt(1) == 'X') {
1631: string = string.substring(2);
1632: radix = 16;
1633: } else
1634: radix = 8;
1635: return new BigInteger(string, radix);
1636: } // parseString
1637:
1638: /**
1639: *
1640: **/
1641: private Terminal booleanLiteral() throws IOException,
1642: ParseException {
1643: Boolean bool = null;
1644: if (token.name.equals("TRUE"))
1645: bool = new Boolean(true);
1646: else if (token.name.equals("FALSE"))
1647: bool = new Boolean(false);
1648: else {
1649: ParseException.invalidConst(scanner, token.name);
1650: bool = new Boolean(false);
1651: }
1652: String name = token.name;
1653: match(Token.BooleanLiteral);
1654: return exprFactory.terminal(name, bool);
1655: } // booleanLiteral
1656:
1657: /**
1658: *
1659: **/
1660: private Expression stringLiteral() throws IOException,
1661: ParseException {
1662: // If string literals appear together, concatenate them. Ie:
1663: // "Twas " "brillig " "and " "the " "slithy " "toves"
1664: // becomes
1665: // "Twas brillig and the slithy toves"
1666: boolean isWide = token.isWide();
1667: String literal = "";
1668: do {
1669: literal += token.name;
1670: match(Token.StringLiteral);
1671: } while (token.equals(Token.StringLiteral));
1672: Expression stringExpr = exprFactory.terminal(literal, isWide);
1673: stringExpr.rep('"' + literal + '"');
1674: return stringExpr;
1675: } // stringLiteral
1676:
1677: /**
1678: *
1679: **/
1680: private Expression positiveIntConst(SymtabEntry entry)
1681: throws IOException, ParseException {
1682: Expression e = constExp(entry);
1683: Object value = e.value();
1684: while (value instanceof ConstEntry)
1685: value = ((ConstEntry) value).value().value();
1686: if (!(value instanceof Number) || value instanceof Float
1687: || value instanceof Double) {
1688: ParseException.notPositiveInt(scanner, e.rep());
1689: //e = exprFactory.terminal ("1", new Long (1));
1690: e = exprFactory.terminal("1", BigInteger.valueOf(1));
1691: }
1692: //else if (((Number)value).longValue () <= 0) {
1693: // ParseException.notPositiveInt (scanner, value.toString ());
1694: // e = exprFactory.terminal ("1", new Long (1)); }
1695: else if (((BigInteger) value).compareTo(BigInteger.valueOf(0)) <= 0) {
1696: ParseException.notPositiveInt(scanner, value.toString());
1697: //e = exprFactory.terminal ("1", new Long (1)); <daz>
1698: e = exprFactory.terminal("1", BigInteger.valueOf(1));
1699: }
1700: return e;
1701: } // positiveIntConst
1702:
1703: /**
1704: *
1705: **/
1706: private SymtabEntry typeDcl(SymtabEntry entry) throws IOException,
1707: ParseException {
1708: switch (token.type) {
1709: case Token.Typedef:
1710: match(Token.Typedef);
1711: return typeDeclarator(entry);
1712: case Token.Struct:
1713: return structType(entry);
1714: case Token.Union:
1715: return unionType(entry);
1716: case Token.Enum:
1717: return enumType(entry);
1718: default:
1719: throw ParseException.syntaxError(scanner, new int[] {
1720: Token.Typedef, Token.Struct, Token.Union,
1721: Token.Enum }, token.type);
1722: }
1723: } // typeDcl
1724:
1725: /**
1726: *
1727: **/
1728: private TypedefEntry typeDeclarator(SymtabEntry entry)
1729: throws IOException, ParseException {
1730: TypedefEntry typedefEntry = stFactory.typedefEntry(entry,
1731: (IDLID) repIDStack.peek());
1732: typedefEntry.sourceFile(scanner.fileEntry());
1733: // Comment must immediately precede "typedef" keyword
1734: typedefEntry.comment(tokenHistory.lookBack(1).comment);
1735: typedefEntry.type(typeSpec(entry));
1736: Vector typedefList = new Vector();
1737: declarators(typedefEntry, typedefList);
1738: for (Enumeration e = typedefList.elements(); e
1739: .hasMoreElements();)
1740: pigeonhole(entry, (SymtabEntry) e.nextElement());
1741: return typedefEntry;
1742: } // typeDeclarator
1743:
1744: /**
1745: *
1746: **/
1747: private SymtabEntry typeSpec(SymtabEntry entry) throws IOException,
1748: ParseException {
1749: return ((token.type == Token.Struct)
1750: || (token.type == Token.Union) || (token.type == Token.Enum)) ? constrTypeSpec(entry)
1751: : simpleTypeSpec(entry, true);
1752: } // typeSpec
1753:
1754: /**
1755: *
1756: **/
1757: private SymtabEntry simpleTypeSpec(SymtabEntry entry,
1758: boolean mustBeReferencable) throws IOException,
1759: ParseException {
1760: // <f46082.40>
1761: //if ((token.type == Token.Identifier) ||
1762: // (token.type == Token.DoubleColon) ||
1763: // (token.type == Token.Object)) {
1764: if ((token.type == Token.Identifier)
1765: || (token.type == Token.DoubleColon)
1766: || (token.type == Token.Object)
1767: || (token.type == Token.ValueBase)) {
1768: SymtabEntry container = ((entry instanceof InterfaceEntry)
1769: || (entry instanceof ModuleEntry)
1770: || (entry instanceof StructEntry) || (entry instanceof UnionEntry)) ? entry
1771: : entry.container();
1772: return scopedName(container, stFactory.primitiveEntry(),
1773: mustBeReferencable);
1774: }
1775: return ((token.type == Token.Sequence)
1776: || (token.type == Token.String) || (token.type == Token.Wstring)) ? templateTypeSpec(entry)
1777: : baseTypeSpec(entry);
1778: } // simpleTypeSpec
1779:
1780: /**
1781: *
1782: **/
1783: private SymtabEntry baseTypeSpec(SymtabEntry entry)
1784: throws IOException, ParseException {
1785: switch (token.type) {
1786: case Token.Float:
1787: case Token.Double:
1788: return floatingPtType();
1789: case Token.Long:
1790: case Token.Short:
1791: case Token.Unsigned:
1792: return integerType(entry);
1793: case Token.Char:
1794: case Token.Wchar:
1795: return charType();
1796: case Token.Boolean:
1797: return booleanType();
1798: case Token.Octet:
1799: return octetType();
1800: case Token.Any:
1801: return anyType();
1802: // NOTE: Object and ValueBase are <base_type_spec>s, but both
1803: // are processed at simpleTypeSpec(), not here. parmTypeSpec()
1804: // directly checks for these types. Could make baseTypeSpec() do
1805: // the same
1806: default:
1807: throw ParseException
1808: .syntaxError(scanner, new int[] { Token.Float,
1809: Token.Double, Token.Long, Token.Short,
1810: Token.Unsigned, Token.Char, Token.Wchar,
1811: Token.Boolean, Token.Octet, Token.Any },
1812: token.type);
1813: }
1814: } // baseTypeSpec
1815:
1816: /**
1817: *
1818: **/
1819: private SymtabEntry templateTypeSpec(SymtabEntry entry)
1820: throws IOException, ParseException {
1821: switch (token.type) {
1822: case Token.Sequence:
1823: return sequenceType(entry);
1824: case Token.String:
1825: case Token.Wstring:
1826: return stringType(entry);
1827: }
1828: throw ParseException.syntaxError(scanner, new int[] {
1829: Token.Sequence, Token.String, Token.Wstring },
1830: token.type);
1831: } // templateTypeSpec
1832:
1833: /**
1834: *
1835: **/
1836: private SymtabEntry constrTypeSpec(SymtabEntry entry)
1837: throws IOException, ParseException {
1838: switch (token.type) {
1839: case Token.Struct:
1840: return structType(entry);
1841: case Token.Union:
1842: return unionType(entry);
1843: case Token.Enum:
1844: return enumType(entry);
1845: }
1846: throw ParseException.syntaxError(scanner, new int[] {
1847: Token.Struct, Token.Union, Token.Enum }, token.type);
1848: } // constrTypeSpec
1849:
1850: /**
1851: *
1852: **/
1853: private void declarators(TypedefEntry entry, Vector list)
1854: throws IOException, ParseException {
1855: for (;; match(Token.Comma)) {
1856: TypedefEntry newEntry = (TypedefEntry) entry.clone();
1857: declarator(newEntry);
1858: if (isntInList(list, newEntry.name()))
1859: list.addElement(newEntry);
1860: if (token.type != Token.Comma)
1861: break;
1862: }
1863: } // declarators
1864:
1865: /**
1866: *
1867: **/
1868: private void declarator(TypedefEntry entry) throws IOException,
1869: ParseException {
1870: entry.name(token.name);
1871: // If the declarator is commented then override the comment cloned from the parent
1872: // entry. <08aug1997daz>
1873: if (!token.comment.text().equals(""))
1874: entry.comment(token.comment);
1875: match(Token.Identifier);
1876: while (token.type == Token.LeftBracket)
1877: fixedArraySize(entry);
1878: } // declarator
1879:
1880: /**
1881: *
1882: **/
1883: private PrimitiveEntry floatingPtType() throws IOException,
1884: ParseException {
1885: String name = "double";
1886: if (token.type == Token.Float) {
1887: match(Token.Float);
1888: name = "float";
1889: } else if (token.type == Token.Double)
1890: match(Token.Double);
1891: else {
1892: int[] expected = { Token.Float, Token.Double };
1893: ParseException.syntaxError(scanner, new int[] {
1894: Token.Float, Token.Double }, token.type);
1895: }
1896: PrimitiveEntry ret = null;
1897: try {
1898: ret = (PrimitiveEntry) qualifiedEntry(name);
1899: } catch (ClassCastException exception) {
1900: ParseException.undeclaredType(scanner, name);
1901: }
1902: return ret;
1903: } // floatingPtType
1904:
1905: /**
1906: *
1907: **/
1908: private PrimitiveEntry integerType(SymtabEntry entry)
1909: throws IOException, ParseException {
1910: String name = "";
1911: if (token.type == Token.Unsigned) {
1912: match(Token.Unsigned);
1913: name = "unsigned ";
1914: }
1915: name += signedInt();
1916: PrimitiveEntry ret = null;
1917: try {
1918: ret = (PrimitiveEntry) qualifiedEntry(name);
1919: } catch (ClassCastException exception) {
1920: ParseException.undeclaredType(scanner, name);
1921: }
1922: return ret;
1923: } // integerType
1924:
1925: /**
1926: *
1927: **/
1928: private String signedInt() throws IOException, ParseException {
1929: String ret = "long";
1930: if (token.type == Token.Long) {
1931: match(Token.Long);
1932: // <signedInt'> ::= "long" | e
1933: if (token.type == Token.Long) {
1934: ret = "long long";
1935: match(Token.Long);
1936: }
1937: } else if (token.type == Token.Short) {
1938: ret = "short";
1939: match(Token.Short);
1940: } else
1941: ParseException.syntaxError(scanner, new int[] { Token.Long,
1942: Token.Short }, token.type);
1943: return ret;
1944: } // signedInt
1945:
1946: /**
1947: *
1948: **/
1949: private PrimitiveEntry charType() throws IOException,
1950: ParseException {
1951: String tokenName;
1952: if (token.type == Token.Char) {
1953: match(Token.Char);
1954: tokenName = "char";
1955: } else {
1956: match(Token.Wchar);
1957: tokenName = "wchar";
1958: }
1959: PrimitiveEntry ret = null;
1960: try {
1961: ret = (PrimitiveEntry) qualifiedEntry(tokenName);
1962: } catch (ClassCastException exception) {
1963: ParseException.undeclaredType(scanner,
1964: overrideName(tokenName));
1965: }
1966: return ret;
1967: } // charType
1968:
1969: /**
1970: *
1971: **/
1972: private PrimitiveEntry booleanType() throws IOException,
1973: ParseException {
1974: PrimitiveEntry ret = null;
1975: match(Token.Boolean);
1976: try {
1977: ret = (PrimitiveEntry) qualifiedEntry("boolean");
1978: } catch (ClassCastException exception) {
1979: ParseException.undeclaredType(scanner,
1980: overrideName("boolean"));
1981: }
1982: return ret;
1983: } // booleanType
1984:
1985: /**
1986: *
1987: **/
1988: private PrimitiveEntry octetType() throws IOException,
1989: ParseException {
1990: PrimitiveEntry ret = null;
1991: match(Token.Octet);
1992: try {
1993: ret = (PrimitiveEntry) qualifiedEntry("octet");
1994: } catch (ClassCastException exception) {
1995: ParseException.undeclaredType(scanner,
1996: overrideName("octet"));
1997: }
1998: return ret;
1999: } // octetType
2000:
2001: /**
2002: *
2003: **/
2004: private SymtabEntry anyType() throws IOException, ParseException {
2005: match(Token.Any);
2006: try {
2007: return qualifiedEntry("any");
2008: } catch (ClassCastException exception) {
2009: ParseException.undeclaredType(scanner, overrideName("any"));
2010: return null;
2011: }
2012: } // anyType
2013:
2014: /**
2015: *
2016: **/
2017: private StructEntry structType(SymtabEntry entry)
2018: throws IOException, ParseException {
2019: match(Token.Struct);
2020: String name = token.name;
2021: match(Token.Identifier);
2022: StructEntry structEntry = null;
2023:
2024: if (token.type == Token.LeftBrace) {
2025: repIDStack.push(((IDLID) repIDStack.peek()).clone());
2026: ((IDLID) repIDStack.peek()).appendToName(name);
2027: structEntry = makeStructEntry(name, entry, false);
2028: prep.openScope(structEntry);
2029: match(Token.LeftBrace);
2030: member(structEntry);
2031: memberList2(structEntry);
2032: prep.closeScope(structEntry);
2033: match(Token.RightBrace);
2034: repIDStack.pop();
2035: } else if (token.equals(Token.Semicolon)) {
2036: structEntry = makeStructEntry(name, entry, true);
2037: } else {
2038: throw ParseException.syntaxError(scanner, new int[] {
2039: Token.Semicolon, Token.LeftBrace }, token.type);
2040: }
2041: return structEntry;
2042: } // structType
2043:
2044: private StructEntry makeStructEntry(String name, SymtabEntry entry,
2045: boolean isForward) {
2046: StructEntry structEntry = stFactory.structEntry(entry,
2047: (IDLID) repIDStack.peek());
2048: structEntry.isReferencable(!isForward);
2049: structEntry.sourceFile(scanner.fileEntry());
2050: structEntry.name(name);
2051: // Comment must immediately preceed "struct" keyword
2052: structEntry.comment(tokenHistory.lookBack(1).comment);
2053: pigeonhole(entry, structEntry);
2054: return structEntry;
2055: }
2056:
2057: /**
2058: *
2059: **/
2060: private void memberList2(StructEntry entry) throws IOException {
2061: while (token.type != Token.RightBrace)
2062: member(entry);
2063: } // memberList2
2064:
2065: /**
2066: *
2067: **/
2068: private void member(StructEntry entry) throws IOException {
2069: TypedefEntry newEntry = stFactory.typedefEntry(entry,
2070: (IDLID) repIDStack.peek());
2071: newEntry.sourceFile(scanner.fileEntry());
2072: // comment must immediately precede <type_spec> lexeme
2073: newEntry.comment(token.comment);
2074: try {
2075: newEntry.type(typeSpec(entry));
2076: if (newEntry.type() == entry)
2077: throw ParseException.recursive(scanner, entry
2078: .fullName(), (token.name == null) ? ""
2079: : token.name);
2080: // <d46094> Exception cannot appear within a struct, union, or exception
2081: if (typeOf(newEntry) instanceof ExceptionEntry)
2082: throw ParseException.illegalException(scanner,
2083: entryName(entry));
2084: declarators(newEntry, entry.members());
2085: match(Token.Semicolon);
2086: } catch (ParseException exception) {
2087: skipToSemicolon();
2088: }
2089: } // member
2090:
2091: /**
2092: *
2093: **/
2094: private final boolean isConstTypeSpec(Token t) {
2095: return (t.type == Token.Struct || t.type == Token.Union || t.type == Token.Enum);
2096: } // isConstTypeSpec
2097:
2098: /**
2099: *
2100: **/
2101: private UnionEntry unionType(SymtabEntry entry) throws IOException,
2102: ParseException {
2103: match(Token.Union);
2104: String name = token.name;
2105: match(Token.Identifier);
2106: UnionEntry unionEntry = null;
2107:
2108: if (token.type == Token.Switch) {
2109: repIDStack.push(((IDLID) repIDStack.peek()).clone());
2110: ((IDLID) repIDStack.peek()).appendToName(name);
2111: unionEntry = makeUnionEntry(name, entry, false);
2112: match(Token.Switch);
2113: match(Token.LeftParen);
2114: unionEntry.type(switchTypeSpec(unionEntry));
2115: match(Token.RightParen);
2116: prep.openScope(unionEntry);
2117: match(Token.LeftBrace);
2118: switchBody(unionEntry);
2119: verifyUnion(unionEntry);
2120: prep.closeScope(unionEntry);
2121: match(Token.RightBrace);
2122: repIDStack.pop();
2123: } else if (token.equals(Token.Semicolon)) {
2124: unionEntry = makeUnionEntry(name, entry, true);
2125: } else {
2126: throw ParseException.syntaxError(scanner, new int[] {
2127: Token.Semicolon, Token.Switch }, token.type);
2128: }
2129:
2130: return unionEntry;
2131: } // unionType
2132:
2133: private UnionEntry makeUnionEntry(String name, SymtabEntry entry,
2134: boolean isForward) {
2135: UnionEntry unionEntry = stFactory.unionEntry(entry,
2136: (IDLID) repIDStack.peek());
2137: unionEntry.isReferencable(!isForward);
2138: unionEntry.sourceFile(scanner.fileEntry());
2139: unionEntry.name(name);
2140: // Comment must immediately preceed "union" keyword
2141: unionEntry.comment(tokenHistory.lookBack(1).comment);
2142: pigeonhole(entry, unionEntry);
2143: return unionEntry;
2144: }
2145:
2146: /**
2147: *
2148: **/
2149: private void verifyUnion(UnionEntry u) {
2150: if (u.typeName().equals(overrideName("boolean"))) {
2151: if (caseCount(u) > 2)
2152: ParseException.noDefault(scanner);
2153: } else if (u.type() instanceof EnumEntry) {
2154: if (caseCount(u) > ((EnumEntry) u.type()).elements().size())
2155: ParseException.noDefault(scanner);
2156: }
2157: } // verifyUnion
2158:
2159: /**
2160: *
2161: **/
2162: private long caseCount(UnionEntry u) {
2163: long cases = 0;
2164: Enumeration branches = u.branches().elements();
2165: while (branches.hasMoreElements()) {
2166: UnionBranch branch = (UnionBranch) branches.nextElement();
2167: cases += branch.labels.size();
2168: if (branch.isDefault)
2169: ++cases;
2170: }
2171: return cases;
2172: } // caseCount
2173:
2174: /**
2175: *
2176: **/
2177: private SymtabEntry switchTypeSpec(UnionEntry entry)
2178: throws IOException, ParseException {
2179: SymtabEntry ret = null;
2180: switch (token.type) {
2181: case Token.Long:
2182: case Token.Short:
2183: case Token.Unsigned:
2184: return integerType(entry);
2185: case Token.Char:
2186: case Token.Wchar:
2187: return charType();
2188: case Token.Boolean:
2189: return booleanType();
2190: case Token.Enum:
2191: return enumType(entry);
2192: case Token.Identifier:
2193: case Token.DoubleColon:
2194: ret = scopedName(entry, stFactory.primitiveEntry());
2195: if (hasArrayInfo(entry.type()))
2196: ParseException.illegalArray(scanner, "switch");
2197: SymtabEntry retType = typeOf(ret);
2198: if (!(retType instanceof EnumEntry || retType instanceof PrimitiveEntry))
2199: ParseException
2200: .wrongType(
2201: scanner,
2202: ret.fullName(),
2203: "long, unsigned long, short, unsigned short, char, boolean, enum",
2204: entryName(ret.type()));
2205: else if (ret instanceof PrimitiveEntry) {
2206: SymtabEntry octet = qualifiedEntry("octet");
2207: SymtabEntry flt = qualifiedEntry("float");
2208: SymtabEntry dbl = qualifiedEntry("double");
2209: if (retType == octet || retType == flt
2210: || retType == dbl)
2211: ParseException
2212: .wrongType(
2213: scanner,
2214: ret.fullName(),
2215: "long, unsigned long, short, unsigned short, char, boolean, enum",
2216: entryName(ret.type()));
2217: }
2218: break;
2219: default:
2220: throw ParseException.syntaxError(scanner, new int[] {
2221: Token.Long, Token.Short, Token.Unsigned,
2222: Token.Char, Token.Boolean, Token.Enum,
2223: Token.Identifier, Token.DoubleColon }, token.type);
2224: }
2225: return ret;
2226: } // switchTypeSpec
2227:
2228: // This is only used by the union methods
2229: UnionBranch defaultBranch = null;
2230:
2231: /**
2232: *
2233: **/
2234: private void switchBody(UnionEntry entry) throws IOException,
2235: ParseException {
2236: caseProd(entry);
2237: while (!token.equals(Token.RightBrace))
2238: caseProd(entry);
2239: entry.defaultBranch((defaultBranch == null) ? null
2240: : defaultBranch.typedef);
2241: defaultBranch = null;
2242: } // switchBody
2243:
2244: /**
2245: *
2246: **/
2247: private void caseProd(UnionEntry entry) throws IOException,
2248: ParseException {
2249: UnionBranch branch = new UnionBranch();
2250: entry.addBranch(branch);
2251: caseLabel(entry, branch);
2252: while (token.equals(Token.Case) || token.equals(Token.Default))
2253: caseLabel(entry, branch);
2254: elementSpec(entry, branch);
2255: match(Token.Semicolon);
2256: } // caseProd
2257:
2258: /**
2259: *
2260: **/
2261: private void caseLabel(UnionEntry entry, UnionBranch branch)
2262: throws IOException, ParseException {
2263: if (token.type == Token.Case) {
2264: match(Token.Case);
2265: ConstEntry tmpEntry = stFactory.constEntry(entry,
2266: (IDLID) repIDStack.peek());
2267: tmpEntry.sourceFile(scanner.fileEntry());
2268: tmpEntry.type(entry);
2269:
2270: Expression label;
2271: SymtabEntry type = typeOf(entry.type());
2272: if (type instanceof EnumEntry)
2273: label = matchEnum((EnumEntry) type);
2274: else {
2275: label = constExp(tmpEntry);
2276: verifyConstType(label, type);
2277: }
2278: if (entry.has(label))
2279: ParseException.branchLabel(scanner, label.rep());
2280: branch.labels.addElement(label);
2281: match(Token.Colon);
2282: } else if (token.type == Token.Default) {
2283: match(Token.Default);
2284: match(Token.Colon);
2285: if (entry.defaultBranch() != null)
2286: ParseException.alreadyDefaulted(scanner);
2287: branch.isDefault = true;
2288: defaultBranch = branch;
2289: } else
2290: throw ParseException.syntaxError(scanner, new int[] {
2291: Token.Case, Token.Default }, token.type);
2292: } // caselabel
2293:
2294: /**
2295: *
2296: **/
2297: private Expression matchEnum(EnumEntry entry) throws IOException,
2298: ParseException {
2299: // Get the symbol table entry for the case label based on the
2300: // scope of the EnumEntry, NOT the UnionEntry (the union could be
2301: // in a different scope than the enum). Given
2302: // module M { enum E {A, B, C, D}; };
2303: // a case label for A could be one of the following:
2304: // case A:
2305: // case M::A:
2306: // case ::M::A:
2307: SymtabEntry label = scopedName(entry.container(),
2308: new SymtabEntry());
2309: return exprFactory.terminal(label.name(), false);
2310: } // matchEnum
2311:
2312: /**
2313: *
2314: **/
2315: private void elementSpec(UnionEntry entry, UnionBranch branch)
2316: throws IOException, ParseException {
2317: TypedefEntry typedef = stFactory.typedefEntry(entry,
2318: (IDLID) repIDStack.peek());
2319: typedef.sourceFile(scanner.fileEntry());
2320: // Comment must immediately precede <type_spec> lexeme
2321: typedef.comment(token.comment);
2322: typedef.type(typeSpec(entry));
2323: if (typedef.type() == entry)
2324: throw ParseException.recursive(scanner, entry.fullName(),
2325: (token.name == null) ? "" : token.name);
2326: // <d46094> Exception cannot appear within a struct, union, or exception
2327: if (typeOf(typedef) instanceof ExceptionEntry)
2328: throw ParseException.illegalException(scanner,
2329: entryName(entry));
2330: declarator(typedef);
2331: branch.typedef = typedef;
2332: // Ensure a branch with the same name doesn't already exist.
2333: if (entry.has(typedef))
2334: ParseException.branchName(scanner, typedef.name());
2335: } // elementSpec
2336:
2337: /**
2338: *
2339: **/
2340: private EnumEntry enumType(SymtabEntry entry) throws IOException,
2341: ParseException {
2342: match(Token.Enum);
2343: EnumEntry enumEntry = newEnumEntry(entry);
2344: // comment must immediately precede "enum" keyword
2345: enumEntry.comment(tokenHistory.lookBack(1).comment);
2346: enumEntry.name(token.name);
2347: match(Token.Identifier);
2348: prep.openScope(enumEntry);
2349: match(Token.LeftBrace);
2350: if (isntInStringList(enumEntry.elements(), token.name)) {
2351: enumEntry.addElement(token.name);
2352: SymtabEntry element = new SymtabEntry(entry,
2353: (IDLID) repIDStack.peek());
2354: // if block taken from EnumEntry ctor
2355: if (element.module().equals(""))
2356: element.module(element.name());
2357: else if (!element.name().equals(""))
2358: element.module(element.module() + "/" + element.name());
2359: element.name(token.name);
2360: // <d50237> Place the SymtabEntry representing this enumeration
2361: // contant into the SymtabEntry defining its scope (e.g., InterfaceEntry,
2362: // ValueEntry, etc.) rather than the SymtabEntry passed in, which
2363: // may not define the contant's scope (e.g., TypedefEntry).
2364: //pigeonhole (entry, element); } <daz>
2365: pigeonhole(enumEntry.container(), element);
2366: }
2367: match(Token.Identifier);
2368: enumType2(enumEntry);
2369: prep.closeScope(enumEntry);
2370: match(Token.RightBrace);
2371: return enumEntry;
2372: } // enumType
2373:
2374: /**
2375: *
2376: **/
2377: private void enumType2(EnumEntry entry) throws IOException,
2378: ParseException {
2379: while (token.type == Token.Comma) {
2380: match(Token.Comma);
2381: String name = token.name;
2382: match(Token.Identifier);
2383: if (isntInStringList(entry.elements(), name)) {
2384: entry.addElement(name);
2385: SymtabEntry element = new SymtabEntry(
2386: entry.container(), (IDLID) repIDStack.peek());
2387: // if block taken from EnumEntry ctor:
2388: if (element.module().equals(""))
2389: element.module(element.name());
2390: else if (!element.name().equals(""))
2391: element.module(element.module() + "/"
2392: + element.name());
2393: element.name(name);
2394: pigeonhole(entry.container(), element);
2395: }
2396: }
2397: } // enumType2
2398:
2399: /**
2400: *
2401: **/
2402: private SequenceEntry sequenceType(SymtabEntry entry)
2403: throws IOException, ParseException {
2404: match(Token.Sequence);
2405: match(Token.LessThan);
2406:
2407: SequenceEntry newEntry = newSequenceEntry(entry);
2408: SymtabEntry tsentry = simpleTypeSpec(newEntry, false);
2409: newEntry.type(tsentry);
2410: if (!tsentry.isReferencable()) {
2411: // This is a sequence type that is referencing an
2412: // incomplete forward declaration of a struct or
2413: // union. Save the sequence in a list for later
2414: // backpatching.
2415: try {
2416: List fwdTypes = (List) tsentry.dynamicVariable(ftlKey);
2417: if (fwdTypes == null) {
2418: fwdTypes = new ArrayList();
2419: tsentry.dynamicVariable(ftlKey, fwdTypes);
2420: }
2421: fwdTypes.add(newEntry);
2422: } catch (NoSuchFieldException exc) {
2423: throw new IllegalStateException();
2424: }
2425: }
2426:
2427: if (token.type == Token.Comma) {
2428: match(Token.Comma);
2429: ConstEntry tmpEntry = stFactory.constEntry(newEntry,
2430: (IDLID) repIDStack.peek());
2431: tmpEntry.sourceFile(scanner.fileEntry());
2432: tmpEntry.type(qualifiedEntry("long"));
2433: newEntry.maxSize(positiveIntConst(tmpEntry));
2434: verifyConstType(newEntry.maxSize(), qualifiedEntry("long"));
2435: }
2436: match(Token.GreaterThan);
2437: return newEntry;
2438: } // sequenceType
2439:
2440: /**
2441: *
2442: **/
2443: private StringEntry stringType(SymtabEntry entry)
2444: throws IOException, ParseException {
2445: StringEntry string = stFactory.stringEntry();
2446: if (token.type == Token.String) {
2447: string.name(overrideName("string"));
2448: match(Token.String);
2449: } else {
2450: string.name(overrideName("wstring"));
2451: match(Token.Wstring);
2452: }
2453: string.maxSize(stringType2(entry));
2454: return string;
2455: } // stringType
2456:
2457: /**
2458: *
2459: **/
2460: private Expression stringType2(SymtabEntry entry)
2461: throws IOException, ParseException {
2462: if (token.type == Token.LessThan) {
2463: match(Token.LessThan);
2464:
2465: // START IBM.11417 failure in the IDL compiler
2466: //Expression maxSize = positiveIntConst (entry); IBM.11417
2467:
2468: ConstEntry tmpEntry = stFactory.constEntry(entry,
2469: (IDLID) repIDStack.peek());
2470: tmpEntry.sourceFile(scanner.fileEntry());
2471: tmpEntry.type(qualifiedEntry("long"));
2472: Expression maxSize = positiveIntConst(tmpEntry);
2473:
2474: // END IBM.11417
2475:
2476: verifyConstType(maxSize, qualifiedEntry("long"));
2477: match(Token.GreaterThan);
2478: return maxSize;
2479: }
2480: return null;
2481: } // stringType2
2482:
2483: /**
2484: *
2485: **/
2486: private void fixedArraySize(TypedefEntry entry) throws IOException,
2487: ParseException {
2488: match(Token.LeftBracket);
2489: ConstEntry tmpEntry = stFactory.constEntry(entry,
2490: (IDLID) repIDStack.peek());
2491: tmpEntry.sourceFile(scanner.fileEntry());
2492: // <d58058> Set type of tmpExpr to "long", which is the array index type.
2493: // Previously, this type was erroneously set to the array element type.
2494: //tmpEntry.type (entry.type ());
2495: tmpEntry.type(qualifiedEntry("long"));
2496: Expression expr = positiveIntConst(tmpEntry);
2497: entry.addArrayInfo(expr);
2498: verifyConstType(expr, qualifiedEntry("long"));
2499: match(Token.RightBracket);
2500: } // fixedArraySize
2501:
2502: /**
2503: *
2504: **/
2505: private void attrDcl(InterfaceEntry entry) throws IOException,
2506: ParseException {
2507: AttributeEntry attribute = stFactory.attributeEntry(entry,
2508: (IDLID) repIDStack.peek());
2509: attribute.sourceFile(scanner.fileEntry());
2510: // Comment must immediately precede the "attribute" keyword. Save the
2511: // comment preceding the declaration for use below.
2512: attribute.comment(token.comment);
2513: Comment dclComment = attribute.comment();
2514:
2515: if (token.type == Token.Readonly) {
2516: match(Token.Readonly);
2517: attribute.readOnly(true);
2518: }
2519: match(Token.Attribute);
2520: attribute.type(paramTypeSpec(attribute));
2521: attribute.name(token.name);
2522: // Override declaration comment if attribute identifier is commented
2523: if (!token.comment.text().equals(""))
2524: attribute.comment(token.comment);
2525: entry.methodsAddElement(attribute, scanner);
2526: pigeonholeMethod(entry, attribute);
2527: // Declaration comment was overriden:
2528: if (!token.comment.text().equals("")) {
2529: // Create a temporary attribute with declaration comment so cloning in
2530: // attrdcl2() can use declaration comment as default.
2531: AttributeEntry attributeClone = (AttributeEntry) attribute
2532: .clone();
2533: attributeClone.comment(dclComment);
2534:
2535: match(Token.Identifier);
2536: attrDcl2(entry, attributeClone);
2537: } else {
2538: match(Token.Identifier);
2539: attrDcl2(entry, attribute);
2540: }
2541: //match (Token.Identifier);
2542: //attrDcl2 (entry, attribute);
2543: } // attrDcl
2544:
2545: /**
2546: *
2547: **/
2548: private void attrDcl2(InterfaceEntry entry, AttributeEntry clone)
2549: throws IOException, ParseException {
2550: while (token.type == Token.Comma) {
2551: match(Token.Comma);
2552: AttributeEntry attribute = (AttributeEntry) clone.clone();
2553: attribute.name(token.name);
2554: // Override the declaration comment (i.e., that preceding the
2555: // "attribute" keyword) if the attribute identifier is commented.
2556: if (!token.comment.text().equals(""))
2557: attribute.comment(token.comment);
2558: entry.methodsAddElement(attribute, scanner);
2559: pigeonholeMethod(entry, attribute);
2560: match(Token.Identifier);
2561: }
2562: } // attrDcl2
2563:
2564: /**
2565: *
2566: **/
2567: private void exceptDcl(SymtabEntry entry) throws IOException,
2568: ParseException {
2569: match(Token.Exception);
2570: ExceptionEntry exceptEntry = stFactory.exceptionEntry(entry,
2571: (IDLID) repIDStack.peek());
2572: repIDStack.push(((IDLID) repIDStack.peek()).clone());
2573: ((IDLID) repIDStack.peek()).appendToName(token.name);
2574: exceptEntry.sourceFile(scanner.fileEntry());
2575: // Comment must immediately precede "exception" keyword
2576: exceptEntry.comment(tokenHistory.lookBack(1).comment);
2577: exceptEntry.name(token.name);
2578: match(Token.Identifier);
2579: pigeonhole(entry, exceptEntry);
2580: if (token.equals(Token.LeftBrace)) {
2581: prep.openScope(exceptEntry);
2582: match(Token.LeftBrace);
2583: memberList2(exceptEntry);
2584: prep.closeScope(exceptEntry);
2585: match(Token.RightBrace);
2586: repIDStack.pop();
2587: } else
2588: throw ParseException.syntaxError(scanner, Token.LeftBrace,
2589: token.type);
2590: } // exceptDcl
2591:
2592: /**
2593: *
2594: **/
2595: private void opDcl(InterfaceEntry entry) throws IOException,
2596: ParseException {
2597: MethodEntry method = stFactory.methodEntry(entry,
2598: (IDLID) repIDStack.peek());
2599: method.sourceFile(scanner.fileEntry());
2600: // Comment must immediately precede "oneway" keyword or <return_type_spec>
2601: method.comment(token.comment);
2602: if (token.type == Token.Oneway) {
2603: match(Token.Oneway);
2604: method.oneway(true);
2605: }
2606: method.type(opTypeSpec(method));
2607: repIDStack.push(((IDLID) repIDStack.peek()).clone());
2608: ((IDLID) repIDStack.peek()).appendToName(token.name);
2609: method.name(token.name);
2610: entry.methodsAddElement(method, scanner);
2611: pigeonholeMethod(entry, method);
2612: opDcl2(method);
2613: if (method.oneway())
2614: checkIfOpLegalForOneway(method);
2615: repIDStack.pop();
2616: } // opDcl
2617:
2618: /**
2619: *
2620: **/
2621: private void checkIfOpLegalForOneway(MethodEntry method) {
2622: boolean notLegal = false;
2623: if ((method.type() != null)
2624: || (method.exceptions().size() != 0))
2625: notLegal = true;
2626: else {
2627: for (Enumeration e = method.parameters().elements(); e
2628: .hasMoreElements();) {
2629: if (((ParameterEntry) e.nextElement()).passType() != ParameterEntry.In) {
2630: notLegal = true;
2631: break;
2632: }
2633: }
2634: }
2635: if (notLegal)
2636: ParseException.oneway(scanner, method.name());
2637: } // checkifOpLegalForOneway
2638:
2639: /**
2640: *
2641: **/
2642: private void opDcl2(MethodEntry method) throws IOException,
2643: ParseException {
2644: if (token.equals(Token.MacroIdentifier)) {
2645: match(Token.MacroIdentifier);
2646: parameterDcls2(method);
2647: } else {
2648: match(Token.Identifier);
2649: parameterDcls(method);
2650: }
2651: opDcl3(method);
2652: } // opDcl2
2653:
2654: /**
2655: *
2656: **/
2657: private void opDcl3(MethodEntry entry) throws IOException,
2658: ParseException {
2659: if (token.type != Token.Semicolon) {
2660: if (!token.equals(Token.Raises)
2661: && !token.equals(Token.Context))
2662: throw ParseException.syntaxError(scanner, new int[] {
2663: Token.Raises, Token.Context, Token.Semicolon },
2664: token.type);
2665: if (token.type == Token.Raises)
2666: raisesExpr(entry);
2667: if (token.type == Token.Context)
2668: contextExpr(entry);
2669: }
2670: } // opDcl3
2671:
2672: /**
2673: *
2674: **/
2675: private SymtabEntry opTypeSpec(SymtabEntry entry)
2676: throws IOException, ParseException {
2677: SymtabEntry ret = null;
2678: if (token.type == Token.Void)
2679: match(Token.Void);
2680: else
2681: ret = paramTypeSpec(entry);
2682: return ret;
2683: } // opTypeSpec
2684:
2685: /**
2686: *
2687: **/
2688: private void parameterDcls(MethodEntry entry) throws IOException,
2689: ParseException {
2690: match(Token.LeftParen);
2691: parameterDcls2(entry);
2692: } // parameterDcls
2693:
2694: /**
2695: *
2696: **/
2697: private void parameterDcls2(MethodEntry entry) throws IOException,
2698: ParseException {
2699: if (token.type == Token.RightParen)
2700: match(Token.RightParen);
2701: else {
2702: paramDcl(entry);
2703: while (token.type == Token.Comma) {
2704: match(Token.Comma);
2705: paramDcl(entry);
2706: }
2707: match(Token.RightParen);
2708: }
2709: } // paraneterDcls2
2710:
2711: /**
2712: *
2713: **/
2714: private void paramDcl(MethodEntry entry) throws IOException,
2715: ParseException {
2716: ParameterEntry parmEntry = stFactory.parameterEntry(entry,
2717: (IDLID) repIDStack.peek());
2718: parmEntry.sourceFile(scanner.fileEntry());
2719: // Comment must immeiately precede the parameter attribute
2720: parmEntry.comment(token.comment);
2721: paramAttribute(parmEntry);
2722: parmEntry.type(paramTypeSpec(entry));
2723: parmEntry.name(token.name);
2724: match(Token.Identifier);
2725: if (isntInList(entry.parameters(), parmEntry.name()))
2726: entry.addParameter(parmEntry);
2727: } // paramDcl
2728:
2729: /**
2730: *
2731: **/
2732: private void paramAttribute(ParameterEntry entry)
2733: throws IOException, ParseException {
2734: if (token.type == Token.In) {
2735: entry.passType(ParameterEntry.In);
2736: match(Token.In);
2737: } else if (token.type == Token.Out) {
2738: entry.passType(ParameterEntry.Out);
2739: match(Token.Out);
2740: } else if (token.type == Token.Inout) {
2741: entry.passType(ParameterEntry.Inout);
2742: match(Token.Inout);
2743: } else
2744: throw ParseException.syntaxError(scanner, new int[] {
2745: Token.In, Token.Out, Token.Inout }, token.type);
2746: } // paramAttribute
2747:
2748: /**
2749: *
2750: **/
2751: private void raisesExpr(MethodEntry entry) throws IOException,
2752: ParseException {
2753: match(Token.Raises);
2754: match(Token.LeftParen);
2755: // Comment must immediately precede <scoped_name> for exception
2756: Comment tempComment = token.comment;
2757: SymtabEntry exception = scopedName(entry.container(), stFactory
2758: .exceptionEntry());
2759: if (typeOf(exception) instanceof ExceptionEntry) {
2760: // Comment must immediately precede <scoped_name> for exception
2761: exception.comment(tempComment);
2762: if (isntInList(entry.exceptions(), exception))
2763: entry.exceptionsAddElement((ExceptionEntry) exception);
2764: } else
2765: ParseException.wrongType(scanner, exception.fullName(),
2766: "exception", entryName(exception.type()));
2767: raisesExpr2(entry);
2768: match(Token.RightParen);
2769: } // raisesExpr
2770:
2771: /**
2772: *
2773: **/
2774: private void raisesExpr2(MethodEntry entry) throws IOException,
2775: ParseException {
2776: while (token.type == Token.Comma) {
2777: match(Token.Comma);
2778: // Comment must immediately precede <scoped_name> of exception
2779: Comment tempComment = token.comment;
2780: SymtabEntry exception = scopedName(entry.container(),
2781: stFactory.exceptionEntry());
2782: if (typeOf(exception) instanceof ExceptionEntry) {
2783: // Comment must immediately precede <scoped_name> of exception
2784: exception.comment(tempComment);
2785: if (isntInList(entry.exceptions(), exception))
2786: entry.addException((ExceptionEntry) exception);
2787: } else
2788: ParseException.wrongType(scanner, exception.fullName(),
2789: "exception", entryName(exception.type()));
2790: }
2791: } // raisesExpr2
2792:
2793: /**
2794: *
2795: **/
2796: private void contextExpr(MethodEntry entry) throws IOException,
2797: ParseException {
2798: match(Token.Context);
2799: match(Token.LeftParen);
2800: String stringLit = (String) stringLiteral().value();
2801: if (isntInStringList(entry.contexts(), stringLit))
2802: entry.addContext(stringLit);
2803: contextExpr2(entry);
2804: match(Token.RightParen);
2805: } // contextExpr
2806:
2807: private void contextExpr2(MethodEntry entry) throws IOException,
2808: ParseException {
2809: while (token.type == Token.Comma) {
2810: match(Token.Comma);
2811: String stringLit = (String) stringLiteral().value();
2812: if (isntInStringList(entry.contexts(), stringLit))
2813: entry.addContext(stringLit);
2814: }
2815: } // contextExpr2
2816:
2817: /**
2818: *
2819: **/
2820: private SymtabEntry paramTypeSpec(SymtabEntry entry)
2821: throws IOException, ParseException {
2822: SymtabEntry ret = null;
2823: switch (token.type) {
2824: case Token.Float:
2825: case Token.Double:
2826: case Token.Long:
2827: case Token.Short:
2828: case Token.Unsigned:
2829: case Token.Char:
2830: case Token.Wchar:
2831: case Token.Boolean:
2832: case Token.Octet:
2833: case Token.Any:
2834: return baseTypeSpec(entry);
2835: case Token.String:
2836: case Token.Wstring:
2837: return stringType(entry);
2838: case Token.Identifier:
2839: case Token.Object:
2840: // <f46082.40>
2841: case Token.ValueBase:
2842: case Token.DoubleColon:
2843: ret = scopedName(entry.container(), stFactory
2844: .primitiveEntry());
2845: if (typeOf(ret) instanceof AttributeEntry)
2846: //ParseException.attributeParamType (scanner);
2847: ParseException.attributeNotType(scanner, ret.name());
2848: else // <d60942>
2849: if (typeOf(ret) instanceof MethodEntry)
2850: ParseException.operationNotType(scanner, ret.name());
2851:
2852: //if (!(returnType instanceof PrimitiveEntry ||
2853: // returnType instanceof StringEntry))
2854: //ParseException.wrongType (scanner, ret.fullName(),
2855: // "primitive or string", entryName (ret.type()));
2856: break;
2857: default:
2858: throw ParseException.syntaxError(scanner, new int[] {
2859: Token.Float, Token.Double, Token.Long, Token.Short,
2860: Token.Unsigned, Token.Char, Token.Wchar,
2861: Token.Boolean, Token.Octet, Token.Any,
2862: Token.String, Token.Wstring, Token.Identifier,
2863: Token.DoubleColon, Token.ValueBase }, token.type);
2864: }
2865: return ret;
2866: } // paramTypeSpec
2867:
2868: /**
2869: *
2870: **/
2871: private void match(int type) throws IOException, ParseException {
2872: ParseException exception = null;
2873: if (!token.equals(type)) {
2874: exception = ParseException.syntaxError(scanner, type,
2875: token.type);
2876: // Missing a semicolon is a common error. If a semicolon was expected,
2877: // assume it exists and keep the current token (don't get the next one).
2878: // BEWARE!!! THIS HAS THE POTENTIAL FOR AN INFINITE LOOP!
2879: if (type == Token.Semicolon)
2880: return;
2881: }
2882: // <f46082.40> Unecessary due to new valueElement() algorithm.
2883: //if (!tokenStack.empty())
2884: //{
2885: // token = (Token)tokenStack.pop ();
2886: // return;
2887: //}
2888:
2889: // Fetch the next token.
2890: token = scanner.getToken();
2891:
2892: // <d62023> Issue warnings about tokens.
2893: issueTokenWarnings();
2894:
2895: // Maintain history of most recent tokens.
2896: tokenHistory.insert(token);
2897:
2898: // <d59166> Identifiers that collide with keywords are illegal. Note
2899: // that escaped identifers never collide!
2900: /*
2901: if (token.collidesWithKeyword ())
2902: {
2903: // <f60858.1> Issue a warning only
2904: if (corbaLevel <= 2.2f)
2905: ParseException.keywordCollisionWarning (scanner, token.name);
2906: else
2907: exception = ParseException.keywordCollision (scanner, token.name);
2908: }
2909: */
2910:
2911: while (token.isDirective())
2912: token = prep.process(token);
2913:
2914: // If the token is a defined thingy, scan the defined string
2915: // instead of the input stream for a while.
2916: if (token.equals(Token.Identifier)
2917: || token.equals(Token.MacroIdentifier)) {
2918: String string = (String) symbols.get(token.name);
2919: if (string != null && !string.equals("")) {
2920: // If this is a macro, parse the macro
2921: if (macros.contains(token.name)) {
2922: scanner.scanString(prep.expandMacro(string, token));
2923: match(token.type);
2924: } else // This is just a normal define.
2925: {
2926: scanner.scanString(string);
2927: match(token.type);
2928: }
2929: }
2930: }
2931: if (exception != null)
2932: throw exception;
2933: } // match
2934:
2935: // <d62023>
2936: /**
2937: * Issue warnings according to attributes of current Token.
2938: **/
2939: private void issueTokenWarnings() {
2940: if (noWarn)
2941: return;
2942:
2943: if ((token.equals(Token.Identifier) || token
2944: .equals(Token.MacroIdentifier))
2945: && !token.isEscaped()) {
2946: // Identifier collision with keyword in another release.
2947: // Identifier collision with keyword in letter, but not in case.
2948: if (token.collidesWithKeyword())
2949: ParseException.warning(scanner, Util.getMessage(
2950: "Migration.keywordCollision", token.name));
2951: }
2952: // Deprecated keyword.
2953: if (token.isKeyword() && token.isDeprecated())
2954: ParseException.warning(scanner, Util.getMessage(
2955: "Deprecated.keyword", token.toString()));
2956: } // issueTokenWarnings
2957:
2958: /**
2959: *
2960: **/
2961: private ModuleEntry newModule(ModuleEntry oldEntry) {
2962: ModuleEntry entry = stFactory.moduleEntry(oldEntry,
2963: (IDLID) repIDStack.peek());
2964: entry.sourceFile(scanner.fileEntry());
2965: entry.name(token.name);
2966: // If this named module already exists, just reopen it.
2967: /* <46082.46.01> if cppModule, always create new module entry */
2968: SymtabEntry prevEntry = (SymtabEntry) symbolTable.get(entry
2969: .fullName());
2970: if (!cppModule && prevEntry != null
2971: && prevEntry instanceof ModuleEntry) {
2972: // A module has been reopened, return that ModuleEntry.
2973: entry = (ModuleEntry) prevEntry;
2974: if (oldEntry == topLevelModule) {
2975: // Do a little checking:
2976: if (!entry.emit())
2977: // The entry module is being reopened to put new stuff into it.
2978: // The module itself is not marked as "emit", but the new stuff
2979: // may be, so put the module on the emitList (add it to topLevelModule).
2980: addToContainer(oldEntry, entry);
2981: else if (!oldEntry.contained().contains(entry))
2982: // <d50767> The entry module being reopened is to be emitted, but
2983: // will not be placed on the emitList! I.E., it was not added to
2984: // topLevelModule. Occurs when a generator manually inserts
2985: // ModuleEntrys into the symbol table (e.g., org; see preParse()
2986: // in ...idl.toJava.Compile). <daz>
2987: addToContainer(oldEntry, entry);
2988: }
2989: } else
2990: pigeonhole(oldEntry, entry);
2991: return entry;
2992: } // newModule
2993:
2994: /**
2995: *
2996: **/
2997: private EnumEntry newEnumEntry(SymtabEntry oldEntry) {
2998: EnumEntry entry = stFactory.enumEntry(oldEntry,
2999: (IDLID) repIDStack.peek());
3000: entry.sourceFile(scanner.fileEntry());
3001: entry.name(token.name);
3002: pigeonhole(oldEntry, entry);
3003: return entry;
3004: } // newEnumEntry
3005:
3006: /**
3007: *
3008: **/
3009: private SequenceEntry newSequenceEntry(SymtabEntry oldEntry) {
3010: SequenceEntry entry = stFactory.sequenceEntry(oldEntry,
3011: (IDLID) repIDStack.peek());
3012: entry.sourceFile(scanner.fileEntry());
3013: entry.name("");
3014: pigeonhole(oldEntry, entry);
3015: return entry;
3016: } // newSequenceEntry
3017:
3018: private void updateSymbolTable(String fullName, SymtabEntry entry,
3019: boolean lcCheck) {
3020: // Check for case-insensitive collision (IDL error).
3021: String lcFullName = fullName.toLowerCase();
3022: if (lcCheck)
3023: if (lcSymbolTable.get(lcFullName) != null) {
3024: ParseException.alreadyDeclared(scanner, fullName);
3025: }
3026: symbolTable.put(fullName, entry);
3027: lcSymbolTable.put(lcFullName, entry);
3028: // <d59809> Allow fully-qualified CORBA types to be resolved by mapping
3029: // short name (e.g., CORBA/StringValue) to long name, actual name.
3030: String omgPrefix = "org/omg/CORBA";
3031: if (fullName.startsWith(omgPrefix)) {
3032: overrideNames.put("CORBA"
3033: + fullName.substring(omgPrefix.length()), fullName);
3034: }
3035: }
3036:
3037: private void pigeonhole(SymtabEntry container, SymtabEntry entry) {
3038: if (entry.name().equals(""))
3039: entry.name(unknownNamePrefix + ++sequence);
3040:
3041: // If this object is not in the overrides list, then it is
3042: // ok to put it in the table (if it IS in the overrides list,
3043: // it is already in the table under a different name).
3044: String fullName = entry.fullName();
3045: if (overrideNames.get(fullName) == null) {
3046: addToContainer(container, entry);
3047:
3048: // It is an error is this name already exists in the symbol
3049: // table, unless this is a redefinition of a forward decl.
3050: // Re-opening a module is also legal, but not handled here.
3051: SymtabEntry oldEntry = (SymtabEntry) symbolTable
3052: .get(fullName);
3053:
3054: if (oldEntry == null) {
3055: updateSymbolTable(fullName, entry, true);
3056: } else if (oldEntry instanceof ForwardEntry
3057: && entry instanceof InterfaceEntry) {
3058:
3059: String repIDPrefix = ((IDLID) entry.repositoryID())
3060: .prefix();
3061: String oldRepIDPrefix = ((IDLID) oldEntry
3062: .repositoryID()).prefix();
3063: if (repIDPrefix.equals(oldRepIDPrefix)) {
3064: updateSymbolTable(fullName, entry, false);
3065: } else {
3066: ParseException.badRepIDPrefix(scanner, fullName,
3067: oldRepIDPrefix, repIDPrefix);
3068: }
3069: } else if (entry instanceof ForwardEntry
3070: && (oldEntry instanceof InterfaceEntry || oldEntry instanceof ForwardEntry)) {
3071: if (oldEntry instanceof ForwardEntry
3072: && entry.repositoryID() instanceof IDLID
3073: && oldEntry.repositoryID() instanceof IDLID) {
3074:
3075: String repIDPrefix = ((IDLID) entry.repositoryID())
3076: .prefix();
3077: String oldRepIDPrefix = ((IDLID) oldEntry
3078: .repositoryID()).prefix();
3079:
3080: if (!(repIDPrefix.equals(oldRepIDPrefix))) {
3081: // Disallow multiple ForwardEntry's having same Repository
3082: // ID prefixes (CORBA 2.3).
3083: ParseException.badRepIDPrefix(scanner,
3084: fullName, oldRepIDPrefix, repIDPrefix);
3085: }
3086: }
3087: } else if (cppModule && entry instanceof ModuleEntry
3088: && oldEntry instanceof ModuleEntry) {
3089: // Allow multiple ModuleEntrys when user submits
3090: // the -cppModule flag.
3091: } else if (fullName.startsWith("org/omg/CORBA")
3092: || fullName.startsWith("CORBA")) {
3093: // Ignore CORBA PIDL types entered at preParse() by generator.
3094: } else if (isForwardable(oldEntry, entry)) {
3095: // Both oldEntry and entry are structs or unions.
3096: // Legality depends on isReferencable on the two entries:
3097: // oldEntry Entry
3098: // T T ERROR alreadyDeclared
3099: // T F legal fwd decl
3100: // F T if defined in same file legal,
3101: // otherwise ERROR
3102: // F F legal fwd decl
3103: if (oldEntry.isReferencable() && entry.isReferencable())
3104: ParseException.alreadyDeclared(scanner, fullName);
3105:
3106: if (entry.isReferencable()) {
3107: String firstFile = oldEntry.sourceFile()
3108: .absFilename();
3109: String defFile = entry.sourceFile().absFilename();
3110: if (!firstFile.equals(defFile))
3111: ParseException.declNotInSameFile(scanner,
3112: fullName, firstFile);
3113: else {
3114: updateSymbolTable(fullName, entry, false);
3115:
3116: List oldRefList;
3117:
3118: try {
3119: oldRefList = (List) oldEntry
3120: .dynamicVariable(ftlKey);
3121: } catch (NoSuchFieldException exc) {
3122: throw new IllegalStateException();
3123: }
3124:
3125: if (oldRefList != null) {
3126: // Update entries in backpatch list
3127: Iterator iter = oldRefList.iterator();
3128: while (iter.hasNext()) {
3129: SymtabEntry elem = (SymtabEntry) iter
3130: .next();
3131: elem.type(entry);
3132: }
3133: }
3134: }
3135: }
3136: } else {
3137: ParseException.alreadyDeclared(scanner, fullName);
3138: }
3139: }
3140: } // pigeonhole
3141:
3142: private boolean isForwardable(SymtabEntry oldEntry,
3143: SymtabEntry entry) {
3144: return ((oldEntry instanceof StructEntry) && (entry instanceof StructEntry))
3145: || ((oldEntry instanceof UnionEntry) && (entry instanceof UnionEntry));
3146: }
3147:
3148: // pigeonhole checks to see if this entry is already in the symbol
3149: // table and generates an error if it is. Methods must be checked
3150: // not only against the symbol table but also against their
3151: // interface's parent's methods. This is done in InterfaceEntry.
3152: // verifyMethod, so no checking need be done here.
3153:
3154: /**
3155: *
3156: **/
3157: private void pigeonholeMethod(InterfaceEntry container,
3158: MethodEntry entry) {
3159: if (entry.name().equals(""))
3160: entry.name(unknownNamePrefix + ++sequence);
3161:
3162: // If this object is not in the overrides list, then it is
3163: // ok to put it in the table (if it IS in the overrides list,
3164: // it is already in the table under a different name).
3165: String fullName = entry.fullName();
3166: if (overrideNames.get(fullName) == null) {
3167: addToContainer(container, entry);
3168: String lcFullName = fullName.toLowerCase();
3169: symbolTable.put(fullName, entry);
3170: lcSymbolTable.put(lcFullName, entry);
3171: // <d59809> Allow fully-qualified CORBA types to be resolved by mapping
3172: // short name (e.g., CORBA/StringValue) to long name, actual name.
3173: if (fullName.startsWith("org/omg/CORBA"))
3174: overrideNames.put("CORBA" + fullName.substring(13),
3175: fullName);
3176: }
3177: } // pigeonholeMethod
3178:
3179: /**
3180: *
3181: **/
3182: private void addToContainer(SymtabEntry container,
3183: SymtabEntry contained) {
3184: if (container instanceof ModuleEntry)
3185: ((ModuleEntry) container).addContained(contained);
3186: else if (container instanceof InterfaceEntry)
3187: ((InterfaceEntry) container).addContained(contained);
3188: else if (container instanceof StructEntry)
3189: ((StructEntry) container).addContained(contained);
3190: else if (container instanceof UnionEntry)
3191: ((UnionEntry) container).addContained(contained);
3192: else if (container instanceof SequenceEntry)
3193: ((SequenceEntry) container).addContained(contained);
3194: } // addToContainer
3195:
3196: // NOTE: qualifiedEntry/partlyQualifiedEntry/unqualifiedEntry and
3197: // their court could probably use some performance improvements,
3198: // but I'm scared to touch anything. It's the most complex bit of
3199: // code in this parser.
3200:
3201: // The qualified named type is searched for in the following order:
3202: // 1. OverrideNames
3203: // 2. Global scope
3204: // 3. Inheritance scope (if container is an interface)
3205: // A qualified name is one which begins with :: or is assumed to be
3206: // in the global scope (like long, short, etc).
3207:
3208: /**
3209: *
3210: **/
3211: SymtabEntry qualifiedEntry(String typeName) {
3212: SymtabEntry type = recursiveQualifiedEntry(typeName);
3213: if (type == null)
3214: // Then it's not anywhere, report the error.
3215: ParseException.undeclaredType(scanner, typeName);
3216:
3217: // <d57110> Relax this retriction when parsing ID pragma directive, e.g..
3218: //else if (type instanceof ModuleEntry) {
3219: else if (type instanceof ModuleEntry && !_isModuleLegalType) {
3220: // Module's are not valid types.
3221: ParseException.moduleNotType(scanner, typeName);
3222: type = null;
3223: }
3224: return type;
3225: } // qualifiedEntry
3226:
3227: /**
3228: *
3229: **/
3230: SymtabEntry recursiveQualifiedEntry(String typeName) {
3231: SymtabEntry type = null;
3232: if (typeName != null && !typeName.equals("void")) {
3233: int index = typeName.lastIndexOf('/');
3234: if (index >= 0) {
3235: // Figure out if the container of this thing exists, converting any typedefs to interfaces if necessary.
3236: type = recursiveQualifiedEntry(typeName.substring(0,
3237: index));
3238: if (type == null)
3239: return null;
3240: else if (type instanceof TypedefEntry)
3241: typeName = typeOf(type).fullName()
3242: + typeName.substring(index);
3243: }
3244:
3245: // If we got this far, a container exists, start over looking
3246: // for the thing itself (this is the meat of the method):
3247: type = searchOverrideNames(typeName);
3248: if (type == null)
3249: type = (SymtabEntry) symbolTable.get(typeName); // search global scope:
3250: if (type == null)
3251: type = searchGlobalInheritanceScope(typeName);
3252: }
3253: return type;
3254: } // recursiveQualifiedEntry
3255:
3256: // A partially qualified name is of the form <scope>::<name>.
3257: // First the scope is defined (meaning it is fully qualified);
3258: // Then the name is searched for in the scope.
3259:
3260: /**
3261: *
3262: **/
3263: SymtabEntry partlyQualifiedEntry(String typeName,
3264: SymtabEntry container) {
3265: // This is the simple logic of this method:
3266: // type = searchModuleScope (typeName.substring (0, typeName.lastIndexOf ('/')), container);
3267: // type = qualifiedEntry (type.fullName () + typeName.substring (typeName.lastIndexOf ('/')));
3268: // But searchModuleScope only finds the first module that fits.
3269: // The name might not be in that module but in one further out
3270: // in the module scope. Should others be searched?
3271: SymtabEntry type = null;
3272: if (typeName != null) {
3273: int index = typeName.lastIndexOf('/');
3274:
3275: // Figure out if the container of this thing exists, converting any
3276: // typedefs to interfaces if necessary:
3277: type = recursivePQEntry(typeName.substring(0, index),
3278: container);
3279: if (type instanceof TypedefEntry)
3280: typeName = typeOf(type).fullName()
3281: + typeName.substring(index);
3282:
3283: // If we got this far, a container exists, start over looking
3284: // for the thing itself.
3285:
3286: if (container != null)
3287: type = searchModuleScope(typeName.substring(0, typeName
3288: .lastIndexOf('/')), container);
3289: if (type == null)
3290: type = qualifiedEntry(typeName);
3291: else
3292: type = qualifiedEntry(type.fullName()
3293: + typeName.substring(typeName.lastIndexOf('/')));
3294: }
3295: return type;
3296: } // partlyQualifiedEntry
3297:
3298: // partlyQualifiedEntry and recursivePQEntry are almost identical.
3299: // They are different because when the recursive one is looking for
3300: // the existence of containers, the error check for a module type
3301: // must not occur (this check is done in qualifiedEntry). Only
3302: // when the full partly qualified name is being processed must this
3303: // check be performed.
3304:
3305: /**
3306: *
3307: **/
3308: SymtabEntry recursivePQEntry(String typeName, SymtabEntry container) {
3309: SymtabEntry type = null;
3310: if (typeName != null) {
3311: int index = typeName.lastIndexOf('/');
3312: if (index < 0)
3313: type = searchModuleScope(typeName, container);
3314: else {
3315: // Figure out if the container of this thing exists, converting any
3316: // typedefs to interfaces if necessary:
3317: type = recursivePQEntry(typeName.substring(0, index),
3318: container);
3319: if (type == null)
3320: return null;
3321: else if (type instanceof TypedefEntry)
3322: typeName = typeOf(type).fullName()
3323: + typeName.substring(index);
3324:
3325: // If we got this far, a container exists, start over, looking
3326: // for the thing itself (This is the meat of the method):
3327: if (container != null)
3328: type = searchModuleScope(typeName.substring(0,
3329: typeName.lastIndexOf('/')), container);
3330: if (type == null)
3331: recursiveQualifiedEntry(typeName);
3332: else
3333: type = recursiveQualifiedEntry(type.fullName()
3334: + typeName.substring(typeName
3335: .lastIndexOf('/')));
3336: }
3337: }
3338: return type;
3339: } // recursivePQEntry
3340:
3341: // The named type is searched for in the following order:
3342: // 1. Local scope
3343: // 2. Inheritance scope
3344: // 3. OverrideNames
3345: // 4. Module scope
3346:
3347: /**
3348: *
3349: **/
3350: SymtabEntry unqualifiedEntry(String typeName, SymtabEntry container) {
3351: SymtabEntry type = unqualifiedEntryWMod(typeName, container);
3352:
3353: // <d57110> Relax this retriction in special cases, e.g., when
3354: // parsing a ID pragma directive.
3355: //if (type instanceof ModuleEntry) {
3356: if (type instanceof ModuleEntry && !_isModuleLegalType) {
3357: // Module's are not valid types:
3358: ParseException.moduleNotType(scanner, typeName);
3359: type = null;
3360: }
3361: return type;
3362: } // unqualifiedEntry
3363:
3364: /**
3365: *
3366: **/
3367: SymtabEntry unqualifiedEntryWMod(String typeName,
3368: SymtabEntry container) {
3369: SymtabEntry type = null;
3370: if ((typeName != null) && !typeName.equals("void")) {
3371: // Search local scope:
3372: type = (SymtabEntry) symbolTable.get(container.fullName()
3373: + '/' + typeName);
3374: if (type == null)
3375: type = searchLocalInheritanceScope(typeName, container);
3376: if (type == null)
3377: type = searchOverrideNames(typeName);
3378: if ((type == null) && (container != null))
3379: type = searchModuleScope(typeName, container);
3380: if (type == null)
3381: type = searchParentInheritanceScope(typeName, container);
3382: }
3383: if (type == null)
3384: // Then it's not anywhere, report the error:
3385: ParseException.undeclaredType(scanner, typeName);
3386: return type;
3387: } // unqualifiedEntryWMod
3388:
3389: /**
3390: * Walks up the enclosing scopes until it finds an interface type. Then,
3391: * searches up that interface inheritance tree for the type definition.
3392: *
3393: * @param name type name to be searched for.
3394: * @param ptype parent type entry.
3395: **/
3396: SymtabEntry searchParentInheritanceScope(String name,
3397: SymtabEntry ptype) {
3398:
3399: String cname = ptype.fullName();
3400:
3401: while ((ptype != null) && !(cname.equals(""))
3402: && !(ptype instanceof InterfaceEntry)) {
3403: int index = cname.lastIndexOf('/');
3404: if (index < 0) {
3405: cname = "";
3406: } else {
3407: cname = cname.substring(0, index);
3408: ptype = (SymtabEntry) symbolTable.get(cname);
3409: }
3410: }
3411:
3412: if ((ptype == null) || !(ptype instanceof InterfaceEntry)) {
3413: return null; // could not find an enclosing interface type - give up.
3414: }
3415:
3416: // check if the enclosing interface supports the type definition.
3417: String fullName = ptype.fullName() + '/' + name;
3418: SymtabEntry type = (SymtabEntry) symbolTable.get(fullName);
3419: if (type != null) {
3420: return type; // found type definition.
3421: }
3422:
3423: // search up the interface inheritance tree.
3424: return searchLocalInheritanceScope(name, ptype);
3425: }
3426:
3427: /**
3428: *
3429: **/
3430: SymtabEntry searchGlobalInheritanceScope(String name) {
3431: // See if the container of this named object is an interface:
3432: int index = name.lastIndexOf('/');
3433: SymtabEntry entry = null;
3434: if (index >= 0) {
3435: String containerName = name.substring(0, index);
3436: entry = (SymtabEntry) symbolTable.get(containerName);
3437: entry = (entry instanceof InterfaceEntry)
3438: // It's an interface, now look in its inheritance scope:
3439: ? searchLocalInheritanceScope(name.substring(index + 1),
3440: entry)
3441: : null;
3442: }
3443: return entry;
3444: } // searchGlobalInheritanceScope
3445:
3446: /**
3447: *
3448: **/
3449: SymtabEntry searchLocalInheritanceScope(String name,
3450: SymtabEntry container) {
3451: return (container instanceof InterfaceEntry) ? searchDerivedFrom(
3452: name, (InterfaceEntry) container)
3453: : null;
3454: } // searchLocalInheritanceScope
3455:
3456: /**
3457: *
3458: **/
3459: SymtabEntry searchOverrideNames(String name) {
3460: String overrideName = (String) overrideNames.get(name);
3461: return (overrideName != null) ? (SymtabEntry) symbolTable
3462: .get(overrideName) : null;
3463: } // searchOverrideNames
3464:
3465: /**
3466: *
3467: **/
3468: SymtabEntry searchModuleScope(String name, SymtabEntry container) {
3469: String module = container.fullName();
3470: String fullName = module + '/' + name;
3471: SymtabEntry type = (SymtabEntry) symbolTable.get(fullName);
3472: while ((type == null) && !module.equals("")) {
3473: int index = module.lastIndexOf('/');
3474: if (index < 0)
3475: module = "";
3476: else {
3477: module = module.substring(0, index);
3478: fullName = module + '/' + name;
3479: type = (SymtabEntry) symbolTable.get(fullName);
3480: }
3481: }
3482: return (type == null) ? (SymtabEntry) symbolTable.get(name)
3483: : type;
3484: } // searchModuleScope
3485:
3486: /**
3487: *
3488: **/
3489: SymtabEntry searchDerivedFrom(String name, InterfaceEntry i) {
3490: for (Enumeration e = i.derivedFrom().elements(); e
3491: .hasMoreElements();) {
3492: SymtabEntry tmp = (SymtabEntry) e.nextElement();
3493: if (tmp instanceof InterfaceEntry) {
3494: InterfaceEntry parent = (InterfaceEntry) tmp;
3495: String fullName = parent.fullName() + '/' + name;
3496: SymtabEntry type = (SymtabEntry) symbolTable
3497: .get(fullName);
3498: if (type != null)
3499: return type;
3500: type = searchDerivedFrom(name, parent);
3501: if (type != null)
3502: return type;
3503: }
3504: // else it is a ForwardEntry and nothing can be done at this point.
3505: }
3506: return null;
3507: } // searchDerivedFrom
3508:
3509: /**
3510: *
3511: **/
3512: String entryName(SymtabEntry entry) {
3513: if (entry instanceof AttributeEntry)
3514: return "attribute";
3515: if (entry instanceof ConstEntry)
3516: return "constant";
3517: if (entry instanceof EnumEntry)
3518: return "enumeration";
3519: if (entry instanceof ExceptionEntry)
3520: return "exception";
3521: if (entry instanceof ValueBoxEntry)
3522: return "value box";
3523: if (entry instanceof ForwardValueEntry
3524: || entry instanceof ValueEntry)
3525: return "value";
3526: if (entry instanceof ForwardEntry
3527: || entry instanceof InterfaceEntry)
3528: return "interface";
3529: if (entry instanceof MethodEntry)
3530: return "method";
3531: if (entry instanceof ModuleEntry)
3532: return "module";
3533: if (entry instanceof ParameterEntry)
3534: return "parameter";
3535: if (entry instanceof PrimitiveEntry)
3536: return "primitive";
3537: if (entry instanceof SequenceEntry)
3538: return "sequence";
3539: if (entry instanceof StringEntry)
3540: return "string";
3541: if (entry instanceof StructEntry)
3542: return "struct";
3543: if (entry instanceof TypedefEntry)
3544: return "typedef";
3545: if (entry instanceof UnionEntry)
3546: return "union";
3547: return "void";
3548: } // entryName
3549:
3550: /**
3551: *
3552: **/
3553: private boolean isInterface(SymtabEntry entry) {
3554: return entry instanceof InterfaceEntry
3555: || (entry instanceof ForwardEntry && !(entry instanceof ForwardValueEntry));
3556: }
3557:
3558: private boolean isValue(SymtabEntry entry) {
3559: return entry instanceof ValueEntry; // || entry instanceof ForwardValueEntry;
3560: }
3561:
3562: private boolean isInterfaceOnly(SymtabEntry entry) {
3563: return entry instanceof InterfaceEntry;
3564: }
3565:
3566: private boolean isForward(SymtabEntry entry) {
3567: return entry instanceof ForwardEntry;
3568: }
3569:
3570: // list must be a vector of Strings.
3571: /**
3572: *
3573: **/
3574: private boolean isntInStringList(Vector list, String name) {
3575: boolean isnt = true;
3576: Enumeration e = list.elements();
3577: while (e.hasMoreElements())
3578: if (name.equals((String) e.nextElement())) {
3579: ParseException.alreadyDeclared(scanner, name);
3580: isnt = false;
3581: break;
3582: }
3583: return isnt;
3584: } // isntInStringList
3585:
3586: // list must be a vector of SymtabEntry's.
3587: /**
3588: *
3589: **/
3590: private boolean isntInList(Vector list, String name) {
3591: boolean isnt = true;
3592: for (Enumeration e = list.elements(); e.hasMoreElements();)
3593: if (name.equals(((SymtabEntry) e.nextElement()).name())) {
3594: ParseException.alreadyDeclared(scanner, name);
3595: isnt = false;
3596: break;
3597: }
3598: return isnt;
3599: } // isntInList
3600:
3601: // list must be a vector of SymtabEntry's.
3602: /**
3603: *
3604: **/
3605: private boolean isntInList(Vector list, SymtabEntry entry) {
3606: boolean isnt = true;
3607: for (Enumeration e = list.elements(); e.hasMoreElements();) {
3608: SymtabEntry eEntry = (SymtabEntry) e.nextElement();
3609: if (entry == eEntry) // && entry.fullName().equals (eEntry.fullName()))
3610: {
3611: ParseException.alreadyDeclared(scanner, entry
3612: .fullName());
3613: isnt = false;
3614: break;
3615: }
3616: }
3617: return isnt;
3618: } // isntInList
3619:
3620: /**
3621: *
3622: **/
3623: public static SymtabEntry typeOf(SymtabEntry entry) {
3624: while (entry instanceof TypedefEntry)
3625: entry = entry.type();
3626: return entry;
3627: } // typeOf
3628:
3629: /**
3630: *
3631: **/
3632: void forwardEntryCheck() {
3633: for (Enumeration e = symbolTable.elements(); e
3634: .hasMoreElements();) {
3635: SymtabEntry entry = (SymtabEntry) e.nextElement();
3636: if (entry instanceof ForwardEntry)
3637: ParseException.forwardEntry(scanner, entry.fullName());
3638: }
3639: } // forwardEntryCheck
3640:
3641: // <46082.03> Revert to "IDL:"-style (i.e., regular) repository ID.
3642: /*
3643: void updateRepositoryIds () {
3644: for (Enumeration e = symbolTable.elements(); e.hasMoreElements();) {
3645: SymtabEntry entry = (SymtabEntry) e.nextElement();
3646: if (entry instanceof ValueEntry)
3647: ((ValueEntry) entry).calcRepId();
3648: }
3649: } // updateRepositoryIds
3650: */
3651:
3652: ////////////////////
3653: // Error Handling Methods
3654: // A syntax error occurred. Skip until a semicolon is encountered.
3655: // Ignore semicolons within {...} blocks
3656: /**
3657: *
3658: **/
3659: private void skipToSemicolon() throws IOException {
3660: while (!token.equals(Token.EOF)
3661: && !token.equals(Token.Semicolon)) {
3662: if (token.equals(Token.LeftBrace))
3663: skipToRightBrace();
3664: try {
3665: match(token.type);
3666: } catch (ParseException exception) {
3667: // The error has already been reported...
3668: }
3669: }
3670: if (token.equals(Token.EOF))
3671: throw new EOFException();
3672: try {
3673: match(Token.Semicolon);
3674: } catch (Exception exception) {
3675: }
3676: } // skipToSemicolon
3677:
3678: /**
3679: *
3680: **/
3681: private void skipToRightBrace() throws IOException {
3682: boolean firstTime = true;
3683: while (!token.equals(Token.EOF)
3684: && !token.equals(Token.RightBrace)) {
3685: if (firstTime)
3686: firstTime = false;
3687: else if (token.equals(Token.LeftBrace))
3688: skipToRightBrace();
3689: try {
3690: match(token.type);
3691: } catch (ParseException exception) {
3692: // The error has already been reported...
3693: }
3694: }
3695: if (token.equals(Token.EOF))
3696: throw new EOFException();
3697: } // skipToRightBrace
3698:
3699: // Error Handling Methods
3700: ////////////////////
3701:
3702: // <d56351> In CORBA 2.3, an IDL file provides a new scope for Repository IDs.
3703: // The following methods provide a means for other classes in the framework
3704: // to manage this scoping (see Preprocessor and Scanner).
3705:
3706: // public static int nPush = 0;
3707: // public static int nPop = 0;
3708:
3709: /**
3710: *
3711: **/
3712: public static void enteringInclude() {
3713: repIDStack.push(new IDLID());
3714: } // enteringInclude
3715:
3716: /**
3717: *
3718: **/
3719: public static void exitingInclude() {
3720: repIDStack.pop();
3721: } // exitingInclude
3722:
3723: public static final String unknownNamePrefix = "uN__";
3724:
3725: static Hashtable symbolTable;
3726: Hashtable lcSymbolTable = new Hashtable();
3727: static Hashtable overrideNames;
3728: Vector emitList = new Vector();
3729: boolean emitAll;
3730: // <f46082.46.01>
3731: boolean cppModule;
3732: // <d62023>
3733: boolean noWarn;
3734: Scanner scanner;
3735: // <f46082.40> No longer necessary due to new valueElement() algorithm.
3736: // Stack tokenStack = new Stack();
3737: Hashtable symbols;
3738: Vector macros = new Vector();
3739: Vector paths;
3740:
3741: // Only needed for the pragma directive
3742: SymtabEntry currentModule = null;
3743:
3744: // <d56351> Static field necessary to allow Scanner access to enterind/exiting
3745: // Include() methods. Must reset in Compile class, too!
3746: // Stack repIDStack = new Stack ();
3747: static Stack repIDStack = new Stack();
3748:
3749: // Dynamic variable key used for forward type lists.
3750: // A struct or union X entry may have this attached,
3751: // which always contains a List<SymtabEntry>.
3752: // The elements are entries E such that E.type() == X.
3753: // This list must be resolved in pigeonhole when the
3754: // type is finally defined. This is similar to
3755: // ForwardEntry.replaceForwardDecl.
3756: private static int ftlKey = SymtabEntry.getVariableKey();
3757:
3758: int sequence = 0;
3759: Vector includes;
3760: Vector includeEntries;
3761:
3762: // Only needed in primaryExpr. Set in Preprocessor.booleanConstExpr.
3763: boolean parsingConditionalExpr = false;
3764:
3765: Token token;
3766: ModuleEntry topLevelModule;
3767: private Preprocessor prep;
3768: private boolean verbose;
3769: SymtabFactory stFactory;
3770: ExprFactory exprFactory;
3771: private String[] keywords;
3772: // <f46082.51> Remove -stateful feature.
3773: //private boolean parseStateful = false;
3774:
3775: // Circular buffer containing most recent tokens, including the current token.
3776: private TokenBuffer tokenHistory = new TokenBuffer();
3777: protected float corbaLevel; // <f60858.1>
3778: private Arguments arguments;
3779:
3780: } // class Parser
|