webmcp
diff framework/env/parse/decimal.lua @ 0:9fdfb27f8e67
Version 1.0.0
author | jbe/bsw |
---|---|
date | Sun Oct 25 12:00:00 2009 +0100 (2009-10-25) |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/framework/env/parse/decimal.lua Sun Oct 25 12:00:00 2009 +0100 1.3 @@ -0,0 +1,75 @@ 1.4 +local digit_set = { 1.5 + ["0"] = true, ["1"] = true, ["2"] = true, ["3"] = true, ["4"] = true, 1.6 + ["5"] = true, ["6"] = true, ["7"] = true, ["8"] = true, ["9"] = true 1.7 +} 1.8 + 1.9 +function parse.decimal(str, dest_type, options) 1.10 + local str = parse._pre_fold(str) 1.11 + local dest_type = dest_type or atom.number 1.12 + local options = options or {} 1.13 + if str == "" then 1.14 + return nil 1.15 + else 1.16 + local decimal_shift = options.decimal_shift or 0 1.17 + if decimal_shift == true then 1.18 + decimal_shift = options.precision 1.19 + end 1.20 + local decimal_point = locale.get("decimal_point") or "." 1.21 + local negative = nil 1.22 + local int = 0 1.23 + local frac = 0 1.24 + local precision = 0 1.25 + local after_point = false 1.26 + for char in string.gmatch(str, ".") do 1.27 + local skip = false 1.28 + if negative == nil then 1.29 + if char == "+" then 1.30 + negative = false 1.31 + skip = true 1.32 + elseif char == "-" then -- real minus sign already replaced by _pre_fold 1.33 + negative = true 1.34 + skip = true 1.35 + end 1.36 + end 1.37 + if not skip then 1.38 + if digit_set[char] then 1.39 + if after_point then 1.40 + if decimal_shift > 0 then 1.41 + int = 10 * int + tonumber(char) 1.42 + decimal_shift = decimal_shift - 1 1.43 + else 1.44 + frac = 10 * frac + tonumber(char) 1.45 + precision = precision + 1 1.46 + end 1.47 + else 1.48 + int = 10 * int + tonumber(char) 1.49 + end 1.50 + elseif char == decimal_point then 1.51 + if after_point then 1.52 + return dest_type.invalid 1.53 + else 1.54 + after_point = true 1.55 + end 1.56 + elseif char ~= " " then -- TODO: ignore thousand seperator too, when supported by format.decimal 1.57 + return dest_type.invalid 1.58 + end 1.59 + end 1.60 + end 1.61 + int = int * 10 ^ decimal_shift 1.62 + if dest_type == atom.number or dest_type == atom.integer then 1.63 + if dest_type == atom.integer and frac ~= 0 then 1.64 + return atom.not_a_number 1.65 + else 1.66 + local f = int + frac / 10 ^ precision 1.67 + if negative then 1.68 + f = -f 1.69 + end 1.70 + return f 1.71 + end 1.72 + elseif dest_type == atom.fraction then 1.73 + return atom.fraction(int * 10 ^ precision + frac, 10 ^ precision) 1.74 + else 1.75 + error("Missing or invalid destination type for parsing.") 1.76 + end 1.77 + end 1.78 +end