1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
use super::{decode_pair, Value};
use std::{collections::HashMap, convert::TryInto, str::FromStr};
grammar;
pub Value: Value = {
"null" => Value::Null,
"true" => Value::Bool(true),
"false" => Value::Bool(false),
Num => Value::Number(<>),
Str => Value::String(<>),
"[" "]" => Value::Array(Vec::new()),
"[" <v : (<Value> ",")*> <e: Value> "]" => {
let mut v = v;
v.push(e);
Value::Array(v)
},
"{" "}" => Value::Object(HashMap::new()),
"{" <v : (<Str> ":" <Value> ",")*> <e : (<Str> ":" <Value>)> "}" => {
let mut v = v;
v.push(e);
Value::Object(v.into_iter().collect())
},
};
pub Num: f64 = r"-?(0|[1-9][0-9]*)(\.[0-9]*)?([eE][-+]?[0-9]+)?" => f64::from_str(<>).unwrap();
pub Str: String = r#""([^\\"]|\\.)*""# => {
let mut out = String::new();
let mut iter = <>.chars();
iter.next();
iter.next_back();
while let Some(c) = iter.next() {
let c = match c {
c @ '\x20'..='\x21' | c @ '\x23'..='\x5B' | c @ '\x5D'..='\u{10FFFF}' => c,
'\\' => match iter.next().unwrap() {
'\"' => '\x22',
'\\' => '\x5C',
'/' => '\x2F',
'b' => '\x08',
'f' => '\x0C',
'n' => '\x0A',
'r' => '\x0D',
't' => '\x09',
'u' => {
let v = iter.by_ref().take(4).collect::<String>();
assert_eq!(v.len(), 4);
let v = u16::from_str_radix(&v, 16).unwrap();
let codepoint = if (0xD800..=0xDFFF).contains(&v) {
let skipped = iter.by_ref().take(2).collect::<String>();
assert_eq!(skipped, "\\u");
let o = iter.by_ref().take(4).collect::<String>();
assert_eq!(o.len(), 4);
let o = u16::from_str_radix(&o, 16).unwrap();
decode_pair(v, o)
} else {
u32::from(v)
};
codepoint.try_into().unwrap()
}
c => panic!("bad escape sequence {}", c),
}
c => panic!("invalid character {}", c),
};
out.push(c);
}
out
};
|