first scanner /parser copied from the jdt java version
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / ast / LongLiteral.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v0.5 
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v05.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
12
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
14 import net.sourceforge.phpdt.internal.compiler.impl.*;
15 import net.sourceforge.phpdt.internal.compiler.codegen.*;
16 import net.sourceforge.phpdt.internal.compiler.lookup.*;
17
18 public class LongLiteral extends NumberLiteral {
19         long value;
20         
21         static final Constant FORMAT_ERROR = new DoubleConstant(1.0/0.0); // NaN;       
22                 
23 public LongLiteral(char[] token, int s,int e) {
24         super(token, s,e);
25 }
26 public LongLiteral(char[] token, int s,int e, long value) {
27         this(token, s,e);
28         this.value = value;
29 }
30 public void computeConstant() {
31         //the overflow (when radix=10) is tested using the fact that
32         //the value should always grow during its computation
33
34         int length = source.length - 1; //minus one because the last char is 'l' or 'L'
35         
36         long computedValue ;
37         if (source[0] == '0')
38         {       if (length == 1) {      constant = Constant.fromValue(0L);      return; }
39                 final int shift,radix;
40                 int j ;
41                 if ( (source[1] == 'x') | (source[1] == 'X') )
42                 {       shift = 4 ; j = 2; radix = 16;}
43                 else
44                 {       shift = 3 ; j = 1; radix = 8;}
45                 int nbDigit = 0;
46                 while (source[j]=='0') 
47                 {       j++; //jump over redondant zero
48                         if ( j == length)
49                         {       //watch for 0000000000000L
50                                 constant = Constant.fromValue(value = 0L);
51                                 return ;}}
52                                 
53                 int digitValue ;
54                 if ((digitValue = Character.digit(source[j++],radix))   < 0 )   
55                 {       constant = FORMAT_ERROR; return ;}
56                 if (digitValue >= 8) nbDigit = 4;
57                 else    if (digitValue >= 4) nbDigit = 3;
58                                 else    if (digitValue >= 2) nbDigit = 2;
59                                                 else nbDigit = 1; //digitValue is not 0
60                 computedValue = digitValue ;
61                 while (j<length)
62                 {       if ((digitValue = Character.digit(source[j++],radix))   < 0 )   
63                         {       constant = FORMAT_ERROR; return ;}
64                         if ((nbDigit += shift) > 64) return /*constant stays null*/ ;
65                         computedValue = (computedValue<<shift) | digitValue ;}}
66
67         else
68         {       //-----------case radix=10-----------------
69                 long previous = computedValue = 0;
70                 for (int i = 0 ; i < length; i++) 
71                 {       int digitValue ;        
72                         if ((digitValue = Character.digit(source[i], 10)) < 0 ) return /*constant stays null*/ ;
73                         previous = computedValue;
74                         computedValue = 10 * computedValue + digitValue ;
75                         if (previous > computedValue) return /*constant stays null*/;}}
76         
77         constant = Constant.fromValue(value = computedValue);
78 }
79 /**
80  * Code generation for long literal
81  *
82  * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
83  * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
84  * @param valueRequired boolean
85  */ 
86 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
87         int pc = codeStream.position;
88         if (valueRequired)
89                 if ((implicitConversion >> 4) == T_long)
90                         codeStream.generateInlinedValue(value);
91                 else
92                         codeStream.generateConstant(constant, implicitConversion);
93         codeStream.recordPositionsFrom(pc, this.sourceStart);
94 }
95 public TypeBinding literalType(BlockScope scope) {
96         return LongBinding;
97 }
98 public final boolean mayRepresentMIN_VALUE(){
99         //a special autorized int literral is 9223372036854775808L
100         //which is ONE over the limit. This special case 
101         //only is used in combinaison with - to denote
102         //the minimal value of int -9223372036854775808L
103
104         return ((source.length == 20) &&
105                         (source[0] == '9') &&
106                         (source[1] == '2') &&
107                         (source[2] == '2') &&
108                         (source[3] == '3') &&                   
109                         (source[4] == '3') &&
110                         (source[5] == '7') &&
111                         (source[6] == '2') &&
112                         (source[7] == '0') &&                   
113                         (source[8] == '3') &&
114                         (source[9] == '6') &&
115                         (source[10] == '8') &&
116                         (source[11] == '5') &&
117                         (source[12] == '4') &&                  
118                         (source[13] == '7') &&
119                         (source[14] == '7') &&
120                         (source[15] == '5') &&
121                         (source[16] == '8') &&                  
122                         (source[17] == '0') &&
123                         (source[18] == '8'));}
124 public TypeBinding resolveType(BlockScope scope) {
125         // the format may be incorrect while the scanner could detect
126         // such error only on painfull tests...easier and faster here
127
128         TypeBinding tb = super.resolveType(scope);
129         if (constant == FORMAT_ERROR) {
130                 constant = NotAConstant;
131                 scope.problemReporter().constantOutOfFormat(this);
132                 return null;
133         }
134         return tb;
135 }
136 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
137         visitor.visit(this, scope);
138         visitor.endVisit(this, scope);
139 }
140 }