nom_lua/
number.rs

1// Copyright 2017 The nom-lua project developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use std::str;
10use std::str::FromStr;
11use ast::ASTNode;
12use ast::ASTNode::*;
13//use hexf_parse::parse_hexf64;
14
15use super::nom::{digit, hex_digit};
16//TODO: LOCALE dependent decimal point!
17//TODO: Hex numbers
18
19named!(parse_int_overflow<ASTNode>, map!(
20           map_res!(map_res!(digit, str::from_utf8), FromStr::from_str),
21           ASTNode::Float));
22
23named!(parse_int<ASTNode>, map!(
24           map_res!(map_res!(digit, str::from_utf8), FromStr::from_str),
25           ASTNode::Integer));
26
27named!(parse_hex_int<ASTNode>,
28           do_parse!(
29               preceded!(tag!("0"), alt!(tag!("x") | tag!("X"))) >>
30               hex: map_res!(
31                     map_res!(hex_digit, str::from_utf8),
32                    |h| i64::from_str_radix(h, 16))
33               >> (ast!(Integer, hex))));
34
35named!(parse_float_exp, recognize!(do_parse!(
36               alt!(tag!("e") | tag!("E"))
37            >> opt!(alt!(tag!("+") | tag!("-")))
38            >> digit
39            >> ())));
40
41named!(parse_float<ASTNode>,
42       do_parse!(
43              float: map_res!( map_res!( recognize!( do_parse!(
44                         alt!(
45                          delimited!(digit, tag!("."), opt!(complete!(digit))) |
46                          delimited!(opt!(digit), tag!("."), digit) |
47                          digit)
48                      >> opt!(complete!(parse_float_exp))
49                      >> ())),
50                  str::from_utf8), FromStr::from_str)
51           >> (ast!(Float, float)))
52      );
53
54
55//named!(parse_hex_float<ASTNode>, map_res!(apply!(parse_hexf64, false), |_| ASTNode::Float(0.0f)));
56
57
58named!(pub parse_number<ASTNode>, dbg_dmp!(alt!(
59            //complete!(parse_hex_float) |
60            complete!(parse_hex_int) |
61            complete!(parse_float) |
62            parse_int |
63            parse_int_overflow
64)));
65
66#[cfg(test)]
67mod tests {
68    //The tests panic because the macro calls unwrap, otherwise they should fail gracefully
69
70    ast_test!(parse_int_1, parse_int, "20", ast!(Integer, 20));
71
72    // Overflowing causes integers to be interperted as floats, thus this should fail
73    ast_panic_test!(parse_int_3, parse_int, "5678987656789876520999999999999");
74
75    // preceding +/- are separate ASTNodes
76    ast_panic_test!(parse_int_4, parse_int, "-20");
77    ast_panic_test!(parse_int_5, parse_int, "+20");
78
79
80    ast_test!(parse_hex_1, parse_hex_int, "0X20", ast!(Integer, 0x20));
81    ast_test!(parse_hex_2, parse_hex_int, "0x20", ast!(Integer, 0x20));
82    ast_test!(parse_hex_3, parse_hex_int, "0x20a", ast!(Integer, 0x20A));
83    ast_test!(parse_hex_4, parse_hex_int, "0x20aB", ast!(Integer, 0x20AB));
84    ast_test!(parse_hex_5, parse_hex_int, "0X20F", ast!(Integer, 0x20F));
85    // need 0x preceding to parse sucessfully
86    ast_panic_test!(parse_hex_6, parse_hex_int, "20");
87    // preceding +/- are separate ASTNodes
88    ast_panic_test!(parse_hex_7, parse_hex_int, "-0x20");
89    ast_panic_test!(parse_hex_8, parse_hex_int, "+0x20");
90
91
92    ast_test!(parse_float_1, parse_float, "3.0", ast!(Float, 3.0));
93    ast_test!(parse_float_2, parse_float, ".1", ast!(Float, 0.1));
94    ast_test!(parse_float_3, parse_float, "1.", ast!(Float, 1.0));
95    ast_test!(parse_float_4, parse_float, "3.1416", ast!(Float, 3.1416));
96    ast_test!(parse_float_5, parse_float, "314.16e-2", ast!(Float, 314.16e-2));
97    ast_test!(parse_float_6, parse_float, "0.31416E1", ast!(Float, 0.31416E1));
98    ast_test!(parse_float_7, parse_float, "34e1", ast!(Float, 340.0));
99    ast_test!(parse_float_8, parse_float, "34e+1", ast!(Float, 340.0));
100    ast_test!(parse_float_9, parse_float, "34e-1", ast!(Float, 3.4));
101    ast_test!(parse_float_10, parse_float, "34.e-1", ast!(Float, 3.4));
102    ast_test!(parse_float_11, parse_float, ".2e1", ast!(Float, 2.0));
103    ast_panic_test!(parse_float_12, parse_float, ".e1");
104
105    // preceding +/- are separate ASTNodes
106    ast_panic_test!(parse_float_13, parse_float, "-20.0");
107    ast_panic_test!(parse_float_14, parse_float, "+20.0");
108
109    ast_test!(parse_number_1, parse_number, "20", ast!(Integer, 20));
110    ast_test!(parse_number_2, parse_number, "20.0", ast!(Float, 20.0));
111    ast_test!(parse_number_3, parse_number, "0x20", ast!(Integer, 0x20));
112    ast_test!(parse_number_4, parse_number, "1000000000000000000000000", ast!(Float, 1e+24));
113    //ast_panic_test!(parse_number_5, parse_number, "10f");
114}