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