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