001 /* This file was generated with JastAdd2 (http://jastadd.org) version R20130213 */ 002 package AST; 003 004 import java.util.HashSet; 005 import java.io.File; 006 import java.util.*; 007 import beaver.*; 008 import java.util.ArrayList; 009 import java.util.zip.*; 010 import java.io.*; 011 import java.io.FileNotFoundException; 012 import java.util.Collection; 013 /** 014 * A NumericLiteral is a raw literal, produced by the parser. 015 * NumericLiterals are rewritten to the best matching concrete 016 * numeric literal kind, or IllegalLiteral. 017 * @production NumericLiteral : {@link Literal}; 018 * @ast node 019 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.ast:18 020 */ 021 public class NumericLiteral extends Literal implements Cloneable { 022 /** 023 * @apilevel low-level 024 */ 025 public void flushCache() { 026 } 027 /** 028 * @apilevel internal 029 */ 030 public void flushCollectionCache() { 031 } 032 /** 033 * @apilevel internal 034 */ 035 @SuppressWarnings({"unchecked", "cast"}) 036 public NumericLiteral clone() throws CloneNotSupportedException { 037 NumericLiteral node = (NumericLiteral)super.clone(); 038 node.type_computed = false; 039 node.type_value = null; 040 node.in$Circle(false); 041 node.is$Final(false); 042 return node; 043 } 044 /** 045 * @apilevel internal 046 */ 047 @SuppressWarnings({"unchecked", "cast"}) 048 public NumericLiteral copy() { 049 050 try { 051 NumericLiteral node = (NumericLiteral) clone(); 052 node.parent = null; 053 if(children != null) 054 node.children = (ASTNode[]) children.clone(); 055 056 return node; 057 } catch (CloneNotSupportedException e) { 058 throw new Error("Error: clone not supported for " + getClass().getName()); 059 } 060 061 }/** 062 * Create a deep copy of the AST subtree at this node. 063 * The copy is dangling, i.e. has no parent. 064 * @return dangling copy of the subtree at this node 065 * @apilevel low-level 066 */ 067 @SuppressWarnings({"unchecked", "cast"}) 068 public NumericLiteral fullCopy() { 069 070 NumericLiteral tree = (NumericLiteral) copy(); 071 if (children != null) { 072 for (int i = 0; i < children.length; ++i) { 073 074 ASTNode child = (ASTNode) children[i]; 075 if(child != null) { 076 child = child.fullCopy(); 077 tree.setChild(child, i); 078 } 079 } 080 } 081 return tree; 082 083 } /** 084 * @ast method 085 * @aspect Literals 086 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:321 087 */ 088 089 090 public static final int DECIMAL = 0; 091 /** 092 * @ast method 093 * @aspect Literals 094 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:322 095 */ 096 097 public static final int HEXADECIMAL = 1; 098 /** 099 * @ast method 100 * @aspect Literals 101 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:323 102 */ 103 104 public static final int OCTAL = 2; 105 /** 106 * @ast method 107 * @aspect Literals 108 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:324 109 */ 110 111 public static final int BINARY = 3; 112 /** 113 * The trimmed digits. 114 * @ast method 115 * @aspect Literals 116 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:382 117 */ 118 119 120 /** 121 * The trimmed digits. 122 */ 123 protected String digits = ""; 124 /** 125 * Sets the trimmed digits of this literal. 126 * @ast method 127 * @aspect Literals 128 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:387 129 */ 130 public void setDigits(String digits) { 131 this.digits = digits; 132 } 133 /** 134 * The literal kind tells which kind of literal it is; 135 * it's either a DECIMAL, HEXADECIMAL, OCTAL or BINARY literal. 136 * @ast method 137 * @aspect Literals 138 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:401 139 */ 140 141 142 /** 143 * The literal kind tells which kind of literal it is; 144 * it's either a DECIMAL, HEXADECIMAL, OCTAL or BINARY literal. 145 */ 146 protected int kind = NumericLiteral.DECIMAL; 147 /** 148 * Sets the literal kind. 149 * @ast method 150 * @aspect Literals 151 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:406 152 */ 153 public void setKind(int kind) { 154 this.kind = kind; 155 } 156 /** 157 * @ast method 158 * @aspect Literals 159 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:489 160 */ 161 162 private StringBuffer buf = new StringBuffer(); 163 /** 164 * @ast method 165 * @aspect Literals 166 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:490 167 */ 168 169 private int idx = 0; 170 /** 171 * @ast method 172 * @aspect Literals 173 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:491 174 */ 175 176 private boolean whole; 177 /** 178 * @ast method 179 * @aspect Literals 180 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:492 181 */ 182 // have whole part? 183 private boolean fraction; 184 /** 185 * @ast method 186 * @aspect Literals 187 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:493 188 */ 189 // have fraction part? 190 private boolean exponent; 191 /** 192 * @ast method 193 * @aspect Literals 194 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:494 195 */ 196 // have exponent part? 197 private boolean floating; 198 /** 199 * @ast method 200 * @aspect Literals 201 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:495 202 */ 203 // is floating point? 204 private boolean isFloat; 205 /** 206 * @ast method 207 * @aspect Literals 208 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:496 209 */ 210 211 private boolean isLong; 212 /** 213 * @return a readable name to describe this literal. 214 * @ast method 215 * @aspect Literals 216 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:501 217 */ 218 219 220 /** 221 * @return a readable name to describe this literal. 222 */ 223 private String name() { 224 String name; 225 switch (kind) { 226 case DECIMAL: 227 name = "decimal"; 228 break; 229 case HEXADECIMAL: 230 name = "hexadecimal"; 231 break; 232 case OCTAL: 233 name = "octal"; 234 break; 235 case BINARY: 236 default: 237 name = "binary"; 238 break; 239 } 240 if (floating) 241 return name+" floating point"; 242 else 243 return name; 244 } 245 /** 246 * The next character in the literal is a significant character; 247 * push it onto the buffer. 248 * @ast method 249 * @aspect Literals 250 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:528 251 */ 252 253 254 /** 255 * The next character in the literal is a significant character; 256 * push it onto the buffer. 257 */ 258 private void pushChar() { 259 buf.append(getLITERAL().charAt(idx++)); 260 } 261 /** 262 * Skip ahead n chracters in the literal. 263 * @ast method 264 * @aspect Literals 265 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:535 266 */ 267 268 269 /** 270 * Skip ahead n chracters in the literal. 271 */ 272 private void skip(int n) { 273 idx += n; 274 } 275 /** 276 * @return true if there exists at least n more characters 277 * in the literal 278 * @ast method 279 * @aspect Literals 280 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:543 281 */ 282 283 284 /** 285 * @return true if there exists at least n more characters 286 * in the literal 287 */ 288 private boolean have(int n) { 289 return getLITERAL().length() >= idx+n; 290 } 291 /** 292 * Look at the n'th next character. 293 * @ast method 294 * @aspect Literals 295 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:550 296 */ 297 298 299 /** 300 * Look at the n'th next character. 301 */ 302 private char peek(int n) { 303 return getLITERAL().charAt(idx+n); 304 } 305 /** 306 * @return true if the character c is a decimal digit 307 * @ast method 308 * @aspect Literals 309 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:557 310 */ 311 312 313 /** 314 * @return true if the character c is a decimal digit 315 */ 316 private static final boolean isDecimalDigit(char c) { 317 return c == '_' || c >= '0' && c <= '9'; 318 } 319 /** 320 * @return true if the character c is a hexadecimal digit 321 * @ast method 322 * @aspect Literals 323 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:564 324 */ 325 326 327 /** 328 * @return true if the character c is a hexadecimal digit 329 */ 330 private static final boolean isHexadecimalDigit(char c) { 331 return c == '_' || c >= '0' && c <= '9' || 332 c >= 'a' && c <= 'f' || 333 c >= 'A' && c <= 'F'; 334 } 335 /** 336 * @return true if the character c is a binary digit 337 * @ast method 338 * @aspect Literals 339 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:573 340 */ 341 342 343 /** 344 * @return true if the character c is a binary digit 345 */ 346 private static final boolean isBinaryDigit(char c) { 347 return c == '_' || c == '0' || c == '1'; 348 } 349 /** 350 * @return true if the character c is an underscore 351 * @ast method 352 * @aspect Literals 353 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:580 354 */ 355 356 357 /** 358 * @return true if the character c is an underscore 359 */ 360 private static final boolean isUnderscore(char c) { 361 return c == '_'; 362 } 363 /** 364 * Parse a literal. If there is a syntax error in the literal, 365 * an IllegalLiteral will be returned. 366 * @ast method 367 * @aspect Literals 368 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:588 369 */ 370 371 372 /** 373 * Parse a literal. If there is a syntax error in the literal, 374 * an IllegalLiteral will be returned. 375 */ 376 public Literal parse() { 377 if (getLITERAL().length() == 0) 378 throw new IllegalStateException("Empty NumericLiteral"); 379 380 kind = classifyLiteral(); 381 382 Literal literal; 383 if (!floating) 384 literal = parseDigits(); 385 else 386 literal = parseFractionPart(); 387 literal.setStart(LITERALstart); 388 literal.setEnd(LITERALend); 389 return literal; 390 } 391 /** 392 * Classify the literal. 393 * 394 * @return either DECIMAL, HEXADECIMAL or BINARY 395 * @ast method 396 * @aspect Literals 397 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:609 398 */ 399 400 401 /** 402 * Classify the literal. 403 * 404 * @return either DECIMAL, HEXADECIMAL or BINARY 405 */ 406 private int classifyLiteral() { 407 if (peek(0) == '.') { 408 floating = true; 409 return DECIMAL; 410 } else if (peek(0) == '0') { 411 if (!have(2)) { 412 // the only 1-length string that starts with 0 (obvious!) 413 return DECIMAL; 414 } else if (peek(1) == 'x' || peek(1) == 'X') { 415 skip(2); 416 return HEXADECIMAL; 417 } else if (peek(1) == 'b' || peek(1) == 'B') { 418 skip(2); 419 return BINARY; 420 } else { 421 return DECIMAL; 422 } 423 } else { 424 return DECIMAL; 425 } 426 } 427 /** 428 * If the current character is an underscore, the previous and next 429 * characters need to be valid digits or underscores. 430 * 431 * @return true if the underscore is misplaced 432 * @ast method 433 * @aspect Literals 434 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:637 435 */ 436 437 438 /** 439 * If the current character is an underscore, the previous and next 440 * characters need to be valid digits or underscores. 441 * 442 * @return true if the underscore is misplaced 443 */ 444 private boolean misplacedUnderscore() { 445 // first and last characters are never allowed to be an underscore 446 if (idx == 0 || idx+1 == getLITERAL().length()) 447 return true; 448 449 switch (kind) { 450 case DECIMAL: 451 return !(isDecimalDigit(peek(-1)) && isDecimalDigit(peek(1))); 452 case HEXADECIMAL: 453 return !(isHexadecimalDigit(peek(-1)) && isHexadecimalDigit(peek(1))); 454 case BINARY: 455 return !(isBinaryDigit(peek(-1)) && isBinaryDigit(peek(1))); 456 } 457 throw new IllegalStateException("Unexpected literal kind"); 458 } 459 /** 460 * Report an illegal digit. 461 * @ast method 462 * @aspect Literals 463 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:656 464 */ 465 466 467 /** 468 * Report an illegal digit. 469 */ 470 private Literal syntaxError(String msg) { 471 String err = "in "+name()+" literal "+ 472 "\""+getLITERAL()+"\""+": "+msg; 473 return new IllegalLiteral(err); 474 } 475 /** 476 * @ast method 477 * @aspect Literals 478 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:662 479 */ 480 481 482 private Literal unexpectedCharacter(char c) { 483 return syntaxError("unexpected character '"+c+"'; not a valid digit"); 484 } 485 /** 486 * Returns a string of only the lower case digits of the 487 * parsed numeric literal. 488 * @ast method 489 * @aspect Literals 490 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:670 491 */ 492 493 494 /** 495 * Returns a string of only the lower case digits of the 496 * parsed numeric literal. 497 */ 498 private String getLiteralString() { 499 return buf.toString().toLowerCase(); 500 } 501 /** 502 * Parse and build an IntegerLiteral, LongLiteral, 503 * FloatingPointLiteral or DoubleLiteral. Returns an 504 * IllegalLiteral if the numeric literal can not be 505 * parsed. 506 * 507 * Note: does not perform bounds checks. 508 * 509 * @return a concrete literal on success, or an IllegalLiteral if there is a syntax error 510 * @ast method 511 * @aspect Literals 512 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:684 513 */ 514 515 516 /** 517 * Parse and build an IntegerLiteral, LongLiteral, 518 * FloatingPointLiteral or DoubleLiteral. Returns an 519 * IllegalLiteral if the numeric literal can not be 520 * parsed. 521 * 522 * Note: does not perform bounds checks. 523 * 524 * @return a concrete literal on success, or an IllegalLiteral if there is a syntax error 525 */ 526 private Literal buildLiteral() { 527 NumericLiteral literal; 528 setDigits(buf.toString().toLowerCase()); 529 530 if (!floating) { 531 if (!whole) 532 return syntaxError("at least one digit is required"); 533 534 // check if the literal is octal, and if so report illegal digits 535 if (kind == DECIMAL) { 536 if (digits.charAt(0) == '0') { 537 kind = OCTAL; 538 for (int idx = 1; idx < digits.length(); ++idx) { 539 char c = digits.charAt(idx); 540 if (c < '0' || c > '7') 541 return unexpectedCharacter(c); 542 } 543 } 544 } 545 546 if (isLong) 547 literal = new LongLiteral(getLITERAL()); 548 else 549 literal = new IntegerLiteral(getLITERAL()); 550 } else { 551 if (kind == HEXADECIMAL && !exponent) 552 return syntaxError("exponent is required"); 553 554 if (!(whole || fraction)) 555 return syntaxError("at least one digit is required in "+ 556 "either the whole or fraction part"); 557 558 if (kind == HEXADECIMAL) 559 digits = "0x"+digits;// digits parsed with Float or Double 560 561 if (isFloat) 562 literal = new FloatingPointLiteral(getLITERAL()); 563 else 564 literal = new DoubleLiteral(getLITERAL()); 565 } 566 567 literal.setDigits(getDigits()); 568 literal.setKind(getKind()); 569 return literal; 570 } 571 /** 572 * @ast method 573 * @aspect Literals 574 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:730 575 */ 576 577 578 private Literal parseDigits() { 579 // while we have at least one more character/digit 580 while (have(1)) { 581 char c = peek(0); 582 switch (c) { 583 case '_': 584 if (misplacedUnderscore()) 585 return syntaxError("misplaced underscore - underscores may only "+ 586 "be used within sequences of digits"); 587 skip(1); 588 continue; 589 case '.': 590 if (kind != DECIMAL && kind != HEXADECIMAL) 591 return unexpectedCharacter(c); 592 return parseFractionPart(); 593 case 'l': 594 case 'L': 595 if (have(2)) 596 return syntaxError("extra digits/characters "+ 597 "after suffix "+c); 598 isLong = true; 599 skip(1); 600 continue; 601 case 'f': 602 case 'F': 603 if (kind == BINARY) 604 return unexpectedCharacter(c); 605 isFloat = true; 606 case 'd': 607 case 'D': 608 if (kind == BINARY) 609 return unexpectedCharacter(c); 610 if (kind != HEXADECIMAL) { 611 if (have(2)) 612 return syntaxError("extra digits/characters "+ 613 "after type suffix "+c); 614 floating = true; 615 skip(1); 616 } else { 617 whole = true; 618 pushChar(); 619 } 620 continue; 621 } 622 623 switch (kind) { 624 case DECIMAL: 625 if (c == 'e' || c == 'E') { 626 return parseExponentPart(); 627 628 } else if (c == 'f' || c == 'F') { 629 if (have(2)) 630 return syntaxError("extra digits/characters "+ 631 "after type suffix "+c); 632 floating = true; 633 isFloat = true; 634 skip(1); 635 } else if (c == 'd' || c == 'D') { 636 if (have(2)) 637 return syntaxError("extra digits/characters "+ 638 "after type suffix "+c); 639 floating = true; 640 skip(1); 641 } else { 642 if (!isDecimalDigit(c)) 643 return unexpectedCharacter(c); 644 whole = true; 645 pushChar(); 646 } 647 continue; 648 case HEXADECIMAL: 649 if (c == 'p' || c == 'P') 650 return parseExponentPart(); 651 652 if (!isHexadecimalDigit(c)) 653 return unexpectedCharacter(c); 654 whole = true; 655 pushChar(); 656 continue; 657 case BINARY: 658 if (!isBinaryDigit(c)) 659 return unexpectedCharacter(c); 660 whole = true; 661 pushChar(); 662 continue; 663 } 664 } 665 666 return buildLiteral(); 667 } 668 /** 669 * @ast method 670 * @aspect Literals 671 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:821 672 */ 673 674 675 private Literal parseFractionPart() { 676 floating = true; 677 678 // current char is the decimal period 679 pushChar(); 680 681 // while we have at least one more character/digit 682 while (have(1)) { 683 char c = peek(0); 684 switch (c) { 685 case '_': 686 if (misplacedUnderscore()) 687 return syntaxError("misplaced underscore - underscores may only "+ 688 "be used as separators within sequences of valid digits"); 689 skip(1); 690 continue; 691 case '.': 692 return syntaxError("multiple decimal periods are not allowed"); 693 } 694 695 if (kind == DECIMAL) { 696 if (c == 'e' || c == 'E') { 697 return parseExponentPart(); 698 699 } else if (c == 'f' || c == 'F') { 700 if (have(2)) 701 return syntaxError("extra digits/characters "+ 702 "after type suffix "+c); 703 floating = true; 704 isFloat = true; 705 skip(1); 706 } else if (c == 'd' || c == 'D') { 707 if (have(2)) 708 return syntaxError("extra digits/characters "+ 709 "after type suffix "+c); 710 floating = true; 711 skip(1); 712 } else { 713 if (!isDecimalDigit(c)) 714 return unexpectedCharacter(c); 715 pushChar(); 716 fraction = true; 717 } 718 } else { // kind == HEXADECIMAL 719 if (c == 'p' || c == 'P') 720 return parseExponentPart(); 721 722 if (!isHexadecimalDigit(c)) 723 return unexpectedCharacter(c); 724 fraction = true; 725 pushChar(); 726 } 727 } 728 729 return buildLiteral(); 730 } 731 /** 732 * @ast method 733 * @aspect Literals 734 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:878 735 */ 736 737 738 private Literal parseExponentPart() { 739 floating = true; 740 741 // current char is the exponent specifier char 742 pushChar(); 743 744 // exponent sign 745 if (have(1) && (peek(0) == '+' || peek(0) == '-')) 746 pushChar(); 747 748 // while we have at least one more character/digit 749 while (have(1)) { 750 char c = peek(0); 751 switch (c) { 752 case '_': 753 if (misplacedUnderscore()) 754 return syntaxError("misplaced underscore - underscores may only "+ 755 "be used as separators within sequences of valid digits"); 756 skip(1); 757 continue; 758 case '-': 759 case '+': 760 return syntaxError("exponent sign character is only allowed as "+ 761 "the first character of the exponent part of a "+ 762 "floating point literal"); 763 case '.': 764 return syntaxError("multiple decimal periods are not allowed"); 765 case 'p': 766 case 'P': 767 return syntaxError("multiple exponent specifiers are not allowed"); 768 case 'f': 769 case 'F': 770 isFloat = true; 771 case 'd': 772 case 'D': 773 if (have(2)) 774 return syntaxError("extra digits/characters "+ 775 "after type suffix "+c); 776 skip(1); 777 continue; 778 } 779 780 // exponent is a signed integer 781 if (!isDecimalDigit(c)) 782 return unexpectedCharacter(c); 783 pushChar(); 784 exponent = true; 785 } 786 787 return buildLiteral(); 788 } 789 /** 790 * @ast method 791 * 792 */ 793 public NumericLiteral() { 794 super(); 795 796 797 } 798 /** 799 * Initializes the child array to the correct size. 800 * Initializes List and Opt nta children. 801 * @apilevel internal 802 * @ast method 803 * @ast method 804 * 805 */ 806 public void init$Children() { 807 } 808 /** 809 * @ast method 810 * 811 */ 812 public NumericLiteral(String p0) { 813 setLITERAL(p0); 814 } 815 /** 816 * @ast method 817 * 818 */ 819 public NumericLiteral(beaver.Symbol p0) { 820 setLITERAL(p0); 821 } 822 /** 823 * @apilevel low-level 824 * @ast method 825 * 826 */ 827 protected int numChildren() { 828 return 0; 829 } 830 /** 831 * @apilevel internal 832 * @ast method 833 * 834 */ 835 public boolean mayHaveRewrite() { 836 return true; 837 } 838 /** 839 * Replaces the lexeme LITERAL. 840 * @param value The new value for the lexeme LITERAL. 841 * @apilevel high-level 842 * @ast method 843 * 844 */ 845 public void setLITERAL(String value) { 846 tokenString_LITERAL = value; 847 } 848 /** 849 * JastAdd-internal setter for lexeme LITERAL using the Beaver parser. 850 * @apilevel internal 851 * @ast method 852 * 853 */ 854 public void setLITERAL(beaver.Symbol symbol) { 855 if(symbol.value != null && !(symbol.value instanceof String)) 856 throw new UnsupportedOperationException("setLITERAL is only valid for String lexemes"); 857 tokenString_LITERAL = (String)symbol.value; 858 LITERALstart = symbol.getStart(); 859 LITERALend = symbol.getEnd(); 860 } 861 /** 862 * Retrieves the value for the lexeme LITERAL. 863 * @return The value for the lexeme LITERAL. 864 * @apilevel high-level 865 * @ast method 866 * 867 */ 868 public String getLITERAL() { 869 return tokenString_LITERAL != null ? tokenString_LITERAL : ""; 870 } 871 /** 872 * This is a refactored version of Literal.parseLong which supports 873 * binary literals. This version of parseLong is implemented as an 874 * attribute rather than a static method. Perhaps some slight 875 * performance boost could be gained from keeping it static, but with 876 * the loss of declarative- and ReRAGness. 877 * 878 * There exists only a parseLong, and not a parseInteger. Parsing 879 * of regular integer literals works the same, but with stricter 880 * bounds requirements on the resulting parsed value. 881 * @attribute syn 882 * @aspect Literals 883 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:212 884 */ 885 public long parseLong() { 886 ASTNode$State state = state(); 887 try { 888 switch (getKind()) { 889 case HEXADECIMAL: 890 return parseLongHexadecimal(); 891 case OCTAL: 892 return parseLongOctal(); 893 case BINARY: 894 return parseLongBinary(); 895 case DECIMAL: 896 default: 897 return parseLongDecimal(); 898 } 899 } 900 finally { 901 } 902 } 903 /** 904 * Parse a hexadecimal long literal. 905 * 906 * @throws NumberFormatException if the literal is too large. 907 * @attribute syn 908 * @aspect Literals 909 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:231 910 */ 911 public long parseLongHexadecimal() { 912 ASTNode$State state = state(); 913 try { 914 long val = 0; 915 if (digits.length() > 16) { 916 for (int i = 0; i < digits.length()-16; i++) 917 if (digits.charAt(i) != '0') 918 throw new NumberFormatException(""); 919 } 920 for (int i = 0; i < digits.length(); i++) { 921 int c = digits.charAt(i); 922 if (c >= 'a' && c <= 'f') 923 c = c - 'a' + 10; 924 else 925 c = c - '0'; 926 val = val * 16 + c; 927 } 928 return val; 929 } 930 finally { 931 } 932 } 933 /** 934 * Parse an octal long literal. 935 * 936 * @throws NumberFormatException if the literal is too large. 937 * @attribute syn 938 * @aspect Literals 939 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:254 940 */ 941 public long parseLongOctal() { 942 ASTNode$State state = state(); 943 try { 944 long val = 0; 945 if (digits.length() > 21) { 946 for (int i = 0; i < digits.length() - 21; i++) 947 if (i == digits.length() - 21 - 1) { 948 if(digits.charAt(i) != '0' && digits.charAt(i) != '1') 949 throw new NumberFormatException(""); 950 } else { 951 if(digits.charAt(i) != '0') 952 throw new NumberFormatException(""); 953 } 954 } 955 for (int i = 0; i < digits.length(); i++) { 956 int c = digits.charAt(i) - '0'; 957 val = val * 8 + c; 958 } 959 return val; 960 } 961 finally { 962 } 963 } 964 /** 965 * Parse a binary long literal. 966 * 967 * @throws NumberFormatException if the literal is too large. 968 * @attribute syn 969 * @aspect Literals 970 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:278 971 */ 972 public long parseLongBinary() { 973 ASTNode$State state = state(); 974 try { 975 long val = 0; 976 if (digits.length() > 64) { 977 for (int i = 0; i < digits.length()-64; i++) 978 if (digits.charAt(i) != '0') 979 throw new NumberFormatException(""); 980 } 981 for (int i = 0; i < digits.length(); ++i) { 982 if (digits.charAt(i) == '1') 983 val |= 1L << (digits.length()-i-1); 984 } 985 return val; 986 } 987 finally { 988 } 989 } 990 /** 991 * Parse an octal long literal. 992 * @throws NumberFormatException if the literal is too large. 993 * @attribute syn 994 * @aspect Literals 995 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:296 996 */ 997 public long parseLongDecimal() { 998 ASTNode$State state = state(); 999 try { 1000 long val = 0; 1001 long prev = 0; 1002 for (int i = 0; i < digits.length(); i++) { 1003 prev = val; 1004 int c = digits.charAt(i); 1005 if(c >= '0' && c <= '9') 1006 c = c - '0'; 1007 else 1008 throw new NumberFormatException(""); 1009 val = val * 10 + c; 1010 if (val < prev) { 1011 boolean negMinValue = i == (digits.length()-1) && 1012 isNegative() && val == Long.MIN_VALUE; 1013 if (!negMinValue) 1014 throw new NumberFormatException(""); 1015 } 1016 } 1017 if (val == Long.MIN_VALUE) 1018 return val; 1019 if (val < 0) 1020 throw new NumberFormatException(""); 1021 return isNegative() ? -val : val; 1022 } 1023 finally { 1024 } 1025 } 1026 /** 1027 * Utility attribute for literal rewriting. 1028 * Any of the NumericLiteral subclasses have already 1029 * been rewritten and/or parsed, and should not be 1030 * rewritten again. 1031 * 1032 * @return true if this literal is a "raw", not-yet-parsed NumericLiteral 1033 * @attribute syn 1034 * @aspect Literals 1035 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:334 1036 */ 1037 public boolean needsRewrite() { 1038 ASTNode$State state = state(); 1039 try { return true; } 1040 finally { 1041 } 1042 } 1043 /** 1044 * @attribute syn 1045 * @aspect Literals 1046 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:371 1047 */ 1048 public boolean isNegative() { 1049 ASTNode$State state = state(); 1050 try { return getLITERAL().charAt(0) == '-'; } 1051 finally { 1052 } 1053 } 1054 /** 1055 * Get the trimmed digits of this literal, excluding 1056 * underscore, prefix and suffix. 1057 * @attribute syn 1058 * @aspect Literals 1059 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:377 1060 */ 1061 public String getDigits() { 1062 ASTNode$State state = state(); 1063 try { return digits; } 1064 finally { 1065 } 1066 } 1067 /** 1068 * The literal kind tells which kind of literal it is; 1069 * it's either a DECIMAL, HEXADECIMAL, OCTAL or BINARY literal. 1070 * @attribute syn 1071 * @aspect Literals 1072 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:395 1073 */ 1074 public int getKind() { 1075 ASTNode$State state = state(); 1076 try { return kind; } 1077 finally { 1078 } 1079 } 1080 /** 1081 * Get the radix of this literal. 1082 * @return 16 (hex), 10 (decimal), 8 (octal) or 2 (binary) 1083 * @attribute syn 1084 * @aspect Literals 1085 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:414 1086 */ 1087 public int getRadix() { 1088 ASTNode$State state = state(); 1089 try { 1090 switch (kind) { 1091 case HEXADECIMAL: 1092 return 16; 1093 case OCTAL: 1094 return 8; 1095 case BINARY: 1096 return 2; 1097 case DECIMAL: 1098 default: 1099 return 10; 1100 } 1101 } 1102 finally { 1103 } 1104 } 1105 /** 1106 * @return true if the literal is a decimal literal 1107 * @attribute syn 1108 * @aspect Literals 1109 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:431 1110 */ 1111 public boolean isDecimal() { 1112 ASTNode$State state = state(); 1113 try { return kind == DECIMAL; } 1114 finally { 1115 } 1116 } 1117 /** 1118 * @return true if the literal is a hexadecimal literal 1119 * @attribute syn 1120 * @aspect Literals 1121 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:436 1122 */ 1123 public boolean isHex() { 1124 ASTNode$State state = state(); 1125 try { return kind == HEXADECIMAL; } 1126 finally { 1127 } 1128 } 1129 /** 1130 * @return true if the literal is an octal literal 1131 * @attribute syn 1132 * @aspect Literals 1133 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:441 1134 */ 1135 public boolean isOctal() { 1136 ASTNode$State state = state(); 1137 try { return kind == OCTAL; } 1138 finally { 1139 } 1140 } 1141 /** 1142 * @return true if the literal is a binary literal 1143 * @attribute syn 1144 * @aspect Literals 1145 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:446 1146 */ 1147 public boolean isBinary() { 1148 ASTNode$State state = state(); 1149 try { return kind == BINARY; } 1150 finally { 1151 } 1152 } 1153 /** 1154 * @apilevel internal 1155 */ 1156 protected boolean type_computed = false; 1157 /** 1158 * @apilevel internal 1159 */ 1160 protected TypeDecl type_value; 1161 /** 1162 * The type of a NumericLiteral is undefined. 1163 * The literal must be parsed before it can have a type. 1164 * @attribute syn 1165 * @aspect Literals 1166 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:463 1167 */ 1168 @SuppressWarnings({"unchecked", "cast"}) 1169 public TypeDecl type() { 1170 if(type_computed) { 1171 return type_value; 1172 } 1173 ASTNode$State state = state(); 1174 int num = state.boundariesCrossed; 1175 boolean isFinal = this.is$Final(); 1176 type_value = type_compute(); 1177 if(isFinal && num == state().boundariesCrossed){ type_computed = true; } 1178 return type_value; 1179 } 1180 /** 1181 * @apilevel internal 1182 */ 1183 private TypeDecl type_compute() { return unknownType(); } 1184 /** 1185 * @apilevel internal 1186 */ 1187 public ASTNode rewriteTo() { 1188 // Declared in /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag at line 365 1189 if(needsRewrite()) { 1190 state().duringLiterals++; 1191 ASTNode result = rewriteRule0(); 1192 state().duringLiterals--; 1193 return result; 1194 } 1195 1196 return super.rewriteTo(); 1197 } 1198 /** 1199 * @declaredat /home/jesper/svn/JastAddJ/Java7Frontend/Literals.jrag:365 1200 * @apilevel internal 1201 */ private Literal rewriteRule0() { 1202 { 1203 return parse(); 1204 } } 1205 }