json/
json.rs

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, // Skip whitespace
28            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}