/[eiffelstudio]/FreeELKS/trunk/library/kernel/string_to_real_convertor.e
ViewVC logotype

Contents of /FreeELKS/trunk/library/kernel/string_to_real_convertor.e

Parent Directory Parent Directory | Revision Log Revision Log


Revision 91477 - (show annotations)
Sun Jan 14 09:47:13 2007 UTC (13 years ago) by ericb
File size: 8768 byte(s)
Synchronized with ISE 6.0.65740
1 indexing
2 description: "String to real/double convertor"
3 library: "Free implementation of ELKS library"
4 copyright: "Copyright (c) 1986-2006, Eiffel Software and others"
5 license: "Eiffel Forum License v2 (see forum.txt)"
6 date: "$Date$"
7 revision: "$Revision$"
8
9 class
10 STRING_TO_REAL_CONVERTOR
11
12 inherit
13 STRING_TO_NUMERIC_CONVERTOR
14
15 create
16 make
17
18 feature{NONE} -- Initialization
19
20 make is
21 -- Initialize.
22 do
23 set_leading_separators (" ")
24 set_trailing_separators (" ")
25 ensure
26 leading_separators_set: leading_separators.is_equal (" ")
27 trailing_separators_set: trailing_separators.is_equal (" ")
28 leading_separators_not_acceptable:
29 not leading_separators_acceptable
30 trailing_separatorsnot_acceptable:
31 not trailing_separators_acceptable
32 end
33
34 feature -- Status reporting
35
36 conversion_type_valid (type: INTEGER): BOOLEAN is
37 -- Is conversion type `type' valid?
38 do
39 Result := real_double_type_valid (type)
40 end
41
42 overflowed: BOOLEAN is
43 -- Is real number parsed so far overflowed?
44 do
45 Result := False
46 end
47
48 underflowed: BOOLEAN is
49 -- Is real number parsed so far underflowed?
50 do
51 Result := False
52 end
53
54 parse_successful: BOOLEAN is
55 -- This only means we didn't enter an invalid state when parsing,
56 -- it doesn't mean that we have got an valid double/real number.
57 -- You need to check `is_double' or `is_real'.
58 do
59 Result := (last_state /= 9)
60 end
61
62 separators_valid (separators: STRING): BOOLEAN is
63 -- Are separators contained in `separators' valid?
64 local
65 i: INTEGER
66 c: CHARACTER
67 l_c: INTEGER
68 done: BOOLEAN
69 do
70 from
71 i := 1
72 l_c := separators.count
73 done := False
74 Result := True
75 until
76 i > l_c or done
77 loop
78 c := separators.item (i)
79 if (c >='0' and c <= '9') or c ='+' or c = '-' or c = 'E' or c = 'e' then
80 done := True
81 Result := False
82 end
83 i := i + 1
84 end
85 end
86
87 is_integral_double: BOOLEAN is
88 -- Is character sequence that has been parsed represents a valid double?
89 do
90 Result := (last_state > 1 and last_state < 9) and (not needs_digit)
91 end
92
93 is_integral_real: BOOLEAN is
94 -- Is character sequence that has been parsed represents a valid real?
95 do
96 Result := is_integral_double
97 end
98
99 is_part_of_double: BOOLEAN is
100 -- Is character sequence that has been parsed so far a valid start part of double?
101 do
102 Result := last_state /= 9
103 end
104
105 is_part_of_real: BOOLEAN is
106 -- Is character sequence that has been parsed so far a valid start part of real?
107 do
108 Result := is_part_of_double
109 end
110
111 parsed_double: DOUBLE is
112 -- Parsed double value
113 do
114 if has_negative_exponent then
115 exponent := -exponent
116 end
117 if has_fractional_part then
118 natural_part := natural_part + fractional_part / fractional_divider
119 end
120 if is_negative then
121 Result := -natural_part * (10.0 ^ exponent)
122 else
123 Result := natural_part * (10.0 ^ exponent)
124 end
125 end
126
127 parsed_real: REAL is
128 -- Parsed real value
129 do
130 Result := parsed_double
131 end
132
133 feature -- Status setting
134
135 reset (type: INTEGER) is
136 -- Reset current convertor to parse real number string of type `type'.
137 do
138 conversion_type := type
139 sign := 0
140 last_state := 0
141
142 natural_part := 0
143 fractional_part := 0
144 fractional_divider := 0
145 exponent := 0
146 is_negative := False
147 has_negative_exponent := False
148 has_fractional_part := False
149 needs_digit := False
150 ensure then
151 natural_part_set: natural_part = 0
152 fractional_part_set: fractional_part = 0
153 fractional_divider_set: fractional_divider = 0
154 exponent_set: exponent = 0
155 is_negative_set: is_negative = False
156 has_negative_exponent_set: has_negative_exponent = False
157 has_fractional_part_set: has_fractional_part = False
158 needs_digit_set: needs_digit = False
159 end
160
161 feature -- Parse
162
163 parse_string_with_type (s: STRING_GENERAL; type: INTEGER) is
164 -- Parse string `s' as real number of type `type'.
165 local
166 i: INTEGER
167 l_c: INTEGER
168 do
169 reset (type)
170 from
171 i := 1
172 l_c := s.count
173 until
174 i > l_c or last_state = 9
175 loop
176 parse_character (s.code (i).to_character_8)
177 i := i + 1
178 end
179 end
180
181 parse_character (c: CHARACTER) is
182 -- Parse character `c'.
183 do
184 -- Parse according to the following specification:
185 -- Real/double number specification:
186 -- Real_literal = Mantissa [Exponent_part]
187 -- Exponent_part = "E" Exponent
188 -- | "e" Exponent
189 -- Exponent = Integer_literal
190 -- Mantissa = Decimal_literal
191 -- Decimal_literal = Integer_literal ["." [Integer]] | [Sign] "." Integer
192 -- Integer_literal = [Sign] Integer
193 -- Sign = "+" | "-"
194 -- Integer = Digit | Digit Integer
195 -- Digit = "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9".
196
197 -- last_state = 0 : waiting sign or double value.
198 -- last_state = 1 : sign read, waiting double value.
199 -- last_state = 2 : in the number.
200 -- last_state = 3 : decimal point read
201 -- last_state = 4 : in fractional part
202 -- last_state = 5 : read 'E' or 'e' for scientific notation
203 -- last_state = 6 : sign of exponent read, waiting for digit.
204 -- last_state = 7 : in exponent
205 -- last_state = 8 : after the number.
206 -- last_state = 9 : error state.
207 inspect
208 last_state
209 when 0 then
210 -- Let's find beginning of double.
211 if c.is_digit then
212 last_state := 2
213 natural_part := c.code - 48
214 elseif c = '+' then
215 last_state := 1
216 elseif c = '-' then
217 last_state := 1
218 is_negative := True
219 elseif (leading_separators_acceptable and then leading_separators.has (c)) then
220 -- Do nothing.
221 elseif c = '.' then
222 last_state := 3
223 needs_digit := True
224 else
225 last_state := 9
226 end
227 when 1 then
228 -- Let's find first digit after sign.
229 if c.is_digit then
230 last_state := 2
231 natural_part := c.code - 48
232 elseif c = '.' then
233 last_state := 3
234 needs_digit := True
235 else
236 last_state := 9
237 end
238 when 2 then
239 -- Let's find more digit for mantissa.
240 if c.is_digit then
241 natural_part := natural_part * 10.0 + c.code - 48
242 elseif c = '.' then
243 last_state := 3
244 needs_digit := False
245 elseif (trailing_separators_acceptable and then trailing_separators.has (c)) then
246 last_state := 8
247 elseif c.as_lower = 'e' then
248 -- Not conform to ECMA standard, just for backward compatibility.
249 last_state := 5
250 else
251 last_state := 9
252 end
253 when 3 then
254 -- We are done with mantissa, now reads decimal part
255 if c.is_digit then
256 last_state := 4
257 has_fractional_part := True
258 fractional_part := c.code - 48
259 fractional_divider := 10.0
260 needs_digit := False
261 elseif c.as_lower = 'e' and not needs_digit then
262 needs_digit := True
263 last_state := 5
264 elseif (trailing_separators_acceptable and then trailing_separators.has (c)) then
265 last_state := 8
266 else
267 last_state := 9
268 end
269 when 4 then
270 -- Continue reading decimal part
271 if c.is_digit then
272 fractional_part := fractional_part * 10.0 + (c.code - 48)
273 fractional_divider := fractional_divider * 10.0
274 elseif c.as_lower = 'e' then
275 needs_digit := True
276 last_state := 5
277 elseif (trailing_separators_acceptable and then trailing_separators.has (c)) then
278 last_state := 8
279 else
280 last_state := 9
281 end
282 when 5 then
283 -- Found `e' or `E'. Read signs of exponent if any.
284 if c = '-' then
285 has_negative_exponent := True
286 last_state := 6
287 elseif c = '+' then
288 last_state := 6
289 elseif c.is_digit then
290 needs_digit := False
291 last_state := 7
292 exponent := c.code - 48
293 else
294 -- We get here if after reading the sign we do not
295 -- find a digit, or if there is no sign there was no
296 -- digit.
297 last_state := 9
298 end
299 when 6 then
300 -- Sign of exponent read, waiting for digit
301 if c.is_digit then
302 last_state := 7
303 exponent := c.code - 48
304 needs_digit := False
305 else
306 last_state := 9
307 end
308 when 7 then
309 -- Continue reading exponent
310 if c.is_digit then
311 exponent := exponent * 10 + c.code - 48
312 elseif (trailing_separators_acceptable and then trailing_separators.has (c)) then
313 last_state := 8
314 else
315 last_state := 9
316 end
317 when 8 then
318 if not trailing_separators.has (c) then
319 last_state := 9
320 end
321 else
322 end
323 end
324
325 feature{NONE} -- Implementation
326
327 natural_part: DOUBLE
328 fractional_part: DOUBLE
329 fractional_divider: DOUBLE
330 exponent: INTEGER
331 is_negative: BOOLEAN
332 has_negative_exponent: BOOLEAN
333 has_fractional_part: BOOLEAN
334 needs_digit: BOOLEAN
335 -- Used to calculate real/double value
336
337 end

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.23