001 /* Copyright 2000, 2001, Compaq Computer Corporation */ 002 003 package javafe.parser; 004 005 import javafe.ast.*; 006 import javafe.util.StackVector; 007 import javafe.util.ErrorSet; 008 import javafe.util.Location; 009 010 /** 011 * Base class for Java parser; provides some basic parsing utilities. 012 * 013 * @see javafe.ast.ASTNode 014 * @see javafe.parser.ParseType 015 * @see javafe.parser.Parse 016 */ 017 018 public class ParseUtil 019 { 020 public ParseUtil() { 021 //@ set seqModifierPragma.elementType = \type(ModifierPragma); 022 //@ set seqModifierPragma.owner = this; 023 } 024 025 026 //----------------------- Misc Helper Functions ---------------------------- 027 028 /** Raises a <TT>RuntimeException</TT> with the argument string. */ 029 030 // @ ensures false; 031 // UNUSED private static void fail(String m) { ErrorSet.fatal(m); } 032 033 /** Raises a <TT>RuntimeException</TT> with the argument string 034 including a textual representation of the given source location. */ 035 //@ requires loc != Location.NULL; 036 //@ ensures false; 037 public static void fail(int loc, String m) { ErrorSet.fatal(loc, m); } 038 039 //@ requires loc != Location.NULL; 040 public static void error(int loc, String m) { ErrorSet.error(loc, m); } 041 042 /** 043 Takes an expected token from the input stream, 044 calls <TT>fail</TT> on error. 045 */ 046 //@ requires l != null && l.m_in != null; 047 //@ modifies l.ttype, l.auxVal, l.identifierVal; 048 //@ ensures \old(l.ttype)==expected; 049 public void expect(Lex l, int expected) { 050 if( l.ttype != expected ) 051 fail(l.startingLoc, 052 "Unexpected token '" + PrettyPrint.inst.toString(l.ttype) + 053 "', expected '" + PrettyPrint.inst.toString(expected)+"'"); 054 l.getNextToken(); 055 } 056 057 /** 058 059 Converts operator tokens to corresponding AST tag. 060 Tokens INC and DEC get mapped to PREFIXINC and PREFIXDEC 061 062 */ 063 064 int operatorTokenToTag(int token) { 065 // Right now we have the identity mapping. 066 return token; 067 } 068 069 070 /*------------------------ Modifiers -------------------------------*/ 071 072 //* Internal working storage for parse*Modifier* functions 073 //@ invariant seqModifierPragma.elementType == \type(ModifierPragma); 074 //@ invariant seqModifierPragma.owner == this; 075 protected final StackVector seqModifierPragma = new StackVector(); 076 077 /** 078 * Keyword at index i in this array corresponds to bit i in 079 * modifier bitset. Thus PRIVATE is at index 1, ACC_PRIVATE = 080 * 1<<1. 081 * These are in the same bit order as the values in 082 * java.lang.reflect.Modifier, and should remain that way, though 083 * I don't know if any code uses that fact (it might come in handy 084 * in reading class files, for example). 085 */ 086 public static final int modifierKeywords[] = { 087 TagConstants.PUBLIC, TagConstants.PRIVATE, TagConstants.PROTECTED, 088 TagConstants.STATIC, TagConstants.FINAL, 089 TagConstants.SYNCHRONIZED, TagConstants.VOLATILE, 090 TagConstants.TRANSIENT, TagConstants.NATIVE, 091 -1, // Don't consider 'interface' to be a modifier 092 TagConstants.ABSTRACT, TagConstants.STRICT 093 }; 094 095 096 /** 097 * Parse a list of modifier pragmas. Returns <code>null</code> if 098 * <code>l</code> does not point to a modifier pragma. Otherwise, 099 * reads <code>l</code> until there are no more modifier pragmas and 100 * returns the resulting list. 101 */ 102 //@ requires l.m_in != null; 103 public ModifierPragmaVec parseModifierPragmas(/*@ non_null @*/ Lex l) { 104 if (l.ttype != TagConstants.MODIFIERPRAGMA) 105 return null; 106 107 seqModifierPragma.push(); 108 do { 109 seqModifierPragma.addElement(l.auxVal); 110 l.getNextToken(); 111 } while (l.ttype == TagConstants.MODIFIERPRAGMA); 112 return ModifierPragmaVec.popFromStackVector(seqModifierPragma); 113 } 114 115 /** 116 * Parse a list of modifier pragmas and adds them to an existing 117 * <code>ModifierPragmaVec</code>. If the existing 118 * <code>ModifierPragmaVec</code> was <code>null</code>, then it 119 * either returns <code>null</code> (if <code>l</code> does not point 120 * to a modifier pragma), or returns a new 121 * <code>ModifierPragmaVec</code>. 122 */ 123 //@ requires l.m_in != null; 124 public ModifierPragmaVec parseMoreModifierPragmas(/*@ non_null @*/ Lex l, 125 ModifierPragmaVec orig) 126 { 127 ModifierPragmaVec modifierPragmas = parseModifierPragmas( l ); 128 if (modifierPragmas == null) 129 return orig; 130 else if (orig == null) 131 return modifierPragmas; 132 else { 133 orig.append( modifierPragmas ); 134 return orig; 135 } 136 } 137 138 /** As a side effect, <code>parseModifiers</code> mutates this 139 value. */ 140 public ModifierPragmaVec modifierPragmas; 141 142 143 /** 144 * Parse a list of modifiers. Ensures no duplicate Java modifiers 145 * and only one of the access modifiers public, protected, 146 * private. Return integer encoding the Java modifiers. 147 * 148 * <p> In addition to parsing Java modifiers, also handles modifier 149 * pragmas (anything with a ttype of TagConstants.MODIFIERPRAGMA). 150 * If no modifier pragmas are seen, sets 151 * <c>modifierPragmas</c> to <c>null</c>. Otherwise, sets it to 152 * be the list of modifier pragmas seen in the course of parsing any 153 * Java modifiers. 154 * 155 * @see javafe.ast.Modifiers 156 */ 157 //@ requires l.m_in != null; 158 //@ modifies modifierPragmas; 159 public int parseModifiers(/*@ non_null @*/ Lex l) { 160 boolean seenPragma = false; 161 int modifiers = Modifiers.NONE; 162 163 getModifierLoop: 164 for(;;) { 165 if (l.ttype == TagConstants.MODIFIERPRAGMA) { 166 if (! seenPragma) { 167 seqModifierPragma.push(); 168 seenPragma = true; 169 } 170 seqModifierPragma.addElement(l.auxVal); 171 l.getNextToken(); 172 continue getModifierLoop; 173 } else { 174 int i = getJavaModifier(l,modifiers); 175 if (i != 0) { 176 modifiers |= i; 177 continue getModifierLoop; 178 } 179 } 180 // Next token is not a modifier 181 if (! seenPragma) 182 modifierPragmas = null; 183 else 184 modifierPragmas 185 = ModifierPragmaVec.popFromStackVector(seqModifierPragma); 186 return modifiers; 187 } 188 } 189 190 /** Checks if the next token is a Java modifier. Returns 0 191 if it is not; returns an int with the modifier bit turned on 192 if it is. Also issues an error if the modifier is already 193 present in the modifiers argument (use 0 for this argument 194 to turn off these errors). 195 Note that the bit that is found is not ORed into the modifiers 196 int; you have to do that outside this call. 197 The Lex is advanced if a modifier is found. 198 */ 199 public int getJavaModifier(Lex l, int modifiers) { 200 for( int i=0; i<modifierKeywords.length; i++ ) { 201 if( l.ttype == modifierKeywords[i] ) { 202 // Token is modifier keyword 203 int modifierBit = 1<<i; 204 if( (modifiers & modifierBit) != 0 ) { 205 ErrorSet.caution(l.startingLoc, 206 "Duplicate occurrence of modifier '" 207 +PrettyPrint.inst.toString(l.ttype)+"'"); 208 } else if( (modifiers & Modifiers.ACCESS_MODIFIERS) != 0 && 209 (modifierBit & Modifiers.ACCESS_MODIFIERS) != 0 ) { 210 ErrorSet.error(l.startingLoc, 211 "Cannot have more than one of the access modifiers "+ 212 "public, protected, private"); 213 } 214 l.getNextToken(); 215 return modifierBit; 216 } 217 } 218 return 0; 219 } 220 221 public boolean isJavaModifier(int ttype) { 222 for( int i=0; i<modifierKeywords.length; i++ ) { 223 if( ttype == modifierKeywords[i] ) return true; 224 } 225 return false; 226 } 227 228 static public String arrayToString(Object[] a, String sep) { 229 if (a==null || a.length == 0) return ""; 230 else { 231 StringBuffer sb = new StringBuffer(); 232 sb.append(a[0].toString()); 233 for (int i=1; i<a.length; ++i) { 234 sb.append(sep); 235 sb.append(a[i].toString()); 236 } 237 return sb.toString(); 238 } 239 } 240 }