1use crate::data::{ast::*, tokens::*, Literal};
2use crate::parser::tools::get_string;
3use crate::parser::tools::get_tag;
4use crate::parser::{parse_comments::comment, tools::get_interval};
5
6use crate::data::primitive::{
7 boolean::PrimitiveBoolean, float::PrimitiveFloat, int::PrimitiveInt, null::PrimitiveNull,
8};
9use nom::{
10 branch::alt,
11 bytes::complete::tag,
12 character::complete::{char, one_of},
13 combinator::{opt, recognize},
14 error::{ContextError, ParseError},
15 multi::{many0, many1},
16 sequence::{preceded, terminated, tuple},
17 IResult,
18};
19
20fn signed_digits<'a, E>(s: Span<'a>) -> IResult<Span<'a>, Span, E>
25where
26 E: ParseError<Span<'a>> + ContextError<Span<'a>>,
27{
28 recognize(tuple((opt(one_of("+-")), decimal)))(s)
29}
30
31fn decimal<'a, E>(s: Span<'a>) -> IResult<Span<'a>, Span, E>
32where
33 E: ParseError<Span<'a>> + ContextError<Span<'a>>,
34{
35 recognize(many1(terminated(one_of("0123456789"), many0(char('_')))))(s)
36}
37
38fn parse_integer<'a, E>(s: Span<'a>) -> IResult<Span<'a>, Expr, E>
39where
40 E: ParseError<Span<'a>> + ContextError<Span<'a>>,
41{
42 let (s, interval) = get_interval(s)?;
43 let (s, int) = get_int(s)?;
44
45 let expression = Expr::LitExpr {
46 literal: PrimitiveInt::get_literal(int, interval),
47 in_in_substring: false,
48 };
49 Ok((s, expression))
50}
51
52fn floating_point<'a, E>(s: Span<'a>) -> IResult<Span<'a>, Span<'a>, E>
53where
54 E: ParseError<Span<'a>> + ContextError<Span<'a>>,
55{
56 alt((
57 recognize(tuple((char('.'), decimal))), recognize(tuple((
60 opt(one_of("+-")),
61 decimal,
62 preceded(char('.'), decimal),
63 ))),
64 ))(s)
65}
66
67fn parse_float<'a, E>(s: Span<'a>) -> IResult<Span<'a>, Expr, E>
68where
69 E: ParseError<Span<'a>> + ContextError<Span<'a>>,
70{
71 let (s, interval) = get_interval(s)?;
72 let (s, float_raw) = floating_point(s)?;
73 let float = float_raw.fragment().parse::<f64>().unwrap_or(0.0);
74
75 let expression = Expr::LitExpr {
76 literal: PrimitiveFloat::get_literal(float, interval),
77 in_in_substring: false,
78 };
79
80 Ok((s, expression))
81}
82
83fn parse_number<'a, E>(s: Span<'a>) -> IResult<Span<'a>, Expr, E>
84where
85 E: ParseError<Span<'a>> + ContextError<Span<'a>>,
86{
87 alt((parse_float, parse_integer))(s)
88}
89
90fn parse_true<'a, E>(s: Span<'a>) -> IResult<Span<'a>, PrimitiveBoolean, E>
91where
92 E: ParseError<Span<'a>> + ContextError<Span<'a>>,
93{
94 let (s, _) = tag(TRUE)(s)?;
95
96 Ok((s, PrimitiveBoolean::new(true)))
97}
98
99fn parse_false<'a, E>(s: Span<'a>) -> IResult<Span<'a>, PrimitiveBoolean, E>
100where
101 E: ParseError<Span<'a>> + ContextError<Span<'a>>,
102{
103 let (s, _) = tag(FALSE)(s)?;
104
105 Ok((s, PrimitiveBoolean::new(false)))
106}
107
108fn parse_boolean<'a, E>(s: Span<'a>) -> IResult<Span<'a>, Expr, E>
109where
110 E: ParseError<Span<'a>> + ContextError<Span<'a>>,
111{
112 let (s, interval) = get_interval(s)?;
113 let (s, boolean) = alt((parse_true, parse_false))(s)?;
114
115 let primitive = Box::new(boolean);
116 let expression = Expr::LitExpr {
117 literal: Literal {
118 content_type: "boolean".to_owned(),
119 primitive,
120 additional_info: None,
121 secure_variable: false,
122 interval,
123 },
124 in_in_substring: false,
125 };
126
127 Ok((s, expression))
128}
129
130fn parse_null<'a, E>(s: Span<'a>) -> IResult<Span<'a>, Expr, E>
131where
132 E: ParseError<Span<'a>> + ContextError<Span<'a>>,
133{
134 let (s, interval) = get_interval(s)?;
135 let (s, name) = preceded(comment, get_string)(s)?;
136 let (s, _) = get_tag(name.to_ascii_lowercase(), NULL)(s)?;
137
138 let expression = Expr::LitExpr {
139 literal: PrimitiveNull::get_literal(interval),
140 in_in_substring: false,
141 };
142
143 Ok((s, expression))
144}
145
146pub fn get_int<'a, E>(s: Span<'a>) -> IResult<Span<'a>, i64, E>
151where
152 E: ParseError<Span<'a>> + ContextError<Span<'a>>,
153{
154 let (s, raw_digits) = signed_digits(s)?;
156 let int = raw_digits.fragment().parse::<i64>().unwrap_or(0);
157
158 Ok((s, int))
159}
160
161pub fn parse_literal_expr<'a, E>(s: Span<'a>) -> IResult<Span<'a>, Expr, E>
162where
163 E: ParseError<Span<'a>> + ContextError<Span<'a>>,
164{
165 preceded(comment, alt((parse_number, parse_boolean, parse_null)))(s)
167}
168
169#[cfg(test)]
174mod tests {
175 use super::*;
176 use nom::{error::ErrorKind, *};
177
178 pub fn test_literal(s: Span) -> IResult<Span, Expr> {
179 let var = parse_literal_expr(s);
180 if let Ok((s, v)) = var {
181 if s.fragment().len() != 0 {
182 Err(Err::Error(nom::error::Error::new(s, ErrorKind::Tag)))
183 } else {
184 Ok((s, v))
185 }
186 } else {
187 var
188 }
189 }
190
191 #[test]
192 fn ok_int() {
193 let string = Span::new(" +42");
194 match test_literal(string) {
195 Ok(..) => {}
196 Err(e) => panic!("{:?}", e),
197 }
198 }
199
200 #[test]
201 fn ok_float() {
202 let string = Span::new(" -42.42");
203 match test_literal(string) {
204 Ok(..) => {}
205 Err(e) => panic!("{:?}", e),
206 }
207 }
208
209 #[test]
210 fn ok_bool() {
211 let string = Span::new(" true");
212 match test_literal(string) {
213 Ok(..) => {}
214 Err(e) => panic!("{:?}", e),
215 }
216 }
217
218 #[test]
219 fn err_sign() {
220 let string = Span::new(" +++++4");
221 match test_literal(string) {
222 Ok(..) => panic!("need to fail"),
223 Err(..) => {}
224 }
225 }
226
227 #[test]
228 fn err_float1() {
229 let string = Span::new(" 2.2.2");
230 match test_literal(string) {
231 Ok(..) => panic!("need to fail"),
232 Err(..) => {}
233 }
234 }
235
236 #[test]
237 fn err_float2() {
238 let string = Span::new(" 3,2 ");
239 match test_literal(string) {
240 Ok(ok) => panic!("need to fail {:?}", ok),
241 Err(..) => {}
242 }
243 }
244}