1 16 17 package org.cojen.classfile; 18 19 import java.util.ArrayList ; 20 21 35 public class MethodDeclarationParser { 36 40 private static void skipWhitespace(String src, int[] pos) { 41 int length = src.length(); 42 int i = pos[0]; 43 while (i < length) { 44 char c = src.charAt(i); 45 if (Character.isWhitespace(c)) { 46 i++; 47 } else { 48 break; 49 } 50 } 51 pos[0] = i; 52 } 53 54 59 private static String parseIdentifier(String src, int[] pos) { 60 skipWhitespace(src, pos); 62 int i = pos[0]; 63 int length = src.length(); 64 if (i >= length) { 65 return null; 66 } 67 68 int startPos = i; 69 char c = src.charAt(i); 70 if (!Character.isJavaIdentifierStart(c)) { 71 return null; 72 } 73 i++; 74 75 while (i < length) { 76 c = src.charAt(i); 77 if (Character.isJavaIdentifierPart(c)) { 78 i++; 79 } else { 80 break; 81 } 82 } 83 84 pos[0] = i; 85 86 skipWhitespace(src, pos); 88 89 return src.substring(startPos, i); 90 } 91 92 private static TypeDesc parseTypeDesc(String src, int[] pos) { 93 skipWhitespace(src, pos); 95 int i = pos[0]; 96 int length = src.length(); 97 if (i >= length) { 98 return null; 99 } 100 101 int startPos = i; 102 char c = src.charAt(i); 103 if (!Character.isJavaIdentifierStart(c)) { 104 return null; 105 } 106 i++; 107 108 while (i < length) { 109 c = src.charAt(i); 110 if (c == '.') { 111 if (i + 1 < length && src.charAt(i + 1) == '.') { 113 break; 114 } else { 115 i++; 116 } 117 } else if (Character.isJavaIdentifierPart(c) || c == '[' || c == ']') { 118 i++; 119 } else { 120 break; 121 } 122 } 123 124 pos[0] = i; 125 126 skipWhitespace(src, pos); 128 129 return TypeDesc.forClass(src.substring(startPos, i)); 130 } 131 132 136 private static Modifiers parseModifiers(String src, int[] pos) { 137 Modifiers modifiers = Modifiers.NONE; 138 139 int length = src.length(); 140 loop: while (pos[0] < length) { 141 int savedPos = pos[0]; 142 String ident = parseIdentifier(src, pos); 143 int newPos = pos[0]; 144 pos[0] = savedPos; 145 146 if (ident == null) { 147 break; 148 } 149 150 switch (ident.charAt(0)) { 151 case 'a': 152 if ("abstract".equals(ident)) { 153 modifiers = modifiers.toAbstract(true); 154 } else { 155 break loop; 156 } 157 break; 158 159 case 'f': 160 if ("final".equals(ident)) { 161 modifiers = modifiers.toFinal(true); 162 } else { 163 break loop; 164 } 165 break; 166 167 case 'n': 168 if ("native".equals(ident)) { 169 modifiers = modifiers.toNative(true); 170 } else { 171 break loop; 172 } 173 break; 174 175 case 'p': 176 if ("public".equals(ident)) { 177 modifiers = modifiers.toPublic(true); 178 } else if ("private".equals(ident)) { 179 modifiers = modifiers.toPrivate(true); 180 } else if ("protected".equals(ident)) { 181 modifiers = modifiers.toProtected(true); 182 } else { 183 break loop; 184 } 185 break; 186 187 case 's': 188 if ("static".equals(ident)) { 189 modifiers = modifiers.toStatic(true); 190 } else if ("synchronized".equals(ident)) { 191 modifiers = modifiers.toSynchronized(true); 192 } else if ("strict".equals(ident)) { 193 modifiers = modifiers.toStrict(true); 194 } else { 195 break loop; 196 } 197 break; 198 199 case 't': 200 if ("transient".equals(ident)) { 201 modifiers = modifiers.toTransient(true); 202 } else { 203 break loop; 204 } 205 break; 206 207 case 'v': 208 if ("volatile".equals(ident)) { 209 modifiers = modifiers.toVolatile(true); 210 } else { 211 break loop; 212 } 213 break; 214 215 default: 216 break loop; 217 } 219 pos[0] = newPos; 221 } 222 223 return modifiers; 224 } 225 226 private static TypeDesc[] parseParameters(String src, int[] pos, boolean[] isVarArgs) { 227 skipWhitespace(src, pos); 229 int length = src.length(); 230 if (pos[0] < length && src.charAt(pos[0]) != '(') { 231 throw new IllegalArgumentException ("Left paren expected"); 232 } 233 pos[0]++; 234 235 ArrayList list = new ArrayList (); 236 237 boolean expectParam = false; 238 while (pos[0] < length) { 239 TypeDesc type = parseTypeDesc(src, pos); 240 if (type == null) { 241 if (expectParam) { 242 throw new IllegalArgumentException ("Parameter type expected"); 243 } 244 break; 245 } 246 list.add(type); 247 248 parseIdentifier(src, pos); 250 251 if (pos[0] < length) { 252 char c = src.charAt(pos[0]); 253 if (c == ',') { 254 pos[0]++; 256 expectParam = true; 257 continue; 258 } else if (c == ')') { 259 pos[0]++; 260 break; 261 } 262 263 if (c == '.' && pos[0] + 2 < length) { 265 if (src.charAt(pos[0] + 1) == '.' && src.charAt(pos[0] + 2) == '.') { 266 type = type.toArrayType(); 267 isVarArgs[0] = true; 268 list.set(list.size() - 1, type); 269 pos[0] += 3; 270 expectParam = false; 271 continue; 272 } 273 } 274 275 throw new IllegalArgumentException ("Expected comma or right paren"); 276 } 277 } 278 279 return (TypeDesc[]) list.toArray(new TypeDesc[list.size()]); 280 } 281 282 private final Modifiers mModifiers; 283 private final TypeDesc mReturnType; 284 private final String mMethodName; 285 private final TypeDesc[] mParameters; 286 287 294 public MethodDeclarationParser(String declaration) throws IllegalArgumentException { 295 int[] pos = new int[1]; 296 Modifiers modifiers = parseModifiers(declaration, pos); 297 mReturnType = parseTypeDesc(declaration, pos); 298 if (mReturnType == null) { 299 throw new IllegalArgumentException ("No return type"); 300 } 301 mMethodName = parseIdentifier(declaration, pos); 302 if (mMethodName == null) { 303 throw new IllegalArgumentException ("No method name"); 304 } 305 boolean[] isVarArgs = new boolean[1]; 306 mParameters = parseParameters(declaration, pos, isVarArgs); 307 if (isVarArgs[0]) { 308 modifiers = modifiers.toVarArgs(true); 309 } 310 mModifiers = modifiers; 311 } 312 313 public Modifiers getModifiers() { 314 return mModifiers; 315 } 316 317 public TypeDesc getReturnType() { 318 return mReturnType; 319 } 320 321 public String getMethodName() { 322 return mMethodName; 323 } 324 325 public TypeDesc[] getParameters() { 326 return (TypeDesc[])mParameters.clone(); 327 } 328 } 329 | Popular Tags |