|
1 use crate::server::haskell::HaskellValue::Boolean; |
1 use nom::{ |
2 use nom::{ |
2 branch::alt, |
3 branch::alt, |
3 bytes::complete::{escaped_transform, is_not, tag, take_while, take_while1}, |
4 bytes::complete::{escaped_transform, is_not, tag, take_while, take_while1}, |
4 character::{is_alphanumeric, is_digit, is_space}, |
5 character::{is_alphanumeric, is_digit, is_space}, |
5 combinator::{map, map_res}, |
6 combinator::{map, map_res}, |
10 use std::{ |
11 use std::{ |
11 collections::HashMap, |
12 collections::HashMap, |
12 fmt::{Display, Error, Formatter}, |
13 fmt::{Display, Error, Formatter}, |
13 }; |
14 }; |
14 |
15 |
15 type HaskellResult<'a, T> = IResult<&'a [u8], T, ()>; |
16 type HaskellResult<'a, T> = IResult<&'a [u8], T>; |
16 |
17 |
17 #[derive(Debug, PartialEq)] |
18 #[derive(Debug, PartialEq)] |
18 pub enum HaskellValue { |
19 pub enum HaskellValue { |
|
20 Boolean(bool), |
19 Number(u8), |
21 Number(u8), |
20 String(String), |
22 String(String), |
21 Tuple(Vec<HaskellValue>), |
23 Tuple(Vec<HaskellValue>), |
22 List(Vec<HaskellValue>), |
24 List(Vec<HaskellValue>), |
23 AnonStruct { |
25 AnonStruct { |
124 } |
126 } |
125 |
127 |
126 impl Display for HaskellValue { |
128 impl Display for HaskellValue { |
127 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { |
129 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { |
128 match self { |
130 match self { |
|
131 HaskellValue::Boolean(value) => write!(f, "{}", if *value { "True" } else { "False" }), |
129 HaskellValue::Number(value) => write!(f, "{}", value), |
132 HaskellValue::Number(value) => write!(f, "{}", value), |
130 HaskellValue::String(value) => write_text(f, value), |
133 HaskellValue::String(value) => write_text(f, value), |
131 HaskellValue::Tuple(items) => write_sequence(f, b"()", items.iter()), |
134 HaskellValue::Tuple(items) => write_sequence(f, b"()", items.iter()), |
132 HaskellValue::List(items) => write_sequence(f, b"[]", items.iter()), |
135 HaskellValue::List(items) => write_sequence(f, b"[]", items.iter()), |
133 HaskellValue::AnonStruct { name, fields } => { |
136 HaskellValue::AnonStruct { name, fields } => { |
167 delimited(take_while(is_space), tag(prefix), take_while(is_space)), |
170 delimited(take_while(is_space), tag(prefix), take_while(is_space)), |
168 |i| parser(i), |
171 |i| parser(i), |
169 delimited(take_while(is_space), tag(suffix), take_while(is_space)), |
172 delimited(take_while(is_space), tag(suffix), take_while(is_space)), |
170 )(input) |
173 )(input) |
171 } |
174 } |
|
175 } |
|
176 |
|
177 fn boolean(input: &[u8]) -> HaskellResult<HaskellValue> { |
|
178 map( |
|
179 alt((map(tag("True"), |_| true), map(tag("False"), |_| false))), |
|
180 HaskellValue::Boolean, |
|
181 )(input) |
172 } |
182 } |
173 |
183 |
174 fn number_raw(input: &[u8]) -> HaskellResult<u8> { |
184 fn number_raw(input: &[u8]) -> HaskellResult<u8> { |
175 use std::str::FromStr; |
185 use std::str::FromStr; |
176 map_res(take_while(is_digit), |s| { |
186 map_res(take_while(is_digit), |s| { |
266 |bytes| String::from_utf8(bytes).map_err(|_| ()), |
276 |bytes| String::from_utf8(bytes).map_err(|_| ()), |
267 )(input) |
277 )(input) |
268 } |
278 } |
269 |
279 |
270 fn string(input: &[u8]) -> HaskellResult<HaskellValue> { |
280 fn string(input: &[u8]) -> HaskellResult<HaskellValue> { |
271 map(surrounded("\"", "\"", string_content), HaskellValue::String)(input) |
281 map( |
|
282 delimited(tag("\""), string_content, tag("\"")), |
|
283 HaskellValue::String, |
|
284 )(input) |
272 } |
285 } |
273 |
286 |
274 fn tuple(input: &[u8]) -> HaskellResult<HaskellValue> { |
287 fn tuple(input: &[u8]) -> HaskellResult<HaskellValue> { |
275 map( |
288 map( |
276 surrounded("(", ")", separated_list(comma, value)), |
289 surrounded("(", ")", separated_list(comma, value)), |
312 }, |
325 }, |
313 ), |
326 ), |
314 map( |
327 map( |
315 pair( |
328 pair( |
316 identifier, |
329 identifier, |
317 preceded(take_while1(is_space), separated_list(comma, value)), |
330 preceded( |
|
331 take_while(is_space), |
|
332 separated_list(take_while1(is_space), value), |
|
333 ), |
318 ), |
334 ), |
319 |(name, mut fields)| HaskellValue::AnonStruct { |
335 |(name, mut fields)| HaskellValue::AnonStruct { |
320 name: name.clone(), |
336 name: name.clone(), |
321 fields, |
337 fields, |
322 }, |
338 }, |
323 ), |
339 ), |
324 ))(input) |
340 ))(input) |
325 } |
341 } |
326 |
342 |
327 fn value(input: &[u8]) -> HaskellResult<HaskellValue> { |
343 fn value(input: &[u8]) -> HaskellResult<HaskellValue> { |
328 alt((number, string, tuple, list, structure))(input) |
344 alt((boolean, number, string, tuple, list, structure))(input) |
329 } |
345 } |
330 |
346 |
331 #[inline] |
347 #[inline] |
332 pub fn parse(input: &[u8]) -> HaskellResult<HaskellValue> { |
348 pub fn parse(input: &[u8]) -> HaskellResult<HaskellValue> { |
333 delimited(take_while(is_space), value, take_while(is_space))(input) |
349 delimited(take_while(is_space), value, take_while(is_space))(input) |
339 #[test] |
355 #[test] |
340 fn terminals() { |
356 fn terminals() { |
341 use HaskellValue::*; |
357 use HaskellValue::*; |
342 |
358 |
343 matches!(number(b"127"), Ok((_, Number(127)))); |
359 matches!(number(b"127"), Ok((_, Number(127)))); |
344 matches!(number(b"adas"), Err(nom::Err::Error(()))); |
360 matches!(number(b"adas"), Err(nom::Err::Error(_))); |
345 |
361 |
346 assert_eq!( |
362 assert_eq!( |
347 string(b"\"Hail \\240\\159\\166\\148!\""), |
363 string(b"\"Hail \\240\\159\\166\\148!\""), |
348 Ok((&b""[..], String("Hail \u{1f994}!".to_string()))) |
364 Ok((&b""[..], String("Hail \u{1f994}!".to_string()))) |
349 ); |
365 ); |
384 Ok((&b""[..], value)) |
400 Ok((&b""[..], value)) |
385 ); |
401 ); |
386 |
402 |
387 let value = AnonStruct { |
403 let value = AnonStruct { |
388 name: "Hog".to_string(), |
404 name: "Hog".to_string(), |
389 fields: vec![Number(100), String("\u{1f994}".to_string())], |
405 fields: vec![Boolean(true), Number(100), String("\u{1f994}".to_string())], |
390 }; |
406 }; |
391 |
407 |
392 assert_eq!( |
408 assert_eq!( |
393 structure(b"Hog 100, \"\\240\\159\\166\\148\""), |
409 structure(b"Hog True 100 \"\\240\\159\\166\\148\""), |
394 Ok((&b""[..], value)) |
410 Ok((&b""[..], value)) |
395 ); |
411 ); |
396 } |
412 } |
397 } |
413 } |