2010-06-04 Jb Evain <jbevain@novell.com>
[mcs.git] / ilasm / scanner / NumberHelper.cs
blob022dacbd62737fc6cb6a607fc55d6293afe99090
1 // NumberHelper.cs
2 // Author: Sergey Chaban (serge@wildwestsoftware.com)
4 using System;
5 using System.Text;
6 using System.Globalization;
8 namespace Mono.ILASM {
10 /// <summary>
11 /// </summary>
12 internal class NumberHelper : StringHelperBase {
14 private ILToken result;
16 /// <summary>
17 /// </summary>
18 /// <param name="host"></param>
19 public NumberHelper (ILTokenizer host) : base (host)
21 Reset ();
25 private void Reset ()
27 result = ILToken.Invalid.Clone() as ILToken;
30 /// <summary>
31 /// </summary>
32 /// <returns></returns>
33 public override bool Start (char ch)
35 bool res = (Char.IsDigit (ch) || ch == '-' || (ch == '.' && Char.IsDigit ((char) host.Reader.Peek ())));
36 Reset ();
37 return res;
40 bool is_hex (int e)
42 return (e >= '0' && e <= '9') || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f');
45 bool is_sign (int ch)
47 return ((ch == '+') || (ch == '-'));
50 bool is_e (int ch)
52 return ((ch == 'e') || (ch == 'E'));
55 /// <summary>
56 /// </summary>
57 /// <returns></returns>
58 public override string Build ()
60 ILReader reader = host.Reader;
61 reader.MarkLocation ();
62 StringBuilder num_builder = new StringBuilder ();
63 string num;
64 int ch;
65 int peek;
66 bool is_real = false;
67 bool dec_found = false;
69 NumberStyles nstyles = NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint |
70 NumberStyles.AllowLeadingSign;
72 ch = reader.Read ();
73 peek = reader.Peek ();
74 reader.Unread (ch);
76 if (ch == '0' && (peek == 'x' || peek == 'X'))
77 return BuildHex ();
79 if (is_sign (reader.Peek ()))
80 num_builder.Append ((char) reader.Read ());
82 do {
83 ch = reader.Read ();
84 peek = reader.Peek ();
85 num_builder.Append ((char) ch);
87 if (is_e (ch)) {
88 if (is_real)
89 throw new ILTokenizingException (reader.Location, num_builder.ToString ());
91 is_real = true;
93 if (ch == '.')
94 dec_found = true;
95 if (!is_hex(peek) &&
96 !(peek == '.' && !dec_found) && !is_e (peek) &&
97 !(is_sign (peek) && is_real)) {
98 break;
100 } while (ch != -1);
102 num = num_builder.ToString ();
104 // Check for hexbytes
105 if (num.Length == 2) {
106 if (Char.IsLetter (num[0]) || Char.IsLetter (num[1])) {
107 result.token = Token.HEXBYTE;
108 result.val = Byte.Parse (num, NumberStyles.HexNumber);
109 return num;
113 if (ch == '.' && peek == '.') {
114 num = num.Substring (0, num.Length-1);
115 reader.Unread ('.');
116 dec_found = false;
117 } else if (ch == '.') {
118 num += '0';
121 if (!dec_found && !is_real) {
122 try {
123 long i = Int64.Parse (num, nstyles);
124 result.token = Token.INT64;
125 result.val = i;
127 return num;
128 } catch {
131 try {
132 long i = (long) UInt64.Parse (num, nstyles);
133 result.token = Token.INT64;
134 result.val = i;
136 return num;
137 } catch {
141 try {
142 double d = Double.Parse (num, nstyles, NumberFormatInfo.InvariantInfo);
143 result.token = Token.FLOAT64;
144 result.val = d;
145 } catch {
146 reader.Unread (num.ToCharArray ());
147 reader.RestoreLocation ();
148 num = String.Empty;
149 Reset ();
150 throw new ILTokenizingException (reader.Location, num_builder.ToString ());
152 return num;
155 public string BuildHex ()
157 ILReader reader = host.Reader;
158 reader.MarkLocation ();
159 StringBuilder num_builder = new StringBuilder ();
160 NumberStyles nstyles = NumberStyles.HexNumber;
162 string num;
163 int ch;
164 int peek;
166 ch = reader.Read ();
167 if (ch != '0')
168 throw new ILTokenizingException (reader.Location, ((char) ch).ToString ());
170 ch = reader.Read ();
172 if (ch != 'x' && ch != 'X')
173 throw new ILTokenizingException (reader.Location, "0" + (char) ch);
175 do {
176 ch = reader.Read ();
177 peek = reader.Peek ();
178 num_builder.Append ((char) ch);
180 if (!is_hex ((char) peek))
181 break;
183 if (num_builder.Length == 32)
184 throw new ILTokenizingException (reader.Location, num_builder.ToString ());
186 } while (ch != -1);
188 num = num_builder.ToString ();
190 try {
191 long i = (long) UInt64.Parse (num, nstyles);
192 //if (i < Int32.MinValue || i > Int32.MaxValue) {
193 result.token = Token.INT64;
194 result.val = i;
195 //} else {
196 // result.token = Token.INT32;
197 // result.val = (int) i;
199 } catch {
200 string tnum = num;
201 reader.Unread (num.ToCharArray ());
202 reader.RestoreLocation ();
203 num = String.Empty;
204 Reset ();
205 throw new ILTokenizingException (reader.Location, tnum);
207 return num;
210 /// <summary>
211 /// </summary>
212 public ILToken ResultToken {
213 get {
214 return result;