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