Merge pull request #4327 from vkargov/vk-abcremedy
[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                                 dec_found = false;\r
117                         } else if (ch == '.') {\r
118                                 num += '0';\r
119                         }\r
120 \r
121                         if (!dec_found && !is_real) {        \r
122                                 try { \r
123                                         long i = Int64.Parse (num, nstyles);\r
124                                         result.token = Token.INT64;\r
125                                         result.val = i;\r
126 \r
127                                         return num;\r
128                                 } catch {\r
129                                 }\r
130 \r
131                                 try {\r
132                                         long i = (long) UInt64.Parse (num, nstyles);\r
133                                         result.token = Token.INT64;\r
134                                         result.val = i;\r
135 \r
136                                         return num;\r
137                                 } catch {\r
138                                 }\r
139                         }\r
140 \r
141                         try {\r
142                                 double d = Double.Parse (num, nstyles, NumberFormatInfo.InvariantInfo);\r
143                                 result.token = Token.FLOAT64;\r
144                                 result.val = d;\r
145                         } catch {\r
146                                 reader.Unread (num.ToCharArray ());\r
147                                 reader.RestoreLocation ();\r
148                                 num = String.Empty;\r
149                                 Reset ();\r
150                                 throw new ILTokenizingException (reader.Location, num_builder.ToString ());\r
151                         }\r
152                         return num;\r
153                 }\r
154 \r
155                 public string BuildHex ()\r
156                 {\r
157                         ILReader reader = host.Reader;\r
158                         reader.MarkLocation ();\r
159                         StringBuilder num_builder = new StringBuilder ();\r
160                         NumberStyles nstyles = NumberStyles.HexNumber;\r
161 \r
162                         string num;\r
163                         int ch;\r
164                         int peek;\r
165 \r
166                         ch = reader.Read ();\r
167                         if (ch != '0')\r
168                                 throw new ILTokenizingException (reader.Location, ((char) ch).ToString ());\r
169 \r
170                         ch = reader.Read ();\r
171 \r
172                         if (ch != 'x' && ch != 'X')\r
173                                 throw new ILTokenizingException (reader.Location, "0" + (char) ch);\r
174 \r
175                         do {\r
176                                 ch = reader.Read ();\r
177                                 peek = reader.Peek ();\r
178                                 num_builder.Append ((char) ch);\r
179 \r
180                                 if (!is_hex ((char) peek))\r
181                                         break;\r
182 \r
183                                 if (num_builder.Length == 32)\r
184                                         throw new ILTokenizingException (reader.Location, num_builder.ToString ());\r
185 \r
186                         } while (ch != -1);\r
187 \r
188                         num = num_builder.ToString ();\r
189 \r
190                         try {\r
191                                 long i = (long) UInt64.Parse (num, nstyles);\r
192                                 //if (i < Int32.MinValue || i > Int32.MaxValue) {\r
193                                         result.token = Token.INT64;\r
194                                         result.val = i;\r
195                                 //} else {\r
196                                 //        result.token = Token.INT32;\r
197                                 //        result.val = (int) i;\r
198                                 //}\r
199                         } catch {\r
200                                 string tnum = num;\r
201                                 reader.Unread (num.ToCharArray ());\r
202                                 reader.RestoreLocation ();\r
203                                 num = String.Empty;\r
204                                 Reset ();\r
205                                 throw new ILTokenizingException (reader.Location, tnum);\r
206                         }\r
207                         return num;\r
208                 }\r
209 \r
210                 /// <summary>\r
211                 /// </summary>\r
212                 public ILToken ResultToken {\r
213                         get {\r
214                                 return result;\r
215                         }\r
216                 }\r
217 \r
218 \r
219         }\r
220 \r
221 }\r