merge -r 53370:58178
[mono.git] / mcs / ilasm / scanner / NumberHelper.cs
1 // NumberHelper.cs\r
2 // Author: Sergey Chaban (serge@wildwestsoftware.com)\r
3 \r
4 using System;\r
5 using System.Text;\r
6 using System.Globalization;\r
7 \r
8 namespace Mono.ILASM {\r
9 \r
10         /// <summary>\r
11         /// </summary>\r
12         internal class NumberHelper : StringHelperBase {\r
13 \r
14                 private ILToken result;\r
15 \r
16                 /// <summary>\r
17                 /// </summary>\r
18                 /// <param name="host"></param>\r
19                 public NumberHelper (ILTokenizer host) : base (host)\r
20                 {\r
21                         Reset ();\r
22                 }\r
23 \r
24 \r
25                 private void Reset ()\r
26                 {\r
27                         result = ILToken.Invalid.Clone() as ILToken;\r
28                 }\r
29 \r
30                 /// <summary>\r
31                 /// </summary>\r
32                 /// <returns></returns>\r
33                 public override bool Start (char ch)\r
34                 {\r
35                         bool res = (Char.IsDigit (ch) || ch == '-' || (ch == '.' && Char.IsDigit ((char) host.Reader.Peek ())));\r
36                         Reset ();\r
37                         return res;\r
38                 }\r
39 \r
40                 bool is_hex (int e)\r
41                 {\r
42                         return (e >= '0' && e <= '9') || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f');\r
43                 }\r
44 \r
45                 bool is_sign (int ch)\r
46                 {\r
47                         return ((ch == '+') || (ch == '-'));\r
48                 }\r
49 \r
50                 bool is_e (int ch)\r
51                 {\r
52                         return ((ch == 'e') || (ch == 'E'));\r
53                 }\r
54 \r
55                 /// <summary>\r
56                 /// </summary>\r
57                 /// <returns></returns>\r
58                 public override string Build ()\r
59                 {\r
60                         ILReader reader = host.Reader;\r
61                         reader.MarkLocation ();\r
62                         StringBuilder num_builder = new StringBuilder ();\r
63                         string num;\r
64                         int ch;\r
65                         int peek;\r
66                         bool is_real = false;\r
67                         bool dec_found = false;\r
68 \r
69                         NumberStyles nstyles = NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint |\r
70                                 NumberStyles.AllowLeadingSign;\r
71 \r
72                         ch = reader.Read ();\r
73                         peek = reader.Peek ();\r
74                         reader.Unread (ch);\r
75 \r
76                         if (ch == '0' && (peek == 'x' || peek == 'X'))\r
77                                 return BuildHex ();\r
78 \r
79                         if (is_sign (reader.Peek ()))\r
80                                 num_builder.Append ((char) reader.Read ());\r
81 \r
82                         do {\r
83                                 ch = reader.Read ();\r
84                                 peek = reader.Peek ();\r
85                                 num_builder.Append ((char) ch);\r
86 \r
87                                 if (is_e (ch)) {\r
88                                         if (is_real)\r
89                                                 throw new ILTokenizingException (reader.Location, num_builder.ToString ());\r
90 \r
91                                         is_real = true;\r
92                                 }\r
93                                 if (ch == '.')\r
94                                         dec_found = true;\r
95                                 if (!is_hex(peek) &&\r
96                                     !(peek == '.' && !dec_found) && !is_e (peek) &&\r
97                                     !(is_sign (peek) && is_real)) {\r
98                                         break;\r
99                                 }\r
100                         } while (ch != -1);\r
101 \r
102                         num = num_builder.ToString ();\r
103 \r
104                         // Check for hexbytes\r
105                         if (num.Length == 2) {\r
106                                 if (Char.IsLetter (num[0]) || Char.IsLetter (num[1])) {\r
107                                         result.token = Token.HEXBYTE;\r
108                                         result.val = Byte.Parse (num, NumberStyles.HexNumber);\r
109                                         return num;\r
110                                 }\r
111                         }\r
112 \r
113                         if (ch == '.' && peek == '.') {\r
114                                 num = num.Substring (0, num.Length-1);\r
115                                 reader.Unread ('.');\r
116                         } else if (ch == '.') {\r
117                                 num += '0';\r
118                         }\r
119 \r
120                         try {\r
121                                 if (dec_found || is_real) {\r
122                                         double d = Double.Parse (num, nstyles, NumberFormatInfo.InvariantInfo);\r
123                                         result.token = Token.FLOAT64;\r
124                                         result.val = d;\r
125                                 } else {\r
126                                         long i = Int64.Parse (num, nstyles);\r
127                                         // if (i < Int32.MinValue || i > Int32.MaxValue) {\r
128                                                 result.token = Token.INT64;\r
129                                                 result.val = i;\r
130                                         // } else {\r
131                                         //        result.token = Token.INT32;\r
132                                         //        result.val = (int) i;\r
133                                         // }\r
134                                 }\r
135                         } catch {\r
136                                 reader.Unread (num.ToCharArray ());\r
137                                 reader.RestoreLocation ();\r
138                                 num = String.Empty;\r
139                                 Reset ();\r
140                                 throw new ILTokenizingException (reader.Location, num_builder.ToString ());\r
141                         }\r
142                         return num;\r
143                 }\r
144 \r
145                 public string BuildHex ()\r
146                 {\r
147                         ILReader reader = host.Reader;\r
148                         reader.MarkLocation ();\r
149                         StringBuilder num_builder = new StringBuilder ();\r
150                         NumberStyles nstyles = NumberStyles.HexNumber;\r
151 \r
152                         string num;\r
153                         int ch;\r
154                         int peek;\r
155 \r
156                         ch = reader.Read ();\r
157                         if (ch != '0')\r
158                                 throw new ILTokenizingException (reader.Location, ((char) ch).ToString ());\r
159 \r
160                         ch = reader.Read ();\r
161 \r
162                         if (ch != 'x' && ch != 'X')\r
163                                 throw new ILTokenizingException (reader.Location, "0" + (char) ch);\r
164 \r
165                         do {\r
166                                 ch = reader.Read ();\r
167                                 peek = reader.Peek ();\r
168                                 num_builder.Append ((char) ch);\r
169 \r
170                                 if (!is_hex ((char) peek))\r
171                                         break;\r
172 \r
173                                 if (num_builder.Length == 32)\r
174                                         throw new ILTokenizingException (reader.Location, num_builder.ToString ());\r
175 \r
176                         } while (ch != -1);\r
177 \r
178                         num = num_builder.ToString ();\r
179 \r
180                         try {\r
181                                 long i = (long) UInt64.Parse (num, nstyles);\r
182                                 //if (i < Int32.MinValue || i > Int32.MaxValue) {\r
183                                         result.token = Token.INT64;\r
184                                         result.val = i;\r
185                                 //} else {\r
186                                 //        result.token = Token.INT32;\r
187                                 //        result.val = (int) i;\r
188                                 //}\r
189                         } catch {\r
190                                 string tnum = num;\r
191                                 reader.Unread (num.ToCharArray ());\r
192                                 reader.RestoreLocation ();\r
193                                 num = String.Empty;\r
194                                 Reset ();\r
195                                 throw new ILTokenizingException (reader.Location, tnum);\r
196                         }\r
197                         return num;\r
198                 }\r
199 \r
200                 /// <summary>\r
201                 /// </summary>\r
202                 public ILToken ResultToken {\r
203                         get {\r
204                                 return result;\r
205                         }\r
206                 }\r
207 \r
208 \r
209         }\r
210 \r
211 }\r