1 use nom::character::is_alphanumeric; |
|
2 use nom::{ |
1 use nom::{ |
3 branch::alt, |
2 branch::alt, |
4 bytes::{ |
3 bytes::complete::{escaped_transform, is_not, tag, take_while}, |
5 complete::tag, |
|
6 complete::take_while, |
|
7 complete::{escaped_transform, is_not}, |
|
8 }, |
|
9 character::is_digit, |
4 character::is_digit, |
|
5 character::{is_alphanumeric, is_space}, |
10 combinator::{map, map_res}, |
6 combinator::{map, map_res}, |
11 multi::separated_list, |
7 multi::separated_list, |
|
8 sequence::separated_pair, |
12 sequence::{delimited, pair}, |
9 sequence::{delimited, pair}, |
13 IResult, |
10 IResult, |
14 }; |
11 }; |
15 use std::collections::HashMap; |
12 use std::collections::HashMap; |
16 |
13 |
22 Tuple(Vec<HaskellValue>), |
19 Tuple(Vec<HaskellValue>), |
23 String(String), |
20 String(String), |
24 Number(u8), |
21 Number(u8), |
25 Struct { |
22 Struct { |
26 name: String, |
23 name: String, |
27 values: HashMap<String, HaskellValue>, |
24 fields: HashMap<String, HaskellValue>, |
28 }, |
25 }, |
|
26 } |
|
27 |
|
28 fn comma(input: &[u8]) -> HaskellResult<&[u8]> { |
|
29 delimited(take_while(is_space), tag(","), take_while(is_space))(input) |
29 } |
30 } |
30 |
31 |
31 fn surrounded<'a, P, O>( |
32 fn surrounded<'a, P, O>( |
32 prefix: &'static str, |
33 prefix: &'static str, |
33 suffix: &'static str, |
34 suffix: &'static str, |
34 parser: P, |
35 parser: P, |
35 ) -> impl Fn(&'a [u8]) -> HaskellResult<'a, O> |
36 ) -> impl Fn(&'a [u8]) -> HaskellResult<'a, O> |
36 where |
37 where |
37 P: Fn(&'a [u8]) -> HaskellResult<'a, O>, |
38 P: Fn(&'a [u8]) -> HaskellResult<'a, O>, |
38 { |
39 { |
39 move |input| delimited(tag(prefix), |i| parser(i), tag(suffix))(input) |
40 move |input| { |
|
41 delimited( |
|
42 delimited(take_while(is_space), tag(prefix), take_while(is_space)), |
|
43 |i| parser(i), |
|
44 delimited(take_while(is_space), tag(suffix), take_while(is_space)), |
|
45 )(input) |
|
46 } |
40 } |
47 } |
41 |
48 |
42 fn number_raw(input: &[u8]) -> HaskellResult<u8> { |
49 fn number_raw(input: &[u8]) -> HaskellResult<u8> { |
43 use std::str::FromStr; |
50 use std::str::FromStr; |
44 map_res(take_while(is_digit), |s| { |
51 map_res(take_while(is_digit), |s| { |
48 })(input) |
55 })(input) |
49 } |
56 } |
50 |
57 |
51 fn number(input: &[u8]) -> HaskellResult<HaskellValue> { |
58 fn number(input: &[u8]) -> HaskellResult<HaskellValue> { |
52 map(number_raw, HaskellValue::Number)(input) |
59 map(number_raw, HaskellValue::Number)(input) |
53 } |
|
54 |
|
55 fn read_string(input: &[u8]) -> HaskellResult<String> { |
|
56 Ok((input, String::new())) |
|
57 } |
|
58 |
|
59 fn raw_string_part(input: &[u8]) -> HaskellResult<&[u8]> { |
|
60 take_while(|c| !b"\"\\".contains(&c))(input) |
|
61 } |
60 } |
62 |
61 |
63 const BYTES: &[u8] = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"; |
62 const BYTES: &[u8] = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"; |
64 |
63 |
65 fn string_escape(input: &[u8]) -> HaskellResult<&[u8]> { |
64 fn string_escape(input: &[u8]) -> HaskellResult<&[u8]> { |
120 map(surrounded("\"", "\"", string_content), HaskellValue::String)(input) |
119 map(surrounded("\"", "\"", string_content), HaskellValue::String)(input) |
121 } |
120 } |
122 |
121 |
123 fn tuple(input: &[u8]) -> HaskellResult<HaskellValue> { |
122 fn tuple(input: &[u8]) -> HaskellResult<HaskellValue> { |
124 map( |
123 map( |
125 surrounded("(", ")", separated_list(tag(","), value)), |
124 surrounded("(", ")", separated_list(comma, value)), |
126 HaskellValue::Tuple, |
125 HaskellValue::Tuple, |
127 )(input) |
126 )(input) |
128 } |
127 } |
129 |
128 |
130 fn list(input: &[u8]) -> HaskellResult<HaskellValue> { |
129 fn list(input: &[u8]) -> HaskellResult<HaskellValue> { |
131 map( |
130 map( |
132 surrounded("[", "]", separated_list(tag(","), value)), |
131 surrounded("[", "]", separated_list(comma, value)), |
133 HaskellValue::List, |
132 HaskellValue::List, |
134 )(input) |
133 )(input) |
135 } |
134 } |
136 |
135 |
137 fn identifier(input: &[u8]) -> HaskellResult<String> { |
136 fn identifier(input: &[u8]) -> HaskellResult<String> { |
138 map_res(take_while(is_alphanumeric), |s| { |
137 map_res(take_while(is_alphanumeric), |s| { |
139 std::str::from_utf8(s).map_err(|_| ()).map(String::from) |
138 std::str::from_utf8(s).map_err(|_| ()).map(String::from) |
140 })(input) |
139 })(input) |
141 } |
140 } |
142 |
141 |
143 fn property() -> impl Fn(&[u8]) -> HaskellResult<(String, HaskellValue)> { |
142 fn named_field(input: &[u8]) -> HaskellResult<(String, HaskellValue)> { |
144 |input| { |
143 separated_pair( |
145 let (input, name) = identifier(input)?; |
144 identifier, |
146 let (input, _) = tag("=")(input)?; |
145 delimited(take_while(is_space), tag("="), take_while(is_space)), |
147 value(input).map(|(i, value)| (i, (name, value))) |
146 value, |
148 } |
147 )(input) |
149 } |
148 } |
150 |
149 |
151 fn structure(input: &[u8]) -> HaskellResult<HaskellValue> { |
150 fn structure(input: &[u8]) -> HaskellResult<HaskellValue> { |
152 map( |
151 map( |
153 pair( |
152 pair( |
154 identifier, |
153 identifier, |
155 surrounded("{", "}", separated_list(tag(","), property())), |
154 surrounded("{", "}", separated_list(comma, named_field)), |
156 ), |
155 ), |
157 |(name, mut values)| HaskellValue::Struct { |
156 |(name, mut fields)| HaskellValue::Struct { |
158 name, |
157 name, |
159 values: values.drain(..).collect(), |
158 fields: fields.drain(..).collect(), |
160 }, |
159 }, |
161 )(input) |
160 )(input) |
162 } |
161 } |
163 |
162 |
164 fn value(input: &[u8]) -> HaskellResult<HaskellValue> { |
163 fn value(input: &[u8]) -> HaskellResult<HaskellValue> { |
165 alt((number, string, tuple, list, structure))(input) |
164 alt((number, string, tuple, list, structure))(input) |
166 } |
165 } |
167 |
166 |
168 #[inline] |
167 #[inline] |
169 pub fn parse(input: &[u8]) -> HaskellResult<HaskellValue> { |
168 pub fn parse(input: &[u8]) -> HaskellResult<HaskellValue> { |
170 value(input) |
169 delimited(take_while(is_space), value, take_while(is_space))(input) |
171 } |
170 } |
172 |
171 |
173 mod test { |
172 mod test { |
174 use super::*; |
173 use super::*; |
175 |
174 |
194 Number(64), |
193 Number(64), |
195 String("text".to_string()), |
194 String("text".to_string()), |
196 List(vec![Number(1), Number(2), Number(3)]), |
195 List(vec![Number(1), Number(2), Number(3)]), |
197 ]); |
196 ]); |
198 |
197 |
199 assert_eq!(tuple(b"(64,\"text\",[1,2,3])"), Ok((&b""[..], value))); |
198 assert_eq!(tuple(b"(64, \"text\", [1 , 2, 3])"), Ok((&b""[..], value))); |
200 } |
199 } |
201 |
200 |
202 #[test] |
201 #[test] |
203 fn structures() { |
202 fn structures() { |
204 use HaskellValue::*; |
203 use HaskellValue::*; |
205 |
204 |
206 let value = Struct { |
205 let value = Struct { |
207 name: "Hog".to_string(), |
206 name: "Hog".to_string(), |
208 values: vec![ |
207 fields: vec![ |
209 ("name".to_string(), String("\u{1f994}".to_string())), |
208 ("name".to_string(), String("\u{1f994}".to_string())), |
210 ("health".to_string(), Number(100)), |
209 ("health".to_string(), Number(100)), |
211 ] |
210 ] |
212 .drain(..) |
211 .drain(..) |
213 .collect(), |
212 .collect(), |
214 }; |
213 }; |
215 |
214 |
216 assert_eq!( |
215 assert_eq!( |
217 structure(b"Hog{name=\"\\240\\159\\166\\148\",health=100}"), |
216 structure(b"Hog {name = \"\\240\\159\\166\\148\",health = 100}"), |
218 Ok((&b""[..], value)) |
217 Ok((&b""[..], value)) |
219 ); |
218 ); |
220 } |
219 } |
221 } |
220 } |