Preprocessor.java revision 608:7e06bf1dcb09
164562Sgshapiro/*
2261363Sgshapiro * Copyright (c) 1999, 2000, Oracle and/or its affiliates. All rights reserved.
364562Sgshapiro * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
464562Sgshapiro *
564562Sgshapiro * This code is free software; you can redistribute it and/or modify it
664562Sgshapiro * under the terms of the GNU General Public License version 2 only, as
764562Sgshapiro * published by the Free Software Foundation.  Oracle designates this
864562Sgshapiro * particular file as subject to the "Classpath" exception as provided
964562Sgshapiro * by Oracle in the LICENSE file that accompanied this code.
1064562Sgshapiro *
1190792Sgshapiro * This code is distributed in the hope that it will be useful, but WITHOUT
12266692Sgshapiro * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1364562Sgshapiro * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1464562Sgshapiro * version 2 for more details (a copy is included in the LICENSE file that
1564562Sgshapiro * accompanied this code).
1664562Sgshapiro *
1764562Sgshapiro * You should have received a copy of the GNU General Public License version
1864562Sgshapiro * 2 along with this work; if not, write to the Free Software Foundation,
1964562Sgshapiro * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2064562Sgshapiro *
2164562Sgshapiro * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2264562Sgshapiro * or visit www.oracle.com if you need additional information or have any
2364562Sgshapiro * questions.
2464562Sgshapiro */
2564562Sgshapiro/*
2664562Sgshapiro * COMPONENT_NAME: idl.parser
2764562Sgshapiro *
2864562Sgshapiro * ORIGINS: 27
2964562Sgshapiro *
3064562Sgshapiro * Licensed Materials - Property of IBM
3164562Sgshapiro * 5639-D57 (C) COPYRIGHT International Business Machines Corp. 1997, 1999
3264562Sgshapiro * RMI-IIOP v1.0
3364562Sgshapiro *
3464562Sgshapiro */
3564562Sgshapiro
3664562Sgshapiropackage com.sun.tools.corba.se.idl;
3764562Sgshapiro
3864562Sgshapiro// NOTES:
3964562Sgshapiro// -D57110<daz> Allow ID pragma directive to be applied to modules and update
4064562Sgshapiro//  feature in accordance to CORBA 2.3.
4164562Sgshapiro// -D59165<daz> Enable escaped identifiers when processing pragmas.
4264562Sgshapiro// -f60858.1<daz> Support -corba option, level = 2.2: Accept identifiers that
4364562Sgshapiro//  collide with keywords, in letter but not case, and issue a warning.
4464562Sgshapiro// -d62023 <daz> support -noWarn option; suppress inappropriate warnings when
4564562Sgshapiro//  parsing IBM-specific pragmas (#meta <interface_name> abstract).
4664562Sgshapiro
4764562Sgshapiroimport java.io.File;
4864562Sgshapiroimport java.io.FileNotFoundException;
4964562Sgshapiroimport java.io.IOException;
5064562Sgshapiroimport java.math.BigInteger;
5164562Sgshapiroimport java.util.Enumeration;
5264562Sgshapiroimport java.util.Hashtable;
5364562Sgshapiroimport java.util.Stack;
5464562Sgshapiroimport java.util.Vector;
5564562Sgshapiro
5664562Sgshapiroimport com.sun.tools.corba.se.idl.RepositoryID;
5764562Sgshapiro
5864562Sgshapiroimport com.sun.tools.corba.se.idl.constExpr.*;
59168515Sgshapiro
6064562Sgshapiro/**
6164562Sgshapiro * This class should be extended if new pragmas are desired.  If the
62125820Sgshapiro * preprocessor encounters a pragma name which it doesn't recognize
63125820Sgshapiro * (anything other than ID, prefix, or version), it calls the method
64125820Sgshapiro * otherPragmas.  This is the only method which need be overridden.
65125820Sgshapiro * The Preprocessor base class has a number of utility-like methods
66125820Sgshapiro * which can be used by the overridden otherPragmas method.
67168515Sgshapiro **/
68168515Sgshapiropublic class Preprocessor
69168515Sgshapiro{
70168515Sgshapiro  /**
71168515Sgshapiro   * Public zero-argument constructor.
72168515Sgshapiro   **/
73132943Sgshapiro  Preprocessor ()
74168515Sgshapiro  {
75168515Sgshapiro  } // ctor
76168515Sgshapiro
77168515Sgshapiro  /**
78168515Sgshapiro   *
79168515Sgshapiro   **/
80168515Sgshapiro  void init (Parser p)
81168515Sgshapiro  {
82168515Sgshapiro    parser  = p;
83168515Sgshapiro    symbols = p.symbols;
84168515Sgshapiro    macros  = p.macros;
85168515Sgshapiro  } // init
86168515Sgshapiro
87168515Sgshapiro  /**
88168515Sgshapiro   *
89168515Sgshapiro   **/
90168515Sgshapiro  protected Object clone ()
91168515Sgshapiro  {
92168515Sgshapiro    return new Preprocessor ();
93168515Sgshapiro  } // clone
94168515Sgshapiro
9564562Sgshapiro  /**
9664562Sgshapiro   *
9764562Sgshapiro   **/
9864562Sgshapiro  Token process (Token t) throws IOException, ParseException
9964562Sgshapiro  {
10064562Sgshapiro    token   = t;
10164562Sgshapiro    scanner = parser.scanner;
10264562Sgshapiro    // <f46082.40> Deactivate escaped identifier processing in Scanner while
10364562Sgshapiro    // preprocessing.
10464562Sgshapiro    //scanner.underscoreOK = true;
10564562Sgshapiro    scanner.escapedOK = false;
10664562Sgshapiro    try
107132943Sgshapiro    {
108132943Sgshapiro      switch (token.type)
10964562Sgshapiro      {
11064562Sgshapiro        case Token.Include:
11164562Sgshapiro          include ();
11264562Sgshapiro          break;
11364562Sgshapiro        case Token.If:
11464562Sgshapiro          ifClause ();
11564562Sgshapiro          break;
116203004Sgshapiro        case Token.Ifdef:
11764562Sgshapiro          ifdef (false);
118168515Sgshapiro          break;
119168515Sgshapiro        case Token.Ifndef:
120168515Sgshapiro          ifdef (true);
121168515Sgshapiro          break;
12264562Sgshapiro        case Token.Else:
12364562Sgshapiro          if (alreadyProcessedABranch.empty ())
12464562Sgshapiro            throw ParseException.elseNoIf (scanner);
12564562Sgshapiro          else if (((Boolean)alreadyProcessedABranch.peek ()).booleanValue ())
12664562Sgshapiro            skipToEndif ();
12764562Sgshapiro          else
12864562Sgshapiro          {
12964562Sgshapiro            alreadyProcessedABranch.pop ();
130132943Sgshapiro            alreadyProcessedABranch.push (new Boolean (true));
131132943Sgshapiro            token = scanner.getToken ();
132132943Sgshapiro          }
133132943Sgshapiro          break;
134132943Sgshapiro        case Token.Elif:
135132943Sgshapiro          elif ();
136132943Sgshapiro          break;
137132943Sgshapiro        case Token.Endif:
138168515Sgshapiro          if (alreadyProcessedABranch.empty ())
139168515Sgshapiro            throw ParseException.endNoIf (scanner);
140168515Sgshapiro          else
14164562Sgshapiro          {
14264562Sgshapiro            alreadyProcessedABranch.pop ();
14364562Sgshapiro            token = scanner.getToken ();
14464562Sgshapiro            break;
14564562Sgshapiro          }
14664562Sgshapiro        case Token.Define:
14764562Sgshapiro          define ();
14864562Sgshapiro          break;
14964562Sgshapiro        case Token.Undef:
15064562Sgshapiro          undefine ();
15164562Sgshapiro          break;
15264562Sgshapiro        case Token.Pragma:
15390792Sgshapiro          pragma ();
154110560Sgshapiro          break;
155110560Sgshapiro        case Token.Unknown:
156132943Sgshapiro          if (!parser.noWarn)
157132943Sgshapiro            ParseException.warning (scanner, Util.getMessage ("Preprocessor.unknown", token.name));
158132943Sgshapiro        case Token.Error:
159132943Sgshapiro        case Token.Line:
160132943Sgshapiro        case Token.Null:
161110560Sgshapiro          // ignore
162132943Sgshapiro        default:
163132943Sgshapiro          scanner.skipLineComment ();
164110560Sgshapiro          token = scanner.getToken ();
165110560Sgshapiro      }
166110560Sgshapiro    }
167168515Sgshapiro    catch (IOException e)
168168515Sgshapiro    {
16964562Sgshapiro      // <f46082.40> Underscore may now precede any identifier, so underscoreOK
17064562Sgshapiro      // is vestigal.  The Preprocessor must reset escapedOK so that Scanner
171132943Sgshapiro      // will process escaped identifiers according to specification.
172132943Sgshapiro      //scanner.underscoreOK = false;
173132943Sgshapiro      scanner.escapedOK = true;
174132943Sgshapiro      throw e;
175168515Sgshapiro    }
176168515Sgshapiro    catch (ParseException e)
177110560Sgshapiro    {
17864562Sgshapiro      // <f46082.40> See above.
17964562Sgshapiro      //scanner.underscoreOK = false;
18064562Sgshapiro      scanner.escapedOK = true;
181168515Sgshapiro      throw e;
182168515Sgshapiro    }
183168515Sgshapiro    // <f46082.40> See above.
184168515Sgshapiro    //scanner.underscoreOK = false;
185168515Sgshapiro    scanner.escapedOK = true;
186168515Sgshapiro    return token;
187168515Sgshapiro  } // process
188168515Sgshapiro
189168515Sgshapiro  /**
190168515Sgshapiro   *
191168515Sgshapiro   **/
192168515Sgshapiro  private void include () throws IOException, ParseException
193168515Sgshapiro  {
194168515Sgshapiro    match (Token.Include);
195168515Sgshapiro    IncludeEntry include = parser.stFactory.includeEntry (parser.currentModule);
19664562Sgshapiro    include.sourceFile (scanner.fileEntry ());
19764562Sgshapiro    scanner.fileEntry ().addInclude (include);
198159609Sgshapiro    if (token.type == Token.StringLiteral)
199159609Sgshapiro      include2 (include);
20064562Sgshapiro    else if (token.type == Token.LessThan)
20164562Sgshapiro      include3 (include);
20264562Sgshapiro    else
203168515Sgshapiro    {
204168515Sgshapiro      int[] expected = {Token.StringLiteral, Token.LessThan};
205168515Sgshapiro      throw ParseException.syntaxError (scanner, expected, token.type);
206168515Sgshapiro    }
207168515Sgshapiro    if (parser.currentModule instanceof ModuleEntry)
208168515Sgshapiro      ((ModuleEntry)parser.currentModule).addContained (include);
209168515Sgshapiro    else if (parser.currentModule instanceof InterfaceEntry)
210168515Sgshapiro      ((InterfaceEntry)parser.currentModule).addContained (include);
211168515Sgshapiro  } // include
212168515Sgshapiro
213168515Sgshapiro  /**
214168515Sgshapiro   *
215168515Sgshapiro   **/
216168515Sgshapiro  private void include2 (IncludeEntry include) throws IOException, ParseException
217168515Sgshapiro  {
21864562Sgshapiro    include.name ('"' + token.name + '"');
21964562Sgshapiro    include4 (include, token.name);
220168515Sgshapiro    match (Token.StringLiteral);
221168515Sgshapiro  } // include2
222168515Sgshapiro
223168515Sgshapiro  /**
224168515Sgshapiro   *
22564562Sgshapiro   **/
22664562Sgshapiro  private void include3 (IncludeEntry include) throws IOException, ParseException
22764562Sgshapiro  {
228168515Sgshapiro    if (token.type != Token.LessThan)
22964562Sgshapiro      // match will throw an exception
23090792Sgshapiro      match (Token.LessThan);
23164562Sgshapiro    else
23290792Sgshapiro    {
23364562Sgshapiro      try
23464562Sgshapiro      {
23564562Sgshapiro        String includeFile = getUntil ('>');
23664562Sgshapiro        token = scanner.getToken ();
23764562Sgshapiro        include.name ('<' + includeFile + '>');
23864562Sgshapiro        include4 (include, includeFile);
23964562Sgshapiro        match (Token.GreaterThan);
24064562Sgshapiro      }
241168515Sgshapiro      catch (IOException e)
24264562Sgshapiro      {
24364562Sgshapiro        throw ParseException.syntaxError (scanner, ">", "EOF");
24464562Sgshapiro      }
24564562Sgshapiro    }
24664562Sgshapiro  } // include3
24764562Sgshapiro
24864562Sgshapiro  /**
24964562Sgshapiro   *
25064562Sgshapiro   **/
25164562Sgshapiro  private void include4 (IncludeEntry include, String filename) throws IOException, ParseException
25264562Sgshapiro  {
25364562Sgshapiro    try
25464562Sgshapiro    {
25564562Sgshapiro      // If the #include is at the global scope, it is treated as
25664562Sgshapiro      // an import statement.  If it is within some other scope, it
25764562Sgshapiro      // is treated as a normal #include.
25864562Sgshapiro      boolean includeIsImport = parser.currentModule == parser.topLevelModule;
25964562Sgshapiro      //daz
26064562Sgshapiro      include.absFilename (Util.getAbsolutePath (filename, parser.paths));
26164562Sgshapiro      scanner.scanIncludedFile (include, getFilename (filename), includeIsImport);
26264562Sgshapiro    }
26364562Sgshapiro    catch (IOException e)
26464562Sgshapiro    {
26564562Sgshapiro      ParseException.generic (scanner, e.toString ());
266168515Sgshapiro    }
267168515Sgshapiro  } // include4
268168515Sgshapiro
269168515Sgshapiro  /**
270168515Sgshapiro   *
271168515Sgshapiro   **/
272168515Sgshapiro  private void define () throws IOException, ParseException
273168515Sgshapiro  {
27464562Sgshapiro    match (Token.Define);
27564562Sgshapiro    if (token.equals (Token.Identifier))
276168515Sgshapiro    {
27790792Sgshapiro      String symbol = scanner.getStringToEOL ();
27866494Sgshapiro      symbols.put (token.name, symbol.trim ());
27966494Sgshapiro      match (Token.Identifier);
28064562Sgshapiro    }
28164562Sgshapiro    else if (token.equals (Token.MacroIdentifier))
28264562Sgshapiro    {
28364562Sgshapiro      symbols.put (token.name, '(' + scanner.getStringToEOL () . trim ());
28464562Sgshapiro      macros.addElement (token.name);
28564562Sgshapiro      match (Token.MacroIdentifier);
28664562Sgshapiro    }
287223067Sgshapiro    else
288168515Sgshapiro      throw ParseException.syntaxError (scanner, Token.Identifier, token.type);
28964562Sgshapiro  } // define
29064562Sgshapiro
29164562Sgshapiro  /**
29290792Sgshapiro   *
29390792Sgshapiro   **/
29490792Sgshapiro  private void undefine () throws IOException, ParseException
29590792Sgshapiro  {
29690792Sgshapiro    match (Token.Undef);
29790792Sgshapiro    if (token.equals (Token.Identifier))
29890792Sgshapiro    {
29990792Sgshapiro      symbols.remove (token.name);
30090792Sgshapiro      macros.removeElement (token.name);
30190792Sgshapiro      match (Token.Identifier);
30290792Sgshapiro    }
303168515Sgshapiro    else
304168515Sgshapiro      throw ParseException.syntaxError (scanner, Token.Identifier, token.type);
305168515Sgshapiro  } // undefine
306168515Sgshapiro
307168515Sgshapiro  /**
308168515Sgshapiro   *
309168515Sgshapiro   **/
310168515Sgshapiro  private void ifClause () throws IOException, ParseException
311168515Sgshapiro  {
31290792Sgshapiro    match (Token.If);
31364562Sgshapiro    constExpr ();
31464562Sgshapiro  } // ifClause
31564562Sgshapiro
31664562Sgshapiro  /**
31764562Sgshapiro   *
318223067Sgshapiro   **/
319168515Sgshapiro  private void constExpr () throws IOException, ParseException
32064562Sgshapiro  {
32164562Sgshapiro    SymtabEntry dummyEntry = new SymtabEntry (parser.currentModule);
32264562Sgshapiro    dummyEntry.container (parser.currentModule);
32364562Sgshapiro    parser.parsingConditionalExpr = true;
32464562Sgshapiro    Expression boolExpr = booleanConstExpr (dummyEntry);
32564562Sgshapiro    parser.parsingConditionalExpr = false;
32664562Sgshapiro    boolean expr;
32764562Sgshapiro    if (boolExpr.value () instanceof Boolean)
32864562Sgshapiro      expr = ((Boolean)boolExpr.value ()).booleanValue ();
32964562Sgshapiro    else
33064562Sgshapiro      expr = ((Number)boolExpr.value ()).longValue () != 0;
331223067Sgshapiro    alreadyProcessedABranch.push (new Boolean (expr));
332168515Sgshapiro    if (!expr)
33364562Sgshapiro      skipToEndiforElse ();
33464562Sgshapiro  } // constExpr
33564562Sgshapiro
33664562Sgshapiro  /**
33764562Sgshapiro   *
33864562Sgshapiro   **/
33964562Sgshapiro  Expression booleanConstExpr (SymtabEntry entry) throws IOException, ParseException
34064562Sgshapiro  {
34164562Sgshapiro    Expression expr = orExpr (null, entry);
342223067Sgshapiro    try
343168515Sgshapiro    {
34464562Sgshapiro      expr.evaluate ();
34564562Sgshapiro    }
34664562Sgshapiro    catch (EvaluationException e)
34764562Sgshapiro    {
34864562Sgshapiro      ParseException.evaluationError (scanner, e.toString ());
34964562Sgshapiro    }
35064562Sgshapiro    return expr;
351223067Sgshapiro  } // booleanConstExpr
352168515Sgshapiro
35364562Sgshapiro  /**
35464562Sgshapiro   *
35564562Sgshapiro   **/
35664562Sgshapiro  private Expression orExpr (Expression e, SymtabEntry entry) throws IOException, ParseException
35764562Sgshapiro  {
35864562Sgshapiro    if (e == null)
35964562Sgshapiro      e = andExpr (null, entry);
360223067Sgshapiro    else
361168515Sgshapiro    {
36264562Sgshapiro      BinaryExpr b = (BinaryExpr)e;
36364562Sgshapiro      b.right (andExpr (null, entry));
36464562Sgshapiro      e.rep (e.rep () + b.right ().rep ());
36564562Sgshapiro    }
36664562Sgshapiro    if (token.equals (Token.DoubleBar))
367223067Sgshapiro    {
368168515Sgshapiro      match (token.type);
369110560Sgshapiro      BooleanOr or = parser.exprFactory.booleanOr (e, null);
370110560Sgshapiro      or.rep (e.rep () + " || ");
37164562Sgshapiro      return orExpr (or, entry);
37264562Sgshapiro    }
37364562Sgshapiro    else
37464562Sgshapiro      return e;
37564562Sgshapiro  } // orExpr
37664562Sgshapiro
37764562Sgshapiro  /**
37864562Sgshapiro   *
37964562Sgshapiro   **/
38064562Sgshapiro  private Expression andExpr (Expression e, SymtabEntry entry) throws IOException, ParseException
38164562Sgshapiro  {
38264562Sgshapiro    if (e == null)
38364562Sgshapiro      e = notExpr (entry);
38490792Sgshapiro    else
385102528Sgshapiro    {
386102528Sgshapiro      BinaryExpr b = (BinaryExpr)e;
387102528Sgshapiro      b.right (notExpr (entry));
388102528Sgshapiro      e.rep (e.rep () + b.right ().rep ());
389102528Sgshapiro    }
39064562Sgshapiro    if (token.equals (Token.DoubleAmpersand))
39190792Sgshapiro    {
39264562Sgshapiro      match (token.type);
39364562Sgshapiro      BooleanAnd and = parser.exprFactory.booleanAnd (e, null);
39464562Sgshapiro      and.rep (e.rep () + " && ");
39564562Sgshapiro      return andExpr (and, entry);
39664562Sgshapiro    }
39764562Sgshapiro    else
39864562Sgshapiro      return e;
39964562Sgshapiro  } // andExpr
40064562Sgshapiro
401141858Sgshapiro  /**
40264562Sgshapiro   *
40364562Sgshapiro   **/
404168515Sgshapiro  private Expression notExpr (/*boolean alreadySawExclamation, */SymtabEntry entry) throws IOException, ParseException
40564562Sgshapiro  {
406168515Sgshapiro    Expression e;
40764562Sgshapiro    if (token.equals (Token.Exclamation))
40864562Sgshapiro    {
40964562Sgshapiro      match (Token.Exclamation);
41064562Sgshapiro      e = parser.exprFactory.booleanNot (definedExpr (entry));
41164562Sgshapiro      e.rep ("!" + ((BooleanNot)e).operand ().rep ());
41264562Sgshapiro    }
41364562Sgshapiro    else
41464562Sgshapiro      e = definedExpr (entry);
41564562Sgshapiro    return e;
41664562Sgshapiro  } // notExpr
41764562Sgshapiro
41864562Sgshapiro  /**
41964562Sgshapiro   *
42064562Sgshapiro   **/
42164562Sgshapiro  private Expression definedExpr (SymtabEntry entry) throws IOException, ParseException
42264562Sgshapiro  {
42364562Sgshapiro    if (token.equals (Token.Identifier) && token.name.equals ("defined"))
42464562Sgshapiro      match (Token.Identifier);
42564562Sgshapiro    return equalityExpr (null, entry);
42664562Sgshapiro  } // definedExpr
42764562Sgshapiro
42864562Sgshapiro  /**
42964562Sgshapiro   *
43064562Sgshapiro   **/
43164562Sgshapiro  private Expression equalityExpr (Expression e, SymtabEntry entry) throws IOException, ParseException
43264562Sgshapiro  {
43364562Sgshapiro    if (e == null)
43464562Sgshapiro    {
43564562Sgshapiro      parser.token = token; // Since parser to parse, give it this token
43664562Sgshapiro      e = parser.constExp (entry);
437223067Sgshapiro      token = parser.token; // Since parser last parsed, get its token
438168515Sgshapiro    }
43964562Sgshapiro    else
44064562Sgshapiro    {
44164562Sgshapiro      BinaryExpr b = (BinaryExpr)e;
44264562Sgshapiro      parser.token = token; // Since parser to parse, give it this token
44364562Sgshapiro      Expression constExpr = parser.constExp (entry);
444168515Sgshapiro      token = parser.token; // Since parser last parsed, get its token
445168515Sgshapiro      b.right (constExpr);
446168515Sgshapiro      e.rep (e.rep () + b.right ().rep ());
44764562Sgshapiro    }
44864562Sgshapiro    if (token.equals (Token.DoubleEqual))
44964562Sgshapiro    {
45064562Sgshapiro      match (token.type);
45164562Sgshapiro      Equal eq = parser.exprFactory.equal (e, null);
45264562Sgshapiro      eq.rep (e.rep () + " == ");
453168515Sgshapiro      return equalityExpr (eq, entry);
454168515Sgshapiro    }
455168515Sgshapiro    else if (token.equals (Token.NotEqual))
456168515Sgshapiro    {
457168515Sgshapiro      match (token.type);
458168515Sgshapiro      NotEqual n = parser.exprFactory.notEqual (e, null);
459168515Sgshapiro      n.rep (e.rep () + " != ");
460168515Sgshapiro      return equalityExpr (n, entry);
461168515Sgshapiro    }
462168515Sgshapiro    else if (token.equals (Token.GreaterThan))
46390792Sgshapiro    {
46464562Sgshapiro      match (token.type);
465168515Sgshapiro      GreaterThan g = parser.exprFactory.greaterThan (e, null);
46664562Sgshapiro      g.rep (e.rep () + " > ");
467168515Sgshapiro      return equalityExpr (g, entry);
46864562Sgshapiro    }
46964562Sgshapiro    else if (token.equals (Token.GreaterEqual))
470168515Sgshapiro    {
471168515Sgshapiro      match (token.type);
472168515Sgshapiro      GreaterEqual g = parser.exprFactory.greaterEqual (e, null);
473168515Sgshapiro      g.rep (e.rep () + " >= ");
474168515Sgshapiro      return equalityExpr (g, entry);
475168515Sgshapiro    }
476168515Sgshapiro    else if (token.equals (Token.LessThan))
477168515Sgshapiro    {
478168515Sgshapiro      match (token.type);
479168515Sgshapiro      LessThan l = parser.exprFactory.lessThan (e, null);
480168515Sgshapiro      l.rep (e.rep () + " < ");
481168515Sgshapiro      return equalityExpr (l, entry);
482168515Sgshapiro    }
483168515Sgshapiro    else if (token.equals (Token.LessEqual))
484168515Sgshapiro    {
485168515Sgshapiro      match (token.type);
486168515Sgshapiro      LessEqual l = parser.exprFactory.lessEqual (e, null);
487168515Sgshapiro      l.rep (e.rep () + " <= ");
488168515Sgshapiro      return equalityExpr (l, entry);
489168515Sgshapiro    }
490168515Sgshapiro    else
491168515Sgshapiro      return e;
492168515Sgshapiro  } // equalityExpr
493168515Sgshapiro
494168515Sgshapiro  /**
495168515Sgshapiro   *
496168515Sgshapiro   **/
497168515Sgshapiro  Expression primaryExpr (SymtabEntry entry) throws IOException, ParseException
498168515Sgshapiro  {
499168515Sgshapiro    Expression primary = null;
500168515Sgshapiro    switch (token.type)
501168515Sgshapiro    {
502168515Sgshapiro      case Token.Identifier:
503168515Sgshapiro        // If an identifier gets this far, it means that no
504168515Sgshapiro        // preprocessor variable was defined with that name.
505168515Sgshapiro        // Generate a FALSE boolean expr.
506168515Sgshapiro        //daz        primary = parser.exprFactory.terminal ("0", new Long (0));
507168515Sgshapiro        primary = parser.exprFactory.terminal ("0", BigInteger.valueOf (0));
508168515Sgshapiro        token = scanner.getToken ();
509168515Sgshapiro        break;
510168515Sgshapiro      case Token.BooleanLiteral:
511168515Sgshapiro      case Token.CharacterLiteral:
512168515Sgshapiro      case Token.IntegerLiteral:
513168515Sgshapiro      case Token.FloatingPointLiteral:
514168515Sgshapiro      case Token.StringLiteral:
515168515Sgshapiro        //daz        primary = parser.literal ();
516168515Sgshapiro        primary = parser.literal (entry);
517168515Sgshapiro        token = parser.token;
518168515Sgshapiro        break;
519168515Sgshapiro      case Token.LeftParen:
520168515Sgshapiro        match (Token.LeftParen);
521168515Sgshapiro        primary = booleanConstExpr (entry);
522168515Sgshapiro        match (Token.RightParen);
523168515Sgshapiro        primary.rep ('(' + primary.rep () + ')');
524168515Sgshapiro        break;
525168515Sgshapiro      default:
526168515Sgshapiro        int[] expected = {Token.Literal, Token.LeftParen};
527168515Sgshapiro        throw ParseException.syntaxError (scanner, expected, token.type);
528168515Sgshapiro    }
529168515Sgshapiro    return primary;
530168515Sgshapiro  } // primaryExpr
531168515Sgshapiro
532168515Sgshapiro  /**
533168515Sgshapiro   *
534168515Sgshapiro   **/
535168515Sgshapiro  private void ifDefine (boolean inParens, boolean not) throws IOException, ParseException
536168515Sgshapiro  {
537168515Sgshapiro    if (token.equals (Token.Identifier))
538168515Sgshapiro      if ((not && symbols.containsKey (token.name)) || (!not && !symbols.containsKey (token.name)))
539168515Sgshapiro      {
54090792Sgshapiro        alreadyProcessedABranch.push (new Boolean (false));
541168515Sgshapiro        skipToEndiforElse ();
542168515Sgshapiro      }
543168515Sgshapiro      else
544168515Sgshapiro      {
545168515Sgshapiro        alreadyProcessedABranch.push (new Boolean (true));
546168515Sgshapiro        match (Token.Identifier);
547168515Sgshapiro        if (inParens)
548168515Sgshapiro          match (Token.RightParen);
549168515Sgshapiro      }
550168515Sgshapiro    else
551168515Sgshapiro      throw ParseException.syntaxError (scanner, Token.Identifier, token.type);
552168515Sgshapiro  } // ifDefine
553168515Sgshapiro
554168515Sgshapiro  /**
555168515Sgshapiro   *
556168515Sgshapiro   **/
557168515Sgshapiro  private void ifdef (boolean not) throws IOException, ParseException
558168515Sgshapiro  {
559168515Sgshapiro    if (not)
560168515Sgshapiro      match (Token.Ifndef);
561168515Sgshapiro    else
562168515Sgshapiro      match (Token.Ifdef);
563168515Sgshapiro    if (token.equals (Token.Identifier))
564168515Sgshapiro      if ((not && symbols.containsKey (token.name)) || (!not && !symbols.containsKey (token.name)))
565168515Sgshapiro      {
566168515Sgshapiro        alreadyProcessedABranch.push (new Boolean (false));
567168515Sgshapiro        skipToEndiforElse ();
568168515Sgshapiro      }
569168515Sgshapiro      else
570168515Sgshapiro      {
571168515Sgshapiro        alreadyProcessedABranch.push (new Boolean (true));
572168515Sgshapiro        match (Token.Identifier);
573168515Sgshapiro      }
574168515Sgshapiro    else
575168515Sgshapiro      throw ParseException.syntaxError (scanner, Token.Identifier, token.type);
576168515Sgshapiro  } // ifdef
577168515Sgshapiro
578168515Sgshapiro  /**
579168515Sgshapiro   *
580168515Sgshapiro   **/
581168515Sgshapiro  private void elif () throws IOException, ParseException
582168515Sgshapiro  {
583168515Sgshapiro    if (alreadyProcessedABranch.empty ())
584168515Sgshapiro      throw ParseException.elseNoIf (scanner);
585168515Sgshapiro    else if (((Boolean)alreadyProcessedABranch.peek ()).booleanValue ())
586168515Sgshapiro      skipToEndif ();
587168515Sgshapiro    else
588168515Sgshapiro    {
589168515Sgshapiro      match (Token.Elif);
590168515Sgshapiro      constExpr ();
591168515Sgshapiro    }
592168515Sgshapiro  } // elif
593168515Sgshapiro
594168515Sgshapiro  /**
595168515Sgshapiro   *
59664562Sgshapiro   **/
59764562Sgshapiro  private void skipToEndiforElse () throws IOException, ParseException
59864562Sgshapiro  {
59964562Sgshapiro    while (!token.equals (Token.Endif) && !token.equals (Token.Else) && !token.equals (Token.Elif))
60064562Sgshapiro    {
60164562Sgshapiro      if (token.equals (Token.Ifdef) || token.equals (Token.Ifndef))
60264562Sgshapiro      {
60364562Sgshapiro        alreadyProcessedABranch.push (new Boolean (true));
60464562Sgshapiro        skipToEndif ();
60564562Sgshapiro      }
60664562Sgshapiro      else
60764562Sgshapiro        token = scanner.skipUntil ('#');
60864562Sgshapiro    }
60964562Sgshapiro    process (token);
61064562Sgshapiro  } // skipToEndiforElse
61164562Sgshapiro
61264562Sgshapiro  /**
61364562Sgshapiro   *
61464562Sgshapiro   **/
615168515Sgshapiro  private void skipToEndif () throws IOException, ParseException
616168515Sgshapiro  {
61764562Sgshapiro    while (!token.equals (Token.Endif))
618168515Sgshapiro    {
619168515Sgshapiro      token = scanner.skipUntil ('#');
620168515Sgshapiro      if (token.equals (Token.Ifdef) || token.equals (Token.Ifndef))
621168515Sgshapiro      {
622168515Sgshapiro        alreadyProcessedABranch.push (new Boolean (true));
623168515Sgshapiro        skipToEndif ();
624168515Sgshapiro      }
625168515Sgshapiro    }
626168515Sgshapiro    alreadyProcessedABranch.pop ();
627168515Sgshapiro    match (Token.Endif);
628168515Sgshapiro  } // skipToEndif
629168515Sgshapiro
630168515Sgshapiro  ///////////////
631168515Sgshapiro  // For Pragma
632168515Sgshapiro
633168515Sgshapiro  /**
634168515Sgshapiro   *
635168515Sgshapiro   **/
636168515Sgshapiro  private void pragma () throws IOException, ParseException
637168515Sgshapiro  {
638168515Sgshapiro    match (Token.Pragma);
639168515Sgshapiro    String pragmaType = token.name;
640168515Sgshapiro
641168515Sgshapiro    // <d59165> Enable escaped identifiers while processing pragma internals.
642168515Sgshapiro    // Don't enable until scanning pragma name!
643168515Sgshapiro    scanner.escapedOK = true;
644168515Sgshapiro    match (Token.Identifier);
645168515Sgshapiro
646168515Sgshapiro    // Add pragma entry to container
647168515Sgshapiro    PragmaEntry pragmaEntry = parser.stFactory.pragmaEntry (parser.currentModule);
648168515Sgshapiro    pragmaEntry.name (pragmaType);
649168515Sgshapiro    pragmaEntry.sourceFile (scanner.fileEntry ());
650168515Sgshapiro    pragmaEntry.data (scanner.currentLine ());
651168515Sgshapiro    if (parser.currentModule instanceof ModuleEntry)
65271345Sgshapiro      ((ModuleEntry)parser.currentModule).addContained (pragmaEntry);
65364562Sgshapiro    else if (parser.currentModule instanceof InterfaceEntry)
65464562Sgshapiro      ((InterfaceEntry)parser.currentModule).addContained (pragmaEntry);
65564562Sgshapiro
65664562Sgshapiro    // If the token was an identifier, then pragmaType WILL be non-null.
65764562Sgshapiro    if (pragmaType.equals ("ID"))
65864562Sgshapiro      idPragma ();
65994334Sgshapiro    else if (pragmaType.equals ("prefix"))
66094334Sgshapiro      prefixPragma ();
66194334Sgshapiro    else if (pragmaType.equals ("version"))
66264562Sgshapiro      versionPragma ();
66364562Sgshapiro
66464562Sgshapiro    // we are adding extensions to the Sun's idlj compiler to
66564562Sgshapiro    // handle correct code generation for local Objects, where
66664562Sgshapiro    // the OMG is taking a long time to formalize stuff.  Good
66764562Sgshapiro    // example of this is poa.idl.  Two proprietory pragmas
66864562Sgshapiro    // sun_local and sun_localservant are defined.  sun_local
66964562Sgshapiro    // generates only Holder and Helper classes, where read
67064562Sgshapiro    // and write methods throw marshal exceptions.  sun_localservant
67164562Sgshapiro    // is to generate Helper, Holder, and only Skel with _invoke
67264562Sgshapiro    // throwing an exception, since it does not make sense for
67364562Sgshapiro    // local objects.
67464562Sgshapiro
67564562Sgshapiro    else if (pragmaType.equals ("sun_local"))
67664562Sgshapiro      localPragma();
67764562Sgshapiro    else if (pragmaType.equals ("sun_localservant"))
67864562Sgshapiro      localServantPragma();
67964562Sgshapiro    else
68064562Sgshapiro    {
681168515Sgshapiro      otherPragmas (pragmaType, tokenToString ());
682168515Sgshapiro      token = scanner.getToken ();
683168515Sgshapiro    }
68464562Sgshapiro
68564562Sgshapiro    scanner.escapedOK = false; // <d59165> Disable escaped identifiers.
686168515Sgshapiro  } // pragma
687168515Sgshapiro
688168515Sgshapiro  // <d57110> Pragma ID can be appiled to modules and it is an error to
68964562Sgshapiro  // name a type in more than one ID pragma directive.
69064562Sgshapiro
691168515Sgshapiro  private Vector PragmaIDs = new Vector ();
692168515Sgshapiro
693168515Sgshapiro  private void localPragma () throws IOException, ParseException
694168515Sgshapiro  {
69564562Sgshapiro    // Before I can use a parser method, I must make sure it has the current token.
69664562Sgshapiro    parser.token = token;
697168515Sgshapiro    // this makes sense only for interfaces, if specified for modules,
698168515Sgshapiro    // parser should throw an error
699168515Sgshapiro    SymtabEntry anErrorOccurred = new SymtabEntry ();
700168515Sgshapiro    SymtabEntry entry = parser.scopedName (parser.currentModule, anErrorOccurred);
701168515Sgshapiro    // Was the indicated type found in the symbol table?
702168515Sgshapiro    if (entry == anErrorOccurred)
703168515Sgshapiro    {
704168515Sgshapiro        System.out.println("Error occured ");
705168515Sgshapiro      // Don't have to generate an error, scopedName already has.
70664562Sgshapiro      scanner.skipLineComment ();
70764562Sgshapiro      token = scanner.getToken ();
708168515Sgshapiro    }
709168515Sgshapiro    else
710168515Sgshapiro    {
711168515Sgshapiro      // by this time we have already parsed the ModuleName and the
712168515Sgshapiro      // pragma type, therefore setInterfaceType
713168515Sgshapiro      if (entry instanceof InterfaceEntry) {
714168515Sgshapiro          InterfaceEntry ent = (InterfaceEntry) entry;
715168515Sgshapiro          ent.setInterfaceType (InterfaceEntry.LOCAL_SIGNATURE_ONLY);
716168515Sgshapiro      }
717168515Sgshapiro      token = parser.token;
718168515Sgshapiro      String string = token.name;
719168515Sgshapiro      match (Token.StringLiteral);
720168515Sgshapiro      // for non-interfaces it doesn't make sense, so just ignore it
721168515Sgshapiro    }
72264562Sgshapiro  } // localPragma
72364562Sgshapiro
72464562Sgshapiro  private void localServantPragma () throws IOException, ParseException
72564562Sgshapiro  {
72664562Sgshapiro    // Before I can use a parser method, I must make sure it has the current token.
72764562Sgshapiro    parser.token = token;
72864562Sgshapiro    // this makes sense only for interfaces, if specified for modules,
72964562Sgshapiro    // parser should throw an error
73064562Sgshapiro    SymtabEntry anErrorOccurred = new SymtabEntry ();
73164562Sgshapiro    SymtabEntry entry = parser.scopedName (parser.currentModule, anErrorOccurred);
73264562Sgshapiro
73364562Sgshapiro    // Was the indicated type found in the symbol table?
73464562Sgshapiro    if (entry == anErrorOccurred)
73564562Sgshapiro    {
73664562Sgshapiro      // Don't have to generate an error, scopedName already has.
73764562Sgshapiro      scanner.skipLineComment ();
738168515Sgshapiro      token = scanner.getToken ();
73964562Sgshapiro        System.out.println("Error occured ");
74064562Sgshapiro    }
74164562Sgshapiro    else
74264562Sgshapiro    {
74364562Sgshapiro      // by this time we have already parsed the ModuleName and the
74464562Sgshapiro      // pragma type, therefore setInterfaceType
74564562Sgshapiro      if (entry instanceof InterfaceEntry) {
74664562Sgshapiro          InterfaceEntry ent = (InterfaceEntry) entry;
74764562Sgshapiro          ent.setInterfaceType (InterfaceEntry.LOCALSERVANT);
74864562Sgshapiro      }
74964562Sgshapiro      token = parser.token;
75064562Sgshapiro      String string = token.name;
75164562Sgshapiro      match (Token.StringLiteral);
75264562Sgshapiro      // for non-interfaces it doesn't make sense, so just ignore it
75364562Sgshapiro    }
75464562Sgshapiro  } // localServantPragma
75564562Sgshapiro
75664562Sgshapiro
75764562Sgshapiro  /**
75864562Sgshapiro   *
75964562Sgshapiro   **/
760168515Sgshapiro  private void idPragma () throws IOException, ParseException
76190792Sgshapiro  {
762203004Sgshapiro    // Before I can use a parser method, I must make sure it has the current token.
763203004Sgshapiro    parser.token = token;
764203004Sgshapiro
765203004Sgshapiro    // <d57110> This flag will relax the restriction that the scopedNamed
766203004Sgshapiro    // in this ID pragma directive cannot resolve to a module.
767203004Sgshapiro    parser.isModuleLegalType (true);
768203004Sgshapiro    SymtabEntry anErrorOccurred = new SymtabEntry ();
769203004Sgshapiro    SymtabEntry entry = parser.scopedName (parser.currentModule, anErrorOccurred);
770203004Sgshapiro    parser.isModuleLegalType (false);  // <57110>
771203004Sgshapiro
772203004Sgshapiro    // Was the indicated type found in the symbol table?
773203004Sgshapiro    if (entry == anErrorOccurred)
774203004Sgshapiro    {
775203004Sgshapiro      // Don't have to generate an error, scopedName already has.
776203004Sgshapiro      scanner.skipLineComment ();
777203004Sgshapiro      token = scanner.getToken ();
778203004Sgshapiro    }
779203004Sgshapiro    // <d57110>
780203004Sgshapiro    //else if (PragmaIDs.contains (entry))
781203004Sgshapiro    //{
782203004Sgshapiro    //  ParseException.badRepIDAlreadyAssigned (scanner, entry.name ());
783203004Sgshapiro    //  scanner.skipLineComment ();
784203004Sgshapiro    //  token = scanner.getToken ();
785203004Sgshapiro    //}
786203004Sgshapiro    else
787203004Sgshapiro    {
788203004Sgshapiro      token = parser.token;
789203004Sgshapiro      String string = token.name;
790203004Sgshapiro      // Do not match token until after raise exceptions, otherwise
791203004Sgshapiro      // incorrect messages will be emitted!
792203004Sgshapiro      if (PragmaIDs.contains (entry)) // <d57110>
793203004Sgshapiro      {
794203004Sgshapiro        ParseException.badRepIDAlreadyAssigned (scanner, entry.name ());
795203004Sgshapiro      }
796203004Sgshapiro      else if (!RepositoryID.hasValidForm (string)) // <d57110>
797203004Sgshapiro      {
798203004Sgshapiro        ParseException.badRepIDForm (scanner, string);
799203004Sgshapiro      }
800203004Sgshapiro      else
801203004Sgshapiro      {
802203004Sgshapiro        entry.repositoryID (new RepositoryID (string));
803203004Sgshapiro        PragmaIDs.addElement (entry); // <d57110>
804203004Sgshapiro      }
805203004Sgshapiro      match (Token.StringLiteral);
806203004Sgshapiro    }
807203004Sgshapiro  } // idPragma
808203004Sgshapiro
809203004Sgshapiro  /**
810203004Sgshapiro   *
811203004Sgshapiro   **/
812203004Sgshapiro  private void prefixPragma () throws IOException, ParseException
813203004Sgshapiro  {
814203004Sgshapiro    String string = token.name;
815203004Sgshapiro    match (Token.StringLiteral);
816203004Sgshapiro    ((IDLID)parser.repIDStack.peek ()).prefix (string);
817203004Sgshapiro    ((IDLID)parser.repIDStack.peek ()).name ("");
818203004Sgshapiro  } // prefixPragma
819203004Sgshapiro
820203004Sgshapiro  /**
821203004Sgshapiro   *
822203004Sgshapiro   **/
823203004Sgshapiro  private void versionPragma () throws IOException, ParseException
824203004Sgshapiro  {
82564562Sgshapiro    // Before I can use a parser method, I must make sure it has the current token.
82664562Sgshapiro    parser.token = token;
82764562Sgshapiro    // This flag will relax the restriction that the scopedNamed
82864562Sgshapiro    // in this Version pragma directive cannot resolve to a module.
82964562Sgshapiro    parser.isModuleLegalType (true);
83064562Sgshapiro    SymtabEntry anErrorOccurred = new SymtabEntry ();
83164562Sgshapiro    SymtabEntry entry = parser.scopedName (parser.currentModule, anErrorOccurred);
83264562Sgshapiro    // reset the flag to original value
83364562Sgshapiro    parser.isModuleLegalType (false);
83464562Sgshapiro    if (entry == anErrorOccurred)
83564562Sgshapiro    {
83664562Sgshapiro      // Don't have to generate an error, scopedName already has.
83764562Sgshapiro      scanner.skipLineComment ();
838203004Sgshapiro      token = scanner.getToken ();
839168515Sgshapiro    }
840203004Sgshapiro    else
841203004Sgshapiro    {
842203004Sgshapiro      token = parser.token;
843168515Sgshapiro      String string = token.name;
844168515Sgshapiro      match (Token.FloatingPointLiteral);
845168515Sgshapiro      if (entry.repositoryID () instanceof IDLID)
846168515Sgshapiro        ((IDLID)entry.repositoryID ()).version (string);
847168515Sgshapiro    }
84864562Sgshapiro  } // versionPragma
84964562Sgshapiro
85064562Sgshapiro  private Vector pragmaHandlers = new Vector ();
851168515Sgshapiro
852168515Sgshapiro  /**
853168515Sgshapiro   *
85464562Sgshapiro   **/
85564562Sgshapiro  void registerPragma (PragmaHandler handler)
85664562Sgshapiro  {
85764562Sgshapiro    pragmaHandlers.addElement (handler);
85864562Sgshapiro  } // registerPragma
859168515Sgshapiro
860168515Sgshapiro  /**
861168515Sgshapiro   *
86264562Sgshapiro   **/
86364562Sgshapiro  private void otherPragmas (String pragmaType, String currentToken) throws IOException
86464562Sgshapiro  {
86564562Sgshapiro    for (int i = pragmaHandlers.size () - 1; i >= 0; --i)
866168515Sgshapiro    {
867168515Sgshapiro      PragmaHandler handler = (PragmaHandler)pragmaHandlers.elementAt (i);
86864562Sgshapiro      if (handler.process (pragmaType, currentToken))
869168515Sgshapiro                break;
870168515Sgshapiro    }
871168515Sgshapiro  } // otherPragmas
872168515Sgshapiro
873168515Sgshapiro  /*
87464562Sgshapiro   * These protected methods are used by extenders, by the code
87564562Sgshapiro   * which implements otherPragma.
876168515Sgshapiro   */
877168515Sgshapiro
878168515Sgshapiro  /**
87964562Sgshapiro   * Get the current token.
88064562Sgshapiro   **/
881168515Sgshapiro  String currentToken ()
882168515Sgshapiro  {
883168515Sgshapiro    return tokenToString ();
884168515Sgshapiro  } // currentToken
885168515Sgshapiro
88664562Sgshapiro  /**
88764562Sgshapiro   * This method, given an entry name, returns the entry with that name.
88864562Sgshapiro   * It can take fully or partially qualified names and returns the
88964562Sgshapiro   * appropriate entry defined within the current scope.  If no entry
89064562Sgshapiro   * exists, null is returned.
89164562Sgshapiro   **/
89264562Sgshapiro  SymtabEntry getEntryForName (String string)
89364562Sgshapiro  {
894168515Sgshapiro    boolean partialScope = false;
89564562Sgshapiro    boolean globalScope  = false;
896203004Sgshapiro
89764562Sgshapiro    // Change all ::'s to /'s
89864562Sgshapiro    if (string.startsWith ("::"))
89964562Sgshapiro    {
90064562Sgshapiro      globalScope = true;
90164562Sgshapiro      string = string.substring (2);
90264562Sgshapiro    }
90364562Sgshapiro    int index = string.indexOf ("::");
904203004Sgshapiro    while (index >= 0)
905203004Sgshapiro    {
906203004Sgshapiro      partialScope = true;
907203004Sgshapiro      string = string.substring (0, index) + '/' + string.substring (index + 2);
908203004Sgshapiro      index = string.indexOf ("::");
909203004Sgshapiro    }
910203004Sgshapiro
911203004Sgshapiro    // Get the entry for that string
912203004Sgshapiro    SymtabEntry entry = null;
913203004Sgshapiro    if (globalScope)
914203004Sgshapiro      entry = parser.recursiveQualifiedEntry (string);
915168515Sgshapiro    else if (partialScope)
916203004Sgshapiro      entry = parser.recursivePQEntry (string, parser.currentModule);
917203004Sgshapiro    else
918203004Sgshapiro      entry = parser.unqualifiedEntryWMod (string, parser.currentModule);
919203004Sgshapiro    return entry;
920203004Sgshapiro  } // getEntryForName
921203004Sgshapiro
922203004Sgshapiro  /**
923203004Sgshapiro   * This method returns a string of all of the characters from the
924203004Sgshapiro   * input file from the current position up to, but not including,
925203004Sgshapiro   * the end-of-line character(s).
926203004Sgshapiro   **/
927203004Sgshapiro  String getStringToEOL () throws IOException
928203004Sgshapiro  {
929203004Sgshapiro    return scanner.getStringToEOL ();
930203004Sgshapiro  } // getStringToEOL
931203004Sgshapiro
932203004Sgshapiro  /**
933203004Sgshapiro   * This method returns a string of all of the characters from the
934203004Sgshapiro   * input file from the current position up to, but not including,
935203004Sgshapiro   * the given character.  It encapsulates parenthesis and quoted strings,
936203004Sgshapiro   * meaning it does not stop if the given character is found within
937203004Sgshapiro   * parentheses or quotes.  For instance, given the input of
938203004Sgshapiro   * `start(inside)end', getUntil ('n') will return "start(inside)e"
939203004Sgshapiro   **/
940168515Sgshapiro  String getUntil (char c) throws IOException
941203004Sgshapiro  {
942203004Sgshapiro    return scanner.getUntil (c);
943203004Sgshapiro  } // getUntil
944203004Sgshapiro
945203004Sgshapiro  private boolean lastWasMacroID = false;
946203004Sgshapiro
947203004Sgshapiro  /**
948203004Sgshapiro   *
949203004Sgshapiro   **/
950203004Sgshapiro  private String tokenToString ()
951168515Sgshapiro  {
952168515Sgshapiro    if (token.equals (Token.MacroIdentifier))
953168515Sgshapiro    {
954168515Sgshapiro      lastWasMacroID = true;
955168515Sgshapiro      return token.name;
956168515Sgshapiro    }
957168515Sgshapiro    else if (token.equals (Token.Identifier))
958168515Sgshapiro      return token.name;
959168515Sgshapiro    else
960168515Sgshapiro      return token.toString ();
961168515Sgshapiro  } // tokenToString
962168515Sgshapiro
963168515Sgshapiro  /**
964168515Sgshapiro   * This method returns the next token String from the input file.
965168515Sgshapiro   **/
966168515Sgshapiro  String nextToken () throws IOException
967168515Sgshapiro  {
968168515Sgshapiro    if (lastWasMacroID)
969168515Sgshapiro    {
970168988Sgshapiro      lastWasMacroID = false;
971168515Sgshapiro      return "(";
97264562Sgshapiro    }
973168515Sgshapiro    else
974168515Sgshapiro    {
975168515Sgshapiro      token = scanner.getToken ();
976168515Sgshapiro      return tokenToString ();
977168515Sgshapiro    }
978168515Sgshapiro  } // nextToken
979168515Sgshapiro
980168515Sgshapiro  /**
981168515Sgshapiro   * This method assumes that the current token marks the beginning
982168515Sgshapiro   * of a scoped name.  It then parses the subsequent identifier and
983168515Sgshapiro   * double colon tokens, builds the scoped name, and finds the symbol
984168515Sgshapiro   * table entry with that name.
985168515Sgshapiro   **/
986168515Sgshapiro  SymtabEntry scopedName () throws IOException
987168515Sgshapiro  {
988168515Sgshapiro    boolean     globalScope  = false;
989168515Sgshapiro    boolean     partialScope = false;
990168515Sgshapiro    String      name         = null;
991168515Sgshapiro    SymtabEntry entry        = null;
992168515Sgshapiro    try
993168515Sgshapiro    {
994168515Sgshapiro      if (token.equals (Token.DoubleColon))
995203004Sgshapiro        globalScope = true;
996203004Sgshapiro      else
997203004Sgshapiro      {
998203004Sgshapiro        if (token.equals (Token.Object))
999203004Sgshapiro        {
1000203004Sgshapiro          name = "Object";
1001168515Sgshapiro          match (Token.Object);
1002168515Sgshapiro        }
1003168515Sgshapiro        else if (token.type == Token.ValueBase)
1004168515Sgshapiro        {
1005168515Sgshapiro          name = "ValueBase";
1006168515Sgshapiro          match (Token.ValueBase);
1007168515Sgshapiro        }
1008168515Sgshapiro        else
1009168515Sgshapiro        {
1010168515Sgshapiro          name = token.name;
1011168515Sgshapiro          match (Token.Identifier);
1012168515Sgshapiro        }
1013168515Sgshapiro      }
1014168515Sgshapiro      while (token.equals (Token.DoubleColon))
1015168515Sgshapiro      {
1016168515Sgshapiro        match (Token.DoubleColon);
1017168515Sgshapiro        partialScope = true;
1018168515Sgshapiro        if (name != null)
1019168515Sgshapiro          name = name + '/' + token.name;
1020168515Sgshapiro        else
1021168515Sgshapiro          name = token.name;
1022168515Sgshapiro        match (Token.Identifier);
1023168515Sgshapiro      }
1024168515Sgshapiro      if (globalScope)
1025168515Sgshapiro        entry = parser.recursiveQualifiedEntry (name);
1026168515Sgshapiro      else if (partialScope)
1027168515Sgshapiro        entry = parser.recursivePQEntry (name, parser.currentModule);
1028168515Sgshapiro      else
1029168515Sgshapiro        entry = parser.unqualifiedEntryWMod (name, parser.currentModule);
1030168515Sgshapiro    }
1031168515Sgshapiro    catch (ParseException e)
1032168515Sgshapiro    {
1033168515Sgshapiro      entry = null;
1034168515Sgshapiro    }
1035168515Sgshapiro    return entry;
1036168515Sgshapiro  } // scopedName
1037168515Sgshapiro
1038168515Sgshapiro  /**
1039168515Sgshapiro   * Skip to the end of the line.
1040168515Sgshapiro   **/
1041168515Sgshapiro  void skipToEOL () throws IOException
1042168515Sgshapiro  {
1043168515Sgshapiro    scanner.skipLineComment ();
1044168515Sgshapiro  } // skipToEOL
1045168515Sgshapiro
1046168515Sgshapiro  /**
1047168515Sgshapiro   * This method skips the data in the input file until the specified
1048168515Sgshapiro   * character is encountered, then it returns the next token.
1049168515Sgshapiro   **/
1050168515Sgshapiro  String skipUntil (char c) throws IOException
1051168515Sgshapiro  {
1052168515Sgshapiro    if (!(lastWasMacroID && c == '('))
1053168515Sgshapiro      token = scanner.skipUntil (c);
1054168515Sgshapiro    return tokenToString ();
1055168515Sgshapiro  } // skipUntil
1056168515Sgshapiro
1057168515Sgshapiro  /**
1058168515Sgshapiro   * This method displays a Parser Exception complete with line number
1059168515Sgshapiro   * and position information with the given message string.
1060168515Sgshapiro   **/
1061168515Sgshapiro  void parseException (String message)
1062168515Sgshapiro  {
1063168515Sgshapiro    // <d62023> Suppress warnings
1064168515Sgshapiro    if (!parser.noWarn)
1065168515Sgshapiro      ParseException.warning (scanner, message);
1066168515Sgshapiro  } // parseException
1067168515Sgshapiro
1068168515Sgshapiro  // For Pragma
1069168515Sgshapiro  ///////////////
1070168515Sgshapiro  // For macro expansion
1071168515Sgshapiro
1072168515Sgshapiro  /**
1073168515Sgshapiro   *
1074168515Sgshapiro   **/
1075168515Sgshapiro  String expandMacro (String macroDef, Token t) throws IOException, ParseException
1076168515Sgshapiro  {
1077168515Sgshapiro    token = t;
1078168515Sgshapiro    // Get the parameter values from the macro 'call'
1079168515Sgshapiro    Vector parmValues = getParmValues ();
1080168515Sgshapiro
1081168515Sgshapiro    // Get the parameter names from the macro definition
1082168515Sgshapiro    // NOTE:  a newline character is appended here so that when
1083168515Sgshapiro    // getStringToEOL is called, it stops scanning at the end
1084168515Sgshapiro    // of this string.
1085168515Sgshapiro    scanner.scanString (macroDef + '\n');
1086168515Sgshapiro    Vector parmNames = new Vector ();
108764562Sgshapiro    macro (parmNames);
1088168515Sgshapiro
1089168515Sgshapiro    if (parmValues.size () < parmNames.size ())
1090168515Sgshapiro      throw ParseException.syntaxError (scanner, Token.Comma, Token.RightParen);
109164562Sgshapiro    else if (parmValues.size () > parmNames.size ())
109264562Sgshapiro      throw ParseException.syntaxError (scanner, Token.RightParen, Token.Comma);
109364562Sgshapiro
1094168515Sgshapiro    macroDef = scanner.getStringToEOL ();
1095168515Sgshapiro    for (int i = 0; i < parmNames.size (); ++i)
1096168515Sgshapiro      macroDef = replaceAll (macroDef, (String)parmNames.elementAt (i), (String)parmValues.elementAt (i));
1097168515Sgshapiro    return removeDoublePound (macroDef);
1098168515Sgshapiro  } // expandMacro
1099168515Sgshapiro
1100168515Sgshapiro  // This method is only used by the macro expansion methods.
1101168515Sgshapiro  /**
1102168515Sgshapiro   *
1103168515Sgshapiro   **/
1104168515Sgshapiro  private void miniMatch (int type) throws ParseException
1105168515Sgshapiro  {
1106168515Sgshapiro    // A normal production would now execute:
1107168515Sgshapiro    // match (type);
1108168515Sgshapiro    // But match reads the next token.  I don't want to do that now.
1109168515Sgshapiro    // Just make sure the current token is a 'type'.
1110168515Sgshapiro    if (!token.equals (type))
1111168515Sgshapiro      throw ParseException.syntaxError (scanner, type, token.type);
1112168515Sgshapiro  } // miniMatch
1113168515Sgshapiro
1114168515Sgshapiro  /**
1115168515Sgshapiro   *
1116168515Sgshapiro   **/
1117168515Sgshapiro  private Vector getParmValues () throws IOException, ParseException
1118168515Sgshapiro  {
1119168515Sgshapiro    Vector values = new Vector ();
1120168515Sgshapiro    if (token.equals (Token.Identifier))
1121168515Sgshapiro    {
1122182352Sgshapiro      match (Token.Identifier);
1123168515Sgshapiro      miniMatch (Token.LeftParen);
1124168515Sgshapiro    }
1125223067Sgshapiro    else if (!token.equals (Token.MacroIdentifier))
1126168515Sgshapiro      throw ParseException.syntaxError (scanner, Token.Identifier, token.type);
1127168515Sgshapiro
1128168515Sgshapiro    if (!token.equals (Token.RightParen))
1129168515Sgshapiro    {
1130168515Sgshapiro      values.addElement (scanner.getUntil (',', ')').trim ());
1131168515Sgshapiro      token = scanner.getToken ();
1132203004Sgshapiro      macroParmValues (values);
1133203004Sgshapiro    }
1134223067Sgshapiro    return values;
1135203004Sgshapiro  } // getParmValues
1136203004Sgshapiro
1137203004Sgshapiro  /**
1138203004Sgshapiro   *
1139203004Sgshapiro   **/
1140203004Sgshapiro  private void macroParmValues (Vector values) throws IOException, ParseException
1141203004Sgshapiro  {
1142203004Sgshapiro    while (!token.equals (Token.RightParen))
1143203004Sgshapiro    {
1144203004Sgshapiro      miniMatch (Token.Comma);
1145203004Sgshapiro      values.addElement (scanner.getUntil (',', ')').trim ());
1146203004Sgshapiro      token = scanner.getToken ();
1147203004Sgshapiro    }
1148203004Sgshapiro  } // macroParmValues
1149203004Sgshapiro
1150203004Sgshapiro  /**
115164562Sgshapiro   *
115264562Sgshapiro   **/
1153168515Sgshapiro  private void macro (Vector parmNames) throws IOException, ParseException
115490792Sgshapiro  {
115564562Sgshapiro    match (token.type);
115664562Sgshapiro    match (Token.LeftParen);
115764562Sgshapiro    macroParms (parmNames);
115864562Sgshapiro    miniMatch (Token.RightParen);
115964562Sgshapiro  } // macro
116064562Sgshapiro
116164562Sgshapiro  /**
116264562Sgshapiro   *
116364562Sgshapiro   **/
116464562Sgshapiro  private void macroParms (Vector parmNames) throws IOException, ParseException
116564562Sgshapiro  {
116664562Sgshapiro    if (!token.equals (Token.RightParen))
116764562Sgshapiro    {
116864562Sgshapiro      parmNames.addElement (token.name);
116964562Sgshapiro      match (Token.Identifier);
117064562Sgshapiro      macroParms2 (parmNames);
117190792Sgshapiro    }
117264562Sgshapiro  } // macroParms
117364562Sgshapiro
117464562Sgshapiro  /**
117564562Sgshapiro   *
117664562Sgshapiro   **/
117764562Sgshapiro  private void macroParms2 (Vector parmNames) throws IOException, ParseException
117864562Sgshapiro  {
117964562Sgshapiro    while (!token.equals (Token.RightParen))
118064562Sgshapiro    {
118164562Sgshapiro      match (Token.Comma);
118264562Sgshapiro      parmNames.addElement (token.name);
118364562Sgshapiro      match (Token.Identifier);
118464562Sgshapiro    }
118564562Sgshapiro  } // macroParms2
118664562Sgshapiro
1187125820Sgshapiro  /**
118864562Sgshapiro   *
118964562Sgshapiro   **/
119064562Sgshapiro  private String replaceAll (String string, String from, String to)
119164562Sgshapiro  {
119264562Sgshapiro    int index = 0;
1193120256Sgshapiro    while (index != -1)
119464562Sgshapiro    {
119564562Sgshapiro      index = string.indexOf (from, index);
1196125820Sgshapiro      if (index != -1)
119764562Sgshapiro      {
119864562Sgshapiro        if (!embedded (string, index, index + from.length ()))
1199168515Sgshapiro          if (index > 0 && string.charAt(index) == '#')
120064562Sgshapiro            string = string.substring (0, index) + '"' + to + '"' + string.substring (index + from.length ());
1201168515Sgshapiro          else
120264562Sgshapiro            string = string.substring (0, index) + to + string.substring (index + from.length ());
120364562Sgshapiro        index += to.length ();
1204125820Sgshapiro      }
1205125820Sgshapiro    }
1206125820Sgshapiro    return string;
120794334Sgshapiro  } // replaceAll
120894334Sgshapiro
120994334Sgshapiro  /**
121094334Sgshapiro   *
121164562Sgshapiro   **/
121264562Sgshapiro  private boolean embedded (String string, int index, int endIndex)
121364562Sgshapiro  {
121464562Sgshapiro    // Don't replace if found substring is not an independent id.
121594334Sgshapiro    // For example, don't replace "thither".indexOf ("it", 0)
121664562Sgshapiro    boolean ret    = false;
121764562Sgshapiro    char    preCh  = index == 0 ? ' ' : string.charAt (index - 1);
1218168515Sgshapiro    char    postCh = endIndex >= string.length () - 1 ? ' ' : string.charAt (endIndex);
121964562Sgshapiro    if ((preCh >= 'a' && preCh <= 'z') || (preCh >= 'A' && preCh <= 'Z'))
1220168515Sgshapiro      ret = true;
122164562Sgshapiro    else if ((postCh >= 'a' && postCh <= 'z') || (postCh >= 'A' && postCh <= 'Z') || (postCh >= '0' && postCh <= '9') || postCh == '_')
122264562Sgshapiro      ret = true;
122364562Sgshapiro    else
122464562Sgshapiro      ret = inQuotes (string, index);
122564562Sgshapiro    return ret;
122664562Sgshapiro  } // embedded
122764562Sgshapiro
122864562Sgshapiro  /**
122964562Sgshapiro   *
123064562Sgshapiro   **/
123164562Sgshapiro  private boolean inQuotes (String string, int index)
123290792Sgshapiro  {
123390792Sgshapiro    int quoteCount = 0;
123464562Sgshapiro    for (int i = 0; i < index; ++i)
123564562Sgshapiro      if (string.charAt (i) == '"') ++quoteCount;
1236168515Sgshapiro    // If there are an odd number of quotes before this region,
123764562Sgshapiro    // then this region is within quotes
1238168515Sgshapiro    return quoteCount % 2 != 0;
123964562Sgshapiro  } // inQuotes
124064562Sgshapiro
124164562Sgshapiro  /**
124264562Sgshapiro   * Remove any occurrences of ##.
124364562Sgshapiro   **/
124464562Sgshapiro  private String removeDoublePound (String string)
124564562Sgshapiro  {
124664562Sgshapiro    int index = 0;
124764562Sgshapiro    while (index != -1)
124864562Sgshapiro    {
124964562Sgshapiro      index = string.indexOf ("##", index);
125090792Sgshapiro      if (index != -1)
125164562Sgshapiro      {
125264562Sgshapiro        int startSkip = index - 1;
125364562Sgshapiro        int stopSkip  = index + 2;
125464562Sgshapiro        if (startSkip < 0)
1255168515Sgshapiro          startSkip = 0;
125664562Sgshapiro        if (stopSkip >= string.length ())
1257168515Sgshapiro          stopSkip = string.length () - 1;
125864562Sgshapiro        while (startSkip > 0 &&
125964562Sgshapiro               (string.charAt (startSkip) == ' ' ||
126064562Sgshapiro               string.charAt (startSkip) == '\t'))
126164562Sgshapiro          --startSkip;
126264562Sgshapiro        while (stopSkip < string.length () - 1 &&
126364562Sgshapiro               (string.charAt (stopSkip) == ' ' ||
126464562Sgshapiro               string.charAt (stopSkip) == '\t'))
126564562Sgshapiro          ++stopSkip;
1266168515Sgshapiro        string = string.substring (0, startSkip + 1) + string.substring (stopSkip);
126764562Sgshapiro      }
1268168515Sgshapiro    }
126964562Sgshapiro    return string;
127064562Sgshapiro  } // removeDoublePound
127164562Sgshapiro
127264562Sgshapiro  // For macro expansion
127364562Sgshapiro  ///////////////
127464562Sgshapiro
1275132943Sgshapiro  /**
127690792Sgshapiro   *
127764562Sgshapiro   **/
127864562Sgshapiro  private String getFilename (String name) throws FileNotFoundException
127964562Sgshapiro  {
128064562Sgshapiro    String fullName = null;
128164562Sgshapiro    File file = new File (name);
128264562Sgshapiro    if (file.canRead ())
128364562Sgshapiro      fullName = name;
128464562Sgshapiro    else
128564562Sgshapiro    {
128664562Sgshapiro      Enumeration pathList = parser.paths.elements ();
128764562Sgshapiro      while (!file.canRead () && pathList.hasMoreElements ())
128864562Sgshapiro      {
128964562Sgshapiro        fullName = (String)pathList.nextElement () + File.separatorChar + name;
129064562Sgshapiro        file = new File (fullName);
129164562Sgshapiro      }
129264562Sgshapiro      if (!file.canRead ())
129364562Sgshapiro        throw new FileNotFoundException (name);
129464562Sgshapiro    }
129564562Sgshapiro    return fullName;
129664562Sgshapiro  } // getFilename
129764562Sgshapiro
129864562Sgshapiro  /**
1299132943Sgshapiro   *
130090792Sgshapiro   **/
1301132943Sgshapiro  private void match (int type) throws IOException, ParseException
1302132943Sgshapiro  {
1303132943Sgshapiro    if (!token.equals (type))
1304132943Sgshapiro      throw ParseException.syntaxError (scanner, type, token.type);
1305132943Sgshapiro    token = scanner.getToken ();
1306132943Sgshapiro
1307132943Sgshapiro    // <d62023> Added for convenience, but commented-out because there is
1308132943Sgshapiro    // no reason to issue warnings for tokens scanned during preprocessing.
1309132943Sgshapiro    // See issueTokenWarnings().
1310132943Sgshapiro    //issueTokenWarnings ();
1311132943Sgshapiro
1312132943Sgshapiro    //System.out.println ("Preprocessor.match token = " + token.type);
1313132943Sgshapiro    //if (token.equals (Token.Identifier) || token.equals (Token.MacroIdentifier))
1314132943Sgshapiro    //  System.out.println ("Preprocessor.match token name = " + token.name);
1315132943Sgshapiro
1316132943Sgshapiro    // If the token is a defined thingy, scan the defined string
1317132943Sgshapiro    // instead of the input stream for a while.
1318132943Sgshapiro    if (token.equals (Token.Identifier) || token.equals (Token.MacroIdentifier))
1319168988Sgshapiro    {
1320132943Sgshapiro      String string = (String)symbols.get (token.name);
1321132943Sgshapiro      if (string != null && !string.equals (""))
1322132943Sgshapiro        // If this is a macro, parse the macro
1323132943Sgshapiro        if (macros.contains (token.name))
1324132943Sgshapiro        {
1325132943Sgshapiro          scanner.scanString (expandMacro (string, token));
132664562Sgshapiro          token = scanner.getToken ();
132764562Sgshapiro        }
132864562Sgshapiro        // else this is just a normal define
132964562Sgshapiro        else
133064562Sgshapiro        {
133164562Sgshapiro          scanner.scanString (string);
133264562Sgshapiro          token = scanner.getToken ();
133364562Sgshapiro        }
1334168515Sgshapiro    }
133564562Sgshapiro  } // match
133664562Sgshapiro
133764562Sgshapiro  // <d62023>
133864562Sgshapiro  /**
133964562Sgshapiro   * Issue warnings about tokens scanned during preprocessing.
134064562Sgshapiro   **/
134164562Sgshapiro  private void issueTokenWarnings ()
134264562Sgshapiro  {
134364562Sgshapiro    if (parser.noWarn)
134464562Sgshapiro      return;
134564562Sgshapiro
1346125820Sgshapiro    // There are no keywords defined for preprocessing (only directives), so:
1347125820Sgshapiro    //
1348125820Sgshapiro    // 1.) Do not issue warnings for identifiers known to be keywords in
1349125820Sgshapiro    //     another level of IDL.
135064562Sgshapiro    // 2.) Do not issue warnings for identifiers that collide with keywords
1351125820Sgshapiro    //     in letter, but not case.
135264562Sgshapiro    // 3.) Do not issue warnings for deprecated keywords.
135364562Sgshapiro    //
1354168515Sgshapiro    // Should we warn when a macro identifier replaces a keyword?  Hmmm.
135590792Sgshapiro
135664562Sgshapiro    // Deprecated directives?  None to date.
135764562Sgshapiro    //if (token.isDirective () && token.isDeprecated ())
135864562Sgshapiro    //  ParseException.warning (scanner, Util.getMesage ("Deprecated.directive", token.name));
135964562Sgshapiro  } // issueTokenWarnings
136064562Sgshapiro
136164562Sgshapiro  /**
136264562Sgshapiro   * This method is called when the parser encounters a left curly brace.
136364562Sgshapiro   * An extender of PragmaHandler may find scope information useful.
136464562Sgshapiro   * For example, the prefix pragma takes effect as soon as it is
136564562Sgshapiro   * encountered and stays in effect until the current scope is closed.
136664562Sgshapiro   * If a similar pragma extension is desired, then the openScope and
136764562Sgshapiro   * closeScope methods are available for overriding.
136864562Sgshapiro   * @param entry the symbol table entry whose scope has just been opened.
136964562Sgshapiro   *  Be aware that, since the scope has just been entered, this entry is
137064562Sgshapiro   *  incomplete at this point.
137164562Sgshapiro   **/
137264562Sgshapiro  void openScope (SymtabEntry entry)
137364562Sgshapiro  {
137464562Sgshapiro    for (int i = pragmaHandlers.size () - 1; i >= 0; --i)
137564562Sgshapiro    {
137664562Sgshapiro      PragmaHandler handler = (PragmaHandler)pragmaHandlers.elementAt (i);
137764562Sgshapiro      handler.openScope (entry);
137864562Sgshapiro    }
137964562Sgshapiro  } // openScope
138064562Sgshapiro
138164562Sgshapiro  /**
138264562Sgshapiro   * This method is called when the parser encounters a right curly brace.
138390792Sgshapiro   * An extender of PragmaHandler may find scope information useful.
138490792Sgshapiro   * For example, the prefix pragma takes effect as soon as it is
138590792Sgshapiro   * encountered and stays in effect until the current scope is closed.
138690792Sgshapiro   * If a similar pragma extension is desired, then the openScope and
138790792Sgshapiro   * closeScope methods are available for overriding.
138890792Sgshapiro   * @param entry the symbol table entry whose scope has just been closed.
138990792Sgshapiro   **/
139090792Sgshapiro  void closeScope (SymtabEntry entry)
139190792Sgshapiro  {
139290792Sgshapiro    for (int i = pragmaHandlers.size () - 1; i >= 0; --i)
139390792Sgshapiro    {
139464562Sgshapiro      PragmaHandler handler = (PragmaHandler)pragmaHandlers.elementAt (i);
139590792Sgshapiro      handler.closeScope (entry);
139690792Sgshapiro    }
139790792Sgshapiro  } // closeScope
139864562Sgshapiro
139964562Sgshapiro  private Parser    parser;
140090792Sgshapiro  private Scanner   scanner;
140164562Sgshapiro  private Hashtable symbols;
140264562Sgshapiro  private Vector    macros;
140364562Sgshapiro
140464562Sgshapiro  // The logic associated with this stack is scattered above.
140564562Sgshapiro  // A concise map of the logic is:
140664562Sgshapiro  // case #if false, #ifdef false, #ifndef true
140764562Sgshapiro  //   push (false);
140864562Sgshapiro  //   skipToEndifOrElse ();
140964562Sgshapiro  // case #if true, #ifdef true, #ifndef false
141064562Sgshapiro  //   push (true);
141164562Sgshapiro  // case #elif <conditional>
141264562Sgshapiro  //   if (top == true)
141364562Sgshapiro  //     skipToEndif ();
141464562Sgshapiro  //   else if (conditional == true)
141564562Sgshapiro  //     pop ();
1416168515Sgshapiro  //     push (true);
141790792Sgshapiro  //   else if (conditional == false)
141864562Sgshapiro  //     skipToEndifOrElse ();
141964562Sgshapiro  // case #else
142064562Sgshapiro  //   if (top == true)
142164562Sgshapiro  //     skipToEndif ();
142264562Sgshapiro  //   else
142364562Sgshapiro  //     pop ();
142464562Sgshapiro  //     push (true);
142564562Sgshapiro  // case #endif
142664562Sgshapiro  //   pop ();
142764562Sgshapiro  private        Stack  alreadyProcessedABranch = new Stack ();
142864562Sgshapiro                 Token  token;
142964562Sgshapiro
143064562Sgshapiro  private static String indent = "";
143164562Sgshapiro}
143264562Sgshapiro