/[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 91477 - (hide annotations)
Sun Jan 14 09:47:13 2007 UTC (13 years, 1 month ago) by ericb
File size: 8768 byte(s)
Synchronized with ISE 6.0.65740
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 91477 -- Initialize.
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 ericb 91477 -- Is conversion type `type' valid?
38 ericb 91454 do
39 ericb 91475 Result := real_double_type_valid (type)
40 ericb 91454 end
41 ericb 91475
42 ericb 91454 overflowed: BOOLEAN is
43 ericb 91477 -- Is real number parsed so far overflowed?
44 ericb 91454 do
45     Result := False
46     end
47 ericb 91475
48     underflowed: BOOLEAN is
49 ericb 91477 -- Is real number parsed so far underflowed?
50 ericb 91454 do
51     Result := False
52 ericb 91475 end
53    
54 ericb 91454 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 ericb 91475
62 ericb 91454 separators_valid (separators: STRING): BOOLEAN is
63 ericb 91477 -- Are separators contained in `separators' valid?
64 ericb 91454 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 ericb 91475
87 ericb 91454 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 ericb 91475
93 ericb 91454 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 ericb 91475
99 ericb 91454 is_part_of_double: BOOLEAN is
100 ericb 91475 -- Is character sequence that has been parsed so far a valid start part of double?
101 ericb 91454 do
102     Result := last_state /= 9
103     end
104 ericb 91475
105 ericb 91454 is_part_of_real: BOOLEAN is
106 ericb 91475 -- Is character sequence that has been parsed so far a valid start part of real?
107 ericb 91454 do
108     Result := is_part_of_double
109     end
110 ericb 91475
111 ericb 91454 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 ericb 91475 end
125 ericb 91454 end
126 ericb 91475
127 ericb 91454 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 ericb 91477 -- Reset current convertor to parse real number string of type `type'.
137 ericb 91454 do
138     conversion_type := type
139     sign := 0
140     last_state := 0
141 ericb 91475
142 ericb 91454 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 ericb 91475
161 ericb 91454 feature -- Parse
162    
163 ericb 91477 parse_string_with_type (s: STRING_GENERAL; type: INTEGER) is
164     -- Parse string `s' as real number of type `type'.
165 ericb 91454 local
166     i: INTEGER
167 ericb 91475 l_c: INTEGER
168 ericb 91454 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 ericb 91477 parse_character (s.code (i).to_character_8)
177 ericb 91454 i := i + 1
178     end
179     end
180    
181     parse_character (c: CHARACTER) is
182 ericb 91477 -- Parse character `c'.
183 ericb 91454 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 ericb 91475
197 ericb 91454 -- 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 ericb 91475 fractional_divider := 10.0
260     needs_digit := False
261 ericb 91454 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 ericb 91475 fractional_divider := fractional_divider * 10.0
274 ericb 91454 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 ericb 91475 last_state := 8
279 ericb 91454 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 ericb 91475 end
323     end
324    
325 ericb 91454 feature{NONE} -- Implementation
326 ericb 91475
327 ericb 91454 natural_part: DOUBLE
328     fractional_part: DOUBLE
329     fractional_divider: DOUBLE
330     exponent: INTEGER
331     is_negative: BOOLEAN
332 ericb 91475 has_negative_exponent: BOOLEAN
333 ericb 91454 has_fractional_part: BOOLEAN
334     needs_digit: BOOLEAN
335     -- Used to calculate real/double value
336 ericb 91475
337 ericb 91454 end

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.23