1use std::collections::HashMap;
2
3use parse_it::ParseIt;
4
5#[derive(Clone, Debug)]
6pub enum JsonValue {
7 Number(f64),
8 String(String),
9 Boolean(bool),
10 Null,
11 Array(Vec<JsonValue>),
12 Object(HashMap<String, JsonValue>),
13}
14
15parse_it::parse_it! {
16 #[lexer]
17 mod lex {
18 #[derive(Debug)]
19 pub enum Token {
20 Number(f64),
21 String(String),
22 Keyword,
23 Punct,
24 }
25
26 pub Initial -> Token {
27 r"\s+" => continue, Number => Token::Number(self),
29 "\"" => {
30 let mut buf = String::new();
31 while lex!(StringLit(&mut buf)).is_some() {}
32 Token::String(buf)
33 },
34 "true" => Token::Keyword,
35 "false" => Token::Keyword,
36 "null" => Token::Keyword,
37 r"\[" => Token::Punct,
38 r"\]" => Token::Punct,
39 r"\{" => Token::Punct,
40 r"\}" => Token::Punct,
41 r"," => Token::Punct,
42 r":" => Token::Punct,
43 }
44
45 Number -> f64 {
46 r"-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?" => self.parse().unwrap(),
47 }
48
49 StringLit(buf: &mut String) {
50 "\"" => break,
51 r"\\n" => buf.push('\n'),
52 r"\\t" => buf.push('\t'),
53 r#"\\\""# => buf.push('"'),
54 r"\\\\" => buf.push('\\'),
55 r"\\/" => buf.push('/'),
56 r"\\b" => buf.push('\x08'),
57 r"\\f" => buf.push('\x0C'),
58 r"\\r" => buf.push('\r'),
59 r#"[^\"\\]"# => buf.push_str(self),
60 }
61 }
62
63 #[parser]
64 mod parse {
65 use std::collections::HashMap;
66 use super::JsonValue;
67 use super::lex::Token;
68
69 type Lexer = super::lex::Initial;
70
71 Object -> JsonValue {
72 '{' '}' => JsonValue::Object(HashMap::new()),
73 '{' ps:( Key ':' Value ',' )* p:( Key ':' Value ) '}' => {
74 let map = ps.into_iter().chain(std::iter::once(p)).collect::<HashMap<_, _>>();
75 JsonValue::Object(map)
76 }
77 }
78
79 Array -> JsonValue {
80 '[' ']' => JsonValue::Array(Vec::new()),
81 '[' vs:(Value ',')* v:Value ']' => {
82 let vec = vs.into_iter().chain(std::iter::once(v)).collect();
83 JsonValue::Array(vec)
84 }
85 }
86
87 Key -> String {
88 Token::String(buf) => buf
89 }
90
91 pub Value -> JsonValue {
92 Token::Number(i) => JsonValue::Number(i),
93 Token::String(buf) => JsonValue::String(buf),
94 &Token::Keyword "true" => JsonValue::Boolean(true),
95 &Token::Keyword "false" => JsonValue::Boolean(false),
96 &Token::Keyword "null" => JsonValue::Null,
97 Object => self,
98 Array => self,
99 }
100 }
101}
102
103fn main() {
104 let input = r#"{"name": "Alice", "age": 30, "is_student": false, "courses": ["Math", "Science"], "address": null}"#;
105
106 let parser = parse::Value::default();
107 let json = parser.parse(input).unwrap();
108 println!("{json:#?}");
109}