1 10 11 package com.triactive.jdo.store; 12 13 import com.triactive.jdo.util.Imports; 14 import java.math.BigDecimal ; 15 import java.math.BigInteger ; 16 import java.text.CharacterIterator ; 17 import java.text.StringCharacterIterator ; 18 import javax.jdo.JDOUserException; 19 20 21 class Parser 22 { 23 private final String input; 24 private final Imports imports; 25 private final CharacterIterator ci; 26 27 28 public Parser(String input, Imports imports) 29 { 30 this.input = input; 31 this.imports = imports; 32 33 ci = new StringCharacterIterator (input); 34 } 35 36 37 public String getInput() 38 { 39 return input; 40 } 41 42 43 public int getIndex() 44 { 45 return ci.getIndex(); 46 } 47 48 49 public int skipWS() 50 { 51 int startIdx = ci.getIndex(); 52 char c = ci.current(); 53 54 while (Character.isWhitespace(c)) 55 c = ci.next(); 56 57 return startIdx; 58 } 59 60 61 public boolean parseEOS() 62 { 63 skipWS(); 64 65 return ci.current() == CharacterIterator.DONE; 66 } 67 68 69 public boolean parseChar(char c) 70 { 71 skipWS(); 72 73 if (ci.current() == c) 74 { 75 ci.next(); 76 return true; 77 } 78 else 79 return false; 80 } 81 82 83 public boolean parseChar(char c, char unlessFollowedBy) 84 { 85 int savedIdx = skipWS(); 86 87 if (ci.current() == c && ci.next() != unlessFollowedBy) 88 return true; 89 else 90 { 91 ci.setIndex(savedIdx); 92 return false; 93 } 94 } 95 96 97 public boolean parseString(String s) 98 { 99 int savedIdx = skipWS(); 100 101 int len = s.length(); 102 char c = ci.current(); 103 104 for (int i = 0; i < len; ++i) 105 { 106 if (c != s.charAt(i)) 107 { 108 ci.setIndex(savedIdx); 109 return false; 110 } 111 112 c = ci.next(); 113 } 114 115 return true; 116 } 117 118 119 public boolean parseString(String s, char unlessFollowedBy) 120 { 121 int savedIdx = skipWS(); 122 123 if (parseString(s) && ci.next() != unlessFollowedBy) 124 return true; 125 else 126 { 127 ci.setIndex(savedIdx); 128 return false; 129 } 130 } 131 132 133 public String parseIdentifier() 134 { 135 skipWS(); 136 char c = ci.current(); 137 138 if (!Character.isJavaIdentifierStart(c)) 139 return null; 140 141 StringBuffer id = new StringBuffer ().append(c); 142 143 while (Character.isJavaIdentifierPart(c = ci.next())) 144 id.append(c); 145 146 return id.toString(); 147 } 148 149 150 public String parseName() 151 { 152 int savedIdx = skipWS(); 153 String id; 154 155 if ((id = parseIdentifier()) == null) 156 return null; 157 158 StringBuffer qn = new StringBuffer (id); 159 160 while (parseChar('.')) 161 { 162 if ((id = parseIdentifier()) == null) 163 { 164 ci.setIndex(savedIdx); 165 return null; 166 } 167 168 qn.append('.').append(id); 169 } 170 171 return qn.toString(); 172 } 173 174 175 public Class parseCast() 176 { 177 int savedIdx = skipWS(); 178 String typeName; 179 180 if (!parseChar('(') || (typeName = parseName()) == null || !parseChar(')')) 181 { 182 ci.setIndex(savedIdx); 183 return null; 184 } 185 186 try 187 { 188 return imports.resolveClassDeclaration(typeName); 189 } 190 catch (ClassNotFoundException e) 191 { 192 ci.setIndex(savedIdx); 193 return null; 194 } 195 } 196 197 198 private final static boolean isDecDigit(char c) 199 { 200 return c >= '0' && c <= '9'; 201 } 202 203 204 private final static boolean isOctDigit(char c) 205 { 206 return c >= '0' && c <= '7'; 207 } 208 209 210 private final static boolean isHexDigit(char c) 211 { 212 return c >= '0' && c <= '9' || c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F'; 213 } 214 215 216 public BigInteger parseIntegerLiteral() 217 { 218 int savedIdx = skipWS(); 219 220 StringBuffer digits = new StringBuffer (); 221 int radix; 222 char c = ci.current(); 223 224 if (c == '0') 225 { 226 c = ci.next(); 227 228 if (c == 'x' || c == 'X') 229 { 230 radix = 16; 231 c = ci.next(); 232 233 while (isHexDigit(c)) 234 { 235 digits.append(c); 236 c = ci.next(); 237 } 238 } 239 else if (isOctDigit(c)) 240 { 241 radix = 8; 242 243 do 244 { 245 digits.append(c); 246 c = ci.next(); 247 } while (isOctDigit(c)); 248 } 249 else 250 { 251 radix = 10; 252 digits.append('0'); 253 } 254 } 255 else 256 { 257 radix = 10; 258 259 while (isDecDigit(c)) 260 { 261 digits.append(c); 262 c = ci.next(); 263 } 264 } 265 266 if (digits.length() == 0) 267 { 268 ci.setIndex(savedIdx); 269 return null; 270 } 271 272 if (c == 'l' || c == 'L') 273 ci.next(); 274 275 return new BigInteger (digits.toString(), radix); 276 } 277 278 279 public BigDecimal parseFloatingPointLiteral() 280 { 281 int savedIdx = skipWS(); 282 StringBuffer val = new StringBuffer (); 283 boolean dotSeen = false; 284 boolean expSeen = false; 285 boolean sfxSeen = false; 286 287 char c = ci.current(); 288 289 while (isDecDigit(c)) 290 { 291 val.append(c); 292 c = ci.next(); 293 } 294 295 if (c == '.') 296 { 297 dotSeen = true; 298 val.append(c); 299 c = ci.next(); 300 301 while (isDecDigit(c)) 302 { 303 val.append(c); 304 c = ci.next(); 305 } 306 } 307 308 if (val.length() < (dotSeen ? 2 : 1)) 309 { 310 ci.setIndex(savedIdx); 311 return null; 312 } 313 314 if (c == 'e' || c == 'E') 315 { 316 expSeen = true; 317 val.append(c); 318 c = ci.next(); 319 320 if (c != '+' && c != '-' && !isDecDigit(c)) 321 { 322 ci.setIndex(savedIdx); 323 return null; 324 } 325 326 do 327 { 328 val.append(c); 329 c = ci.next(); 330 } while (isDecDigit(c)); 331 } 332 333 if (c == 'f' || c == 'F' || c == 'd' || c == 'D') 334 { 335 sfxSeen = true; 336 ci.next(); 337 } 338 339 if (!dotSeen && !expSeen && !sfxSeen) 340 { 341 ci.setIndex(savedIdx); 342 return null; 343 } 344 345 return new BigDecimal (val.toString()); 346 } 347 348 349 public Boolean parseBooleanLiteral() 350 { 351 int savedIdx = skipWS(); 352 String id; 353 354 if ((id = parseIdentifier()) == null) 355 return null; 356 357 if (id.equals("true")) 358 return Boolean.TRUE; 359 else if (id.equals("false")) 360 return Boolean.FALSE; 361 else 362 { 363 ci.setIndex(savedIdx); 364 return null; 365 } 366 } 367 368 369 public Character parseCharacterLiteral() 370 { 371 skipWS(); 372 373 if (ci.current() != '\'') 374 return null; 375 376 char c = ci.next(); 377 378 if (c == CharacterIterator.DONE) 379 throw new JDOUserException("Invalid character literal: " + input); 380 381 if (c == '\\') 382 c = parseEscapedCharacter(); 383 384 if (ci.next() != '\'') 385 throw new JDOUserException("Invalid character literal: " + input); 386 387 ci.next(); 388 389 return new Character (c); 390 } 391 392 393 public String parseStringLiteral() 394 { 395 skipWS(); 396 397 if (ci.current() != '"') 398 return null; 399 400 StringBuffer lit = new StringBuffer (); 401 char c; 402 403 while ((c = ci.next()) != '"') 404 { 405 if (c == CharacterIterator.DONE) 406 throw new JDOUserException("Invalid string literal: " + input); 407 408 if (c == '\\') 409 c = parseEscapedCharacter(); 410 411 lit.append(c); 412 } 413 414 ci.next(); 415 416 return lit.toString(); 417 } 418 419 420 private char parseEscapedCharacter() 421 { 422 char c; 423 424 if (isOctDigit(c = ci.next())) 425 { 426 int i = (int)(c - '0'); 427 428 if (isOctDigit(c = ci.next())) 429 { 430 i = i * 8 + (int)(c - '0'); 431 432 if (isOctDigit(c = ci.next())) 433 i = i * 8 + (int)(c - '0'); 434 else 435 ci.previous(); 436 } 437 else 438 ci.previous(); 439 440 if (i > 0xff) 441 throw new JDOUserException("Invalid character escape: '\\" + Integer.toOctalString(i) + "'"); 442 443 return (char)i; 444 } 445 else 446 { 447 switch (c) 448 { 449 case 'b': return '\b'; 450 case 't': return '\t'; 451 case 'n': return '\n'; 452 case 'f': return '\f'; 453 case 'r': return '\r'; 454 case '"': return '"'; 455 case '\'': return '\''; 456 case '\\': return '\\'; 457 default: 458 throw new JDOUserException("Invalid character escape: '\\" + c + "'"); 459 } 460 } 461 } 462 463 464 public boolean parseNullLiteral() 465 { 466 int savedIdx = skipWS(); 467 String id; 468 469 if ((id = parseIdentifier()) == null) 470 return false; 471 else if (id.equals("null")) 472 return true; 473 else 474 { 475 ci.setIndex(savedIdx); 476 return false; 477 } 478 } 479 } 480 | Popular Tags |