weedle/
literal.rs

1ast_types! {
2    /// Represents an integer value
3    #[derive(Copy)]
4    enum IntegerLit<'a> {
5        /// Parses `-?[1-9][0-9]*`
6        #[derive(Copy)]
7        Dec(struct DecLit<'a>(
8            &'a str = crate::whitespace::ws(nom::combinator::recognize(nom::sequence::tuple((
9                nom::combinator::opt(nom::character::complete::char('-')),
10                nom::character::complete::one_of("123456789"),
11                nom::bytes::complete::take_while(nom::AsChar::is_dec_digit)
12            )))),
13        )),
14        /// Parses `-?0[Xx][0-9A-Fa-f]+)`
15        #[derive(Copy)]
16        Hex(struct HexLit<'a>(
17            &'a str = crate::whitespace::ws(nom::combinator::recognize(nom::sequence::tuple((
18                nom::combinator::opt(nom::character::complete::char('-')),
19                nom::character::complete::char('0'),
20                nom::character::complete::one_of("xX"),
21                nom::bytes::complete::take_while(nom::AsChar::is_hex_digit)
22            )))),
23        )),
24        /// Parses `-?0[0-7]*`
25        #[derive(Copy)]
26        Oct(struct OctLit<'a>(
27            &'a str = crate::whitespace::ws(nom::combinator::recognize(nom::sequence::tuple((
28                nom::combinator::opt(nom::character::complete::char('-')),
29                nom::character::complete::char('0'),
30                nom::bytes::complete::take_while(nom::AsChar::is_oct_digit)
31            )))),
32        )),
33    }
34
35    /// Represents a string value
36    ///
37    /// Follow `/"[^"]*"/`
38    #[derive(Copy)]
39    struct StringLit<'a>(
40        &'a str = crate::whitespace::ws(nom::sequence::delimited(
41            nom::character::complete::char('"'),
42            nom::bytes::complete::take_while(|c| c != '"'),
43            nom::character::complete::char('"'),
44        )),
45    )
46
47    /// Represents a default literal value. Ex: `34|34.23|"value"|[ ]|true|false|null`
48    #[derive(Copy)]
49    enum DefaultValue<'a> {
50        Boolean(BooleanLit),
51        /// Represents `[ ]`
52        #[derive(Copy, Default)]
53        EmptyArray(struct EmptyArrayLit {
54            open_bracket: term!(OpenBracket),
55            close_bracket: term!(CloseBracket),
56        }),
57        /// Represents `{ }`
58        #[derive(Copy, Default)]
59        EmptyDictionary(struct EmptyDictionaryLit {
60            open_brace: term!(OpenBrace),
61            close_brace: term!(CloseBrace),
62        }),
63        Float(FloatLit<'a>),
64        Integer(IntegerLit<'a>),
65        Null(term!(null)),
66        String(StringLit<'a>),
67    }
68
69    /// Represents `true`, `false`, `34.23`, `null`, `56`, ...
70    #[derive(Copy)]
71    enum ConstValue<'a> {
72        Boolean(BooleanLit),
73        Float(FloatLit<'a>),
74        Integer(IntegerLit<'a>),
75        Null(term!(null)),
76    }
77
78    /// Represents either `true` or `false`
79    #[derive(Copy)]
80    struct BooleanLit(
81        bool = nom::branch::alt((
82            nom::combinator::value(true, weedle!(term!(true))),
83            nom::combinator::value(false, weedle!(term!(false))),
84        )),
85    )
86
87    /// Represents a floating point value, `NaN`, `Infinity`, '+Infinity`
88    #[derive(Copy)]
89    enum FloatLit<'a> {
90        /// Parses `/-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+)/`
91        #[derive(Copy)]
92        Value(struct FloatValueLit<'a>(
93            &'a str = crate::whitespace::ws(nom::combinator::recognize(nom::sequence::tuple((
94                nom::combinator::opt(nom::character::complete::char('-')),
95                nom::branch::alt((
96                    nom::combinator::value((), nom::sequence::tuple((
97                        // (?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)
98                        nom::branch::alt((
99                            nom::sequence::tuple((
100                                nom::bytes::complete::take_while1(nom::AsChar::is_dec_digit),
101                                nom::character::complete::char('.'),
102                                nom::bytes::complete::take_while(nom::AsChar::is_dec_digit),
103                            )),
104                            nom::sequence::tuple((
105                                nom::bytes::complete::take_while(nom::AsChar::is_dec_digit),
106                                nom::character::complete::char('.'),
107                                nom::bytes::complete::take_while1(nom::AsChar::is_dec_digit),
108                            )),
109                        )),
110                        // (?:[Ee][+-]?[0-9]+)?
111                        nom::combinator::opt(nom::sequence::tuple((
112                            nom::character::complete::one_of("eE"),
113                            nom::combinator::opt(nom::character::complete::one_of("+-")),
114                            nom::bytes::complete::take_while1(nom::AsChar::is_dec_digit),
115                        ))),
116                    ))),
117                    // [0-9]+[Ee][+-]?[0-9]+
118                    nom::combinator::value((), nom::sequence::tuple((
119                        nom::bytes::complete::take_while1(nom::AsChar::is_dec_digit),
120                        nom::character::complete::one_of("eE"),
121                        nom::combinator::opt(nom::character::complete::one_of("+-")),
122                        nom::bytes::complete::take_while1(nom::AsChar::is_dec_digit),
123                    ))),
124                )),
125            )))),
126        )),
127        NegInfinity(term!(-Infinity)),
128        Infinity(term!(Infinity)),
129        NaN(term!(NaN)),
130    }
131}
132
133#[cfg(test)]
134mod test {
135    use super::*;
136    use crate::term::*;
137    use crate::Parse;
138
139    test!(should_parse_integer { "45" =>
140        "";
141        IntegerLit => IntegerLit::Dec(DecLit("45"))
142    });
143
144    test!(should_parse_integer_surrounding_with_spaces { "  123123  " =>
145        "";
146        IntegerLit => IntegerLit::Dec(DecLit("123123"))
147    });
148
149    test!(should_parse_integer_preceding_others { "3453 string" =>
150        "string";
151        IntegerLit => IntegerLit::Dec(DecLit("3453"))
152    });
153
154    test!(should_parse_neg_integer { "-435" =>
155        "";
156        IntegerLit => IntegerLit::Dec(DecLit("-435"))
157    });
158
159    test!(should_parse_hex_number { "0X08" =>
160        "";
161        IntegerLit => IntegerLit::Hex(HexLit("0X08"))
162    });
163
164    test!(should_parse_hex_large_number { "0xA" =>
165        "";
166        IntegerLit => IntegerLit::Hex(HexLit("0xA"))
167    });
168
169    test!(should_parse_zero { "0" =>
170        "";
171        IntegerLit => IntegerLit::Oct(OctLit("0"))
172    });
173
174    test!(should_parse_oct_number { "-07561" =>
175        "";
176        IntegerLit => IntegerLit::Oct(OctLit("-07561"))
177    });
178
179    test!(should_parse_float { "45.434" =>
180        "";
181        FloatLit => FloatLit::Value(FloatValueLit("45.434"))
182    });
183
184    test!(should_parse_float_surrounding_with_spaces { "  2345.2345  " =>
185        "";
186        FloatLit => FloatLit::Value(FloatValueLit("2345.2345"))
187    });
188
189    test!(should_parse_float_preceding_others { "3453.32334 string" =>
190        "string";
191        FloatLit => FloatLit::Value(FloatValueLit("3453.32334"))
192    });
193
194    test!(should_parse_neg_float { "-435.3435" =>
195        "";
196        FloatLit => FloatLit::Value(FloatValueLit("-435.3435"))
197    });
198
199    test!(should_parse_float_exp { "3e23" =>
200        "";
201        FloatLit => FloatLit::Value(FloatValueLit("3e23"))
202    });
203
204    test!(should_parse_float_exp_with_decimal { "5.3434e23" =>
205        "";
206        FloatLit => FloatLit::Value(FloatValueLit("5.3434e23"))
207    });
208
209    test!(should_parse_neg_infinity { "-Infinity" =>
210        "";
211        FloatLit => FloatLit::NegInfinity(term!(-Infinity))
212    });
213
214    test!(should_parse_infinity { "Infinity" =>
215        "";
216        FloatLit => FloatLit::Infinity(term!(Infinity))
217    });
218
219    test!(should_parse_string { r#""this is a string""# =>
220        "";
221        StringLit => StringLit("this is a string")
222    });
223
224    test!(should_parse_string_surround_with_spaces { r#"  "this is a string"  "# =>
225        "";
226        StringLit => StringLit("this is a string")
227    });
228
229    test!(should_parse_string_followed_by_string { r#" "this is first"  "this is second" "# =>
230        r#""this is second" "#;
231        StringLit => StringLit("this is first")
232    });
233
234    test!(should_parse_string_with_spaces { r#"  "  this is a string  "  "# =>
235        "";
236        StringLit => StringLit("  this is a string  ")
237    });
238
239    test!(should_parse_string_with_comment { r#"  "// this is still a string"
240     "# =>
241        "";
242        StringLit => StringLit("// this is still a string")
243    });
244
245    test!(should_parse_string_with_multiline_comment { r#"  "/*"  "*/"  "# =>
246        r#""*/"  "#;
247        StringLit => StringLit("/*")
248    });
249
250    test!(should_parse_null { "null" =>
251        "";
252        Null => Null
253    });
254
255    test!(should_parse_empty_array { "[]" =>
256        "";
257        EmptyArrayLit => Default::default()
258    });
259
260    test!(should_parse_bool_true { "true" =>
261        "";
262        BooleanLit => BooleanLit(true)
263    });
264
265    test!(should_parse_bool_false { "false" =>
266        "";
267        BooleanLit => BooleanLit(false)
268    });
269}