1use winnow::{
2 combinator::{alt, opt},
3 error::{ErrorKind, FromExternalError, ParserError},
4 token::{literal, one_of, take_while},
5 PResult, Parser,
6};
7
8use crate::comments::space_or_comment0;
9
10pub fn identifier<'a, E: ParserError<&'a str>>(input: &mut &'a str) -> PResult<String, E> {
11 let first = one_of([
12 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
13 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
14 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
15 ])
16 .parse_next(input)?;
17 let rest = take_while(0.., is_identifier_rest).parse_next(input)?;
18 let combine = format!("{}{}", first, rest);
19 if is_reserved_key_word(&combine) {
21 Err(winnow::error::ErrMode::Cut(ParserError::from_error_kind(
22 input,
23 ErrorKind::Token,
24 )))
25 } else {
26 Ok(combine)
27 }
28}
29
30pub fn var_par_identifier<'a, E: ParserError<&'a str>>(input: &mut &'a str) -> PResult<String, E> {
31 let first = one_of([
32 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
33 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
34 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_',
35 ])
36 .parse_next(input)?;
37
38 let rest = take_while(0.., is_identifier_rest).parse_next(input)?;
39 let combine = format!("{}{}", first, rest);
40 if is_reserved_key_word(&combine) {
42 Err(winnow::error::ErrMode::Backtrack(
43 ParserError::from_error_kind(input, ErrorKind::Token),
44 ))
45 } else {
46 Ok(combine)
47 }
48}
49
50fn is_reserved_key_word(string: &str) -> bool {
51 matches!(
52 string,
53 "annotation"
54 | "any"
55 | "array"
56 | "bool"
57 | "case"
58 | "constraint"
59 | "diff"
60 | "div"
61 | "else"
62 | "elseif"
63 | "endif"
64 | "enum"
65 | "false"
66 | "float"
67 | "function"
68 | "if"
69 | "in"
70 | "include"
71 | "int"
72 | "intersect"
73 | "let"
74 | "list"
75 | "maximize"
76 | "minimize"
77 | "mod"
78 | "not"
79 | "of"
80 | "satisfy"
81 | "subset"
82 | "superset"
83 | "output"
84 | "par"
85 | "predicate"
86 | "record"
87 | "set"
88 | "solve"
89 | "string"
90 | "symdiff"
91 | "test"
92 | "then"
93 | "true"
94 | "tuple"
95 | "union"
96 | "type"
97 | "var"
98 | "where"
99 | "xor"
100 )
101}
102
103fn is_identifier_rest(c: char) -> bool {
104 matches!(
105 c,
106 'a' | 'b'
107 | 'c'
108 | 'd'
109 | 'e'
110 | 'f'
111 | 'g'
112 | 'h'
113 | 'i'
114 | 'j'
115 | 'k'
116 | 'l'
117 | 'm'
118 | 'n'
119 | 'o'
120 | 'p'
121 | 'q'
122 | 'r'
123 | 's'
124 | 't'
125 | 'u'
126 | 'v'
127 | 'w'
128 | 'x'
129 | 'y'
130 | 'z'
131 | 'A'
132 | 'B'
133 | 'C'
134 | 'D'
135 | 'E'
136 | 'F'
137 | 'G'
138 | 'H'
139 | 'I'
140 | 'J'
141 | 'K'
142 | 'L'
143 | 'M'
144 | 'N'
145 | 'O'
146 | 'P'
147 | 'Q'
148 | 'R'
149 | 'S'
150 | 'T'
151 | 'U'
152 | 'V'
153 | 'W'
154 | 'X'
155 | 'Y'
156 | 'Z'
157 | '_'
158 | '0'
159 | '1'
160 | '2'
161 | '3'
162 | '4'
163 | '5'
164 | '6'
165 | '7'
166 | '8'
167 | '9'
168 )
169}
170
171pub fn bool_literal<'a, E: ParserError<&'a str>>(input: &mut &'a str) -> PResult<bool, E> {
172 alt((literal("true").value(true), literal("false").value(false))).parse_next(input)
173}
174
175pub fn int_literal<'a, E>(input: &mut &'a str) -> PResult<i128, E>
176where
177 E: ParserError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>,
178{
179 alt((decimal, hexadecimal, octal)).parse_next(input)
180}
181#[test]
182fn test_int_literal() {
183 use winnow::error::ContextError;
184 let mut input = "1";
185 assert_eq!(int_literal::<ContextError>(&mut input), Ok(1));
186}
187
188fn decimal<'a, E>(input: &mut &'a str) -> PResult<i128, E>
189where
190 E: ParserError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>,
191{
192 let negation = opt('-').parse_next(input)?;
193 let int = take_while(1.., is_dec_digit)
194 .parse_next(input)?
195 .parse::<i128>()
196 .map_err(|e| winnow::error::ErrMode::from_external_error(input, ErrorKind::Verify, e))?;
197
198 if negation.is_some() {
199 Ok(-int)
200 } else {
201 Ok(int)
202 }
203}
204#[test]
205fn test_decimal() {
206 use winnow::error::ContextError;
207 let mut input = "170141183460469231731687303715884105727";
208 assert_eq!(
209 decimal::<ContextError>(&mut input),
210 Ok(170141183460469231731687303715884105727)
211 );
212}
213#[test]
214fn test_decimal2() {
215 use winnow::error::ContextError;
216 let mut input = "-170141183460469231731687303715884105727";
217 assert_eq!(
218 decimal::<ContextError>(&mut input),
219 Ok(-170141183460469231731687303715884105727)
220 );
221}
222#[test]
223fn test_decimal3() {
224 use winnow::error::ContextError;
225 let mut input = "170141183460469231731687303715884105728";
226 assert!(decimal::<ContextError>(&mut input).is_err());
228}
229
230fn hexadecimal<'a, E>(input: &mut &'a str) -> PResult<i128, E>
231where
232 E: ParserError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>,
233{
234 let negation = opt('-').parse_next(input)?;
235 "0x".parse_next(input)?;
236 let int = take_while(1.., is_hex_digit).parse_next(input)?;
237 let int = i128::from_str_radix(int, 16)
238 .map_err(|e| winnow::error::ErrMode::from_external_error(input, ErrorKind::Verify, e))?;
239
240 if negation.is_some() {
241 Ok(-int)
242 } else {
243 Ok(int)
244 }
245}
246#[test]
247fn test_hex() {
248 use winnow::error::ContextError;
249 let mut input = "-0x2f";
250 assert_eq!(hexadecimal::<ContextError>(&mut input), Ok(-47));
251}
252
253fn octal<'a, E>(input: &mut &'a str) -> PResult<i128, E>
254where
255 E: ParserError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>,
256{
257 let negation = opt('-').parse_next(input)?;
258 "0o".parse_next(input)?;
259 let int = take_while(1.., is_oct_digit).parse_next(input)?;
260 let int = i128::from_str_radix(int, 8)
261 .map_err(|e| winnow::error::ErrMode::from_external_error(input, ErrorKind::Verify, e))?;
262 if negation.is_some() {
263 Ok(-int)
264 } else {
265 Ok(int)
266 }
267}
268#[test]
269fn test_oct() {
270 use winnow::error::ContextError;
271 let mut input = "0o200000000000000000000000000000000001";
272 assert_eq!(
273 octal::<ContextError>(&mut input),
274 Ok(81129638414606681695789005144065)
275 );
276}
277
278fn is_hex_digit(c: char) -> bool {
279 c.is_ascii_hexdigit()
280}
281
282fn is_oct_digit(c: char) -> bool {
283 c.is_digit(8)
284}
285
286fn is_dec_digit(c: char) -> bool {
287 c.is_ascii_digit()
288}
289
290pub fn float_literal<'a, E>(input: &mut &'a str) -> PResult<f64, E>
291where
292 E: ParserError<&'a str> + FromExternalError<&'a str, std::num::ParseFloatError>,
293{
294 fz_float(input)
295}
296#[test]
297fn test_float_literal() {
298 use winnow::error::ContextError;
299 let mut input = "023.21";
302 assert_eq!(float_literal::<ContextError>(&mut input), Ok(023.21));
303 let mut input = "0023.21E-098";
304 assert_eq!(float_literal::<ContextError>(&mut input), Ok(0023.21E-098));
305 let mut input = "0023.21e+098";
306 assert_eq!(float_literal::<ContextError>(&mut input), Ok(0023.21e+098));
307 let mut input = "002e+098";
308 assert_eq!(float_literal::<ContextError>(&mut input), Ok(002e+098));
309 let mut input = "0.21";
310 assert_eq!(float_literal::<ContextError>(&mut input), Ok(0.21));
311 let mut input = "1.0,";
312 assert_eq!(float_literal::<ContextError>(&mut input), Ok(1.0));
313
314 let mut input = "0.000000000000000000000000000000007609999999000000000000000000000000760999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999900000000000000000000000764DD4DDDDDDDDD%
315 ";
316 assert_eq!(
317 float_literal::<ContextError>(&mut input),
318 Ok(0.000000000000000000000000000000007609999999)
319 );
320}
321
322fn fz_float<'a, E>(input: &mut &'a str) -> PResult<f64, E>
323where
324 E: ParserError<&'a str> + FromExternalError<&'a str, std::num::ParseFloatError>,
325{
326 let mut fl = alt((fz_float1, fz_float2)).parse_next(input)?;
327 winnow::ascii::float.parse_next(&mut fl)
328}
329
330fn fz_float1<'a, E: ParserError<&'a str>>(input: &mut &'a str) -> PResult<&'a str, E> {
331 let sign = opt('-');
332
333 let pre = take_while(1.., is_dec_digit);
334 let post = take_while(1.., is_dec_digit);
335 let rest = opt(bpart);
336
337 (sign, pre, '.', post, rest).take().parse_next(input)
338}
339
340fn fz_float2<'a, E: ParserError<&'a str>>(input: &mut &'a str) -> PResult<&'a str, E> {
341 let sign = opt('-');
342 let digits = take_while(1.., is_dec_digit);
343 let e = alt(('e', 'E'));
344 let sign2 = opt(alt(("-", "+")));
345 let digits2 = take_while(1.., is_dec_digit);
346 (sign, digits, e, sign2, digits2).take().parse_next(input)
347}
348
349fn bpart<'a, E: ParserError<&'a str>>(input: &mut &'a str) -> PResult<String, E> {
350 let e = alt(('e', 'E')).parse_next(input)?;
351 let sign = opt(alt(("-", "+"))).parse_next(input)?;
352 let digits = take_while(1.., is_dec_digit).parse_next(input)?;
353 if let Some(sign) = sign {
354 Ok(format!("{}{}{}", e, sign, digits))
355 } else {
356 Ok(format!("{}{}", e, digits))
357 }
358}
359
360#[derive(PartialEq, Clone, Debug)]
361pub struct IndexSet(pub i128);
362
363pub fn index_set<'a, E>(input: &mut &'a str) -> PResult<IndexSet, E>
364where
365 E: ParserError<&'a str> + FromExternalError<&'a str, std::num::ParseIntError>,
366{
367 '1'.parse_next(input)?;
368 space_or_comment0(input)?;
369 "..".parse_next(input)?;
370 space_or_comment0(input)?;
371 let int = int_literal.parse_next(input)?;
372 Ok(IndexSet(int))
373}