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