saffron_data/
json.rs

1use std::collections::HashMap;
2
3use crate::error::ParseError;
4use crate::tokenizer::TokenKind;
5use crate::{parse::Parse, token_stream::TokenStream, tokenizer::Tokenizer};
6
7#[derive(Debug, Clone, PartialEq)]
8pub enum JsonElement {
9    Number(f64),
10    String(String),
11    Boolean(bool),
12    Array(Vec<JsonElement>),
13    Object(HashMap<String, JsonElement>),
14    Null,
15}
16
17pub struct Json {
18    pub root: JsonElement,
19}
20
21impl Json {
22    fn parse_tokens(mut tokens: TokenStream) -> Result<JsonElement, ParseError> {
23        fn parse_value(tokens: &mut TokenStream) -> Result<JsonElement, ParseError> {
24            use TokenKind::*;
25
26            let tk = tokens.current();
27
28            match tk.kind {
29                String => {
30                    let t = tokens.advance();
31                    Ok(JsonElement::String(t.lexeme))
32                }
33                Number => {
34                    let t = tokens.advance();
35                    let n = t
36                        .lexeme
37                        .parse::<f64>()
38                        .map_err(|_e| ParseError::new(format!("Invalid number '{}'", t.lexeme)))?;
39                    Ok(JsonElement::Number(n))
40                }
41                Boolean => {
42                    let t = tokens.advance();
43                    let b = match t.lexeme.as_str() {
44                        "true" => true,
45                        "false" => false,
46                        other => {
47                            return Err(ParseError::new(format!(
48                                "Invalid boolean literal '{}'",
49                                other
50                            )));
51                        }
52                    };
53                    Ok(JsonElement::Boolean(b))
54                }
55                Null => {
56                    tokens.advance();
57                    Ok(JsonElement::Null)
58                }
59                LeftBrace => parse_object(tokens),
60                LeftBracket => parse_array(tokens),
61                _ => Err(ParseError::new(format!("Unexpected token: {:?}", tk.kind))),
62            }
63        }
64
65        fn parse_object(tokens: &mut TokenStream) -> Result<JsonElement, ParseError> {
66            use TokenKind::*;
67
68            let start = tokens.current();
69            if start.kind != LeftBrace {
70                return Err(ParseError::new("Expected '{' at start of object"));
71            }
72            tokens.advance();
73
74            let mut map = HashMap::new();
75
76            if tokens.current().kind == RightBrace {
77                tokens.advance();
78                return Ok(JsonElement::Object(map));
79            }
80
81            loop {
82                let key_token = tokens.current();
83                if key_token.kind != String {
84                    return Err(ParseError::new(format!(
85                        "Expected string key in object, found {:?}",
86                        key_token.kind
87                    )));
88                }
89                let key = tokens.advance().lexeme;
90
91                if tokens.current().kind != Colon {
92                    return Err(ParseError::new("Expected ':' after object key"));
93                }
94                tokens.advance();
95
96                let value = parse_value(tokens)?;
97                map.insert(key, value);
98
99                match tokens.current().kind {
100                    Comma => {
101                        tokens.advance();
102                        continue;
103                    }
104                    RightBrace => {
105                        tokens.advance();
106                        break;
107                    }
108                    other => {
109                        return Err(ParseError::new(format!(
110                            "Expected ',' or '}}' in object, found {:?}",
111                            other
112                        )));
113                    }
114                }
115            }
116
117            Ok(JsonElement::Object(map))
118        }
119
120        fn parse_array(tokens: &mut TokenStream) -> Result<JsonElement, ParseError> {
121            use TokenKind::*;
122
123            let start = tokens.current();
124            if start.kind != LeftBracket {
125                return Err(ParseError::new("Expected '[' at start of array"));
126            }
127            tokens.advance();
128
129            let mut items = Vec::new();
130
131            if tokens.current().kind == RightBracket {
132                tokens.advance();
133                return Ok(JsonElement::Array(items));
134            }
135
136            loop {
137                let value = parse_value(tokens)?;
138                items.push(value);
139
140                match tokens.current().kind {
141                    Comma => {
142                        tokens.advance();
143                        continue;
144                    }
145                    RightBracket => {
146                        tokens.advance();
147                        break;
148                    }
149                    other => {
150                        return Err(ParseError::new(format!(
151                            "Expected ',' or ']' in array, found {:?}",
152                            other
153                        )));
154                    }
155                }
156            }
157
158            Ok(JsonElement::Array(items))
159        }
160
161        let value = parse_value(&mut tokens)?;
162        Ok(value)
163    }
164
165    fn _parse(source: impl Into<String>) -> Result<Self, ParseError> {
166        let mut tokenizer = Tokenizer::new(source.into());
167        let tokens = tokenizer.scan_tokens()?;
168        let root = Self::parse_tokens(tokens)?;
169
170        Ok(Json { root })
171    }
172}
173
174impl Parse for Json {
175    fn parse(source: impl Into<String>) -> Result<Self, ParseError>
176    where
177        Self: Sized,
178    {
179        Self::_parse(source)
180    }
181}