rev |
line source |
jbe/bsw@0
|
1 local digit_set = {
|
jbe/bsw@0
|
2 ["0"] = true, ["1"] = true, ["2"] = true, ["3"] = true, ["4"] = true,
|
jbe/bsw@0
|
3 ["5"] = true, ["6"] = true, ["7"] = true, ["8"] = true, ["9"] = true
|
jbe/bsw@0
|
4 }
|
jbe/bsw@0
|
5
|
jbe/bsw@0
|
6 function parse.decimal(str, dest_type, options)
|
jbe/bsw@0
|
7 local str = parse._pre_fold(str)
|
jbe/bsw@0
|
8 local dest_type = dest_type or atom.number
|
jbe/bsw@0
|
9 local options = options or {}
|
jbe/bsw@0
|
10 if str == "" then
|
jbe/bsw@0
|
11 return nil
|
jbe/bsw@0
|
12 else
|
jbe/bsw@0
|
13 local decimal_shift = options.decimal_shift or 0
|
jbe/bsw@0
|
14 if decimal_shift == true then
|
jbe/bsw@0
|
15 decimal_shift = options.precision
|
jbe/bsw@0
|
16 end
|
jbe/bsw@0
|
17 local decimal_point = locale.get("decimal_point") or "."
|
jbe/bsw@0
|
18 local negative = nil
|
jbe/bsw@0
|
19 local int = 0
|
jbe/bsw@0
|
20 local frac = 0
|
jbe/bsw@0
|
21 local precision = 0
|
jbe/bsw@0
|
22 local after_point = false
|
jbe/bsw@0
|
23 for char in string.gmatch(str, ".") do
|
jbe/bsw@0
|
24 local skip = false
|
jbe/bsw@0
|
25 if negative == nil then
|
jbe/bsw@0
|
26 if char == "+" then
|
jbe/bsw@0
|
27 negative = false
|
jbe/bsw@0
|
28 skip = true
|
jbe/bsw@0
|
29 elseif char == "-" then -- real minus sign already replaced by _pre_fold
|
jbe/bsw@0
|
30 negative = true
|
jbe/bsw@0
|
31 skip = true
|
jbe/bsw@0
|
32 end
|
jbe/bsw@0
|
33 end
|
jbe/bsw@0
|
34 if not skip then
|
jbe/bsw@0
|
35 if digit_set[char] then
|
jbe/bsw@0
|
36 if after_point then
|
jbe/bsw@0
|
37 if decimal_shift > 0 then
|
jbe/bsw@0
|
38 int = 10 * int + tonumber(char)
|
jbe/bsw@0
|
39 decimal_shift = decimal_shift - 1
|
jbe/bsw@0
|
40 else
|
jbe/bsw@0
|
41 frac = 10 * frac + tonumber(char)
|
jbe/bsw@0
|
42 precision = precision + 1
|
jbe/bsw@0
|
43 end
|
jbe/bsw@0
|
44 else
|
jbe/bsw@0
|
45 int = 10 * int + tonumber(char)
|
jbe/bsw@0
|
46 end
|
jbe/bsw@0
|
47 elseif char == decimal_point then
|
jbe/bsw@0
|
48 if after_point then
|
jbe/bsw@0
|
49 return dest_type.invalid
|
jbe/bsw@0
|
50 else
|
jbe/bsw@0
|
51 after_point = true
|
jbe/bsw@0
|
52 end
|
jbe/bsw@0
|
53 elseif char ~= " " then -- TODO: ignore thousand seperator too, when supported by format.decimal
|
jbe/bsw@0
|
54 return dest_type.invalid
|
jbe/bsw@0
|
55 end
|
jbe/bsw@0
|
56 end
|
jbe/bsw@0
|
57 end
|
jbe/bsw@0
|
58 int = int * 10 ^ decimal_shift
|
jbe/bsw@0
|
59 if dest_type == atom.number or dest_type == atom.integer then
|
jbe/bsw@0
|
60 if dest_type == atom.integer and frac ~= 0 then
|
jbe/bsw@0
|
61 return atom.not_a_number
|
jbe/bsw@0
|
62 else
|
jbe/bsw@0
|
63 local f = int + frac / 10 ^ precision
|
jbe/bsw@0
|
64 if negative then
|
jbe/bsw@0
|
65 f = -f
|
jbe/bsw@0
|
66 end
|
jbe/bsw@0
|
67 return f
|
jbe/bsw@0
|
68 end
|
jbe/bsw@0
|
69 elseif dest_type == atom.fraction then
|
jbe/bsw@0
|
70 return atom.fraction(int * 10 ^ precision + frac, 10 ^ precision)
|
jbe/bsw@0
|
71 else
|
jbe/bsw@0
|
72 error("Missing or invalid destination type for parsing.")
|
jbe/bsw@0
|
73 end
|
jbe/bsw@0
|
74 end
|
jbe/bsw@0
|
75 end
|