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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 91475 - (hide annotations)
Fri Mar 3 10:19:32 2006 UTC (13 years, 11 months ago) by ericb
File size: 8391 byte(s)
Synchronized with ISE 5.7.0726

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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.23