Skip to main content

erjson/
parser.rs

1use std::collections::HashMap;
2use std::fs::File;
3
4use crate::scanner::{Scanner, Token, TokenKind};
5use crate::value::{JSONError, JSONValue};
6
7#[derive(Debug)]
8pub struct Parser<'a> {
9    scanner: Scanner<'a>,
10    ct: Token,
11}
12
13impl<'a> Parser<'a> {
14    pub fn from_string(data: &'a String) -> Self {
15        Parser {
16            scanner: Scanner::from_string(&data),
17            ct: Token::dummy(),
18        }
19    }
20
21    pub fn from_file(file: File) -> Self {
22        Parser {
23            scanner: Scanner::from_file(file),
24            ct: Token::dummy(),
25        }
26    }
27
28    pub fn parse(&mut self) -> Result<JSONValue, JSONError> {
29        let mut value = Err(JSONError::new("Empty json stream".to_string(), 0, 0));
30        loop {
31            let tk = self.consume();
32            value = match tk.kind {
33                TokenKind::Eof => break,
34                _ => self.parse_value(),
35            }
36        }
37        value
38    }
39
40    fn consume(&mut self) -> Token {
41        self.ct = self.scanner.next_token();
42        self.ct.clone()
43    }
44
45    fn parse_object(&mut self) -> Result<JSONValue, JSONError> {
46        let mut values: HashMap<String, JSONValue> = HashMap::new();
47
48        //consume LeftBrace
49        self.consume();
50        if self.ct.kind == TokenKind::RightBrace {
51            self.consume();
52            return Ok(JSONValue::Object(values));
53        }
54
55        while self.ct.kind != TokenKind::RightBrace && self.ct.kind != TokenKind::Eof {
56            if self.ct.kind != TokenKind::String {
57                return Err(JSONError::new(
58                    format!("Expecting key name but found {:?}", self.ct.kind),
59                    self.ct.line,
60                    self.ct.col,
61                ));
62            }
63            let key = self.ct.value.clone();
64            self.consume(); //consume String
65
66            if self.ct.kind != TokenKind::Collon {
67                return Err(JSONError::new(
68                    format!("Expecting collon but found {:?}", self.ct.kind),
69                    self.ct.line,
70                    self.ct.col,
71                ));
72            }
73            self.consume(); //consume Collon
74
75            let r = self.parse_value();
76            match r {
77                Ok(v) => values.insert(key, v),
78                Err(_) => return r,
79            };
80
81            match self.ct.kind {
82                TokenKind::Comma => {
83                    self.consume();
84                    if self.ct.kind == TokenKind::RightBrace {
85                        return Err(JSONError::new(
86                            format!("Trailing `{}`", self.ct.value),
87                            self.ct.line,
88                            self.ct.col,
89                        ));
90                    }
91                }
92                TokenKind::RightBrace => {
93                    self.consume();
94                    return Ok(JSONValue::Object(values));
95                }
96                _ => {
97                    return Err(JSONError::new(
98                        format!("Unexpected token {}", self.ct.value),
99                        self.ct.line,
100                        self.ct.col,
101                    ))
102                }
103            };
104        }
105
106        Ok(JSONValue::Object(values))
107    }
108
109    fn parse_array(&mut self) -> Result<JSONValue, JSONError> {
110        let mut values: Vec<JSONValue> = Vec::new();
111
112        //consume LeftBracket
113        self.consume();
114        if self.ct.kind == TokenKind::RightBracket {
115            self.consume();
116            return Ok(JSONValue::Array(values));
117        }
118
119        while self.ct.kind != TokenKind::RightBracket && self.ct.kind != TokenKind::Eof {
120            let rst = self.parse_value();
121            match rst {
122                Ok(v) => values.push(v),
123                Err(err) => return Err(err),
124            }
125
126            match self.ct.kind {
127                TokenKind::Comma => {
128                    self.consume();
129                    if self.ct.kind == TokenKind::RightBracket {
130                        return Err(JSONError::new(
131                            format!("Trailing `{}`", self.ct.value),
132                            self.ct.line,
133                            self.ct.col,
134                        ));
135                    }
136                }
137                TokenKind::RightBracket => {
138                    self.consume();
139                    return Ok(JSONValue::Array(values));
140                }
141                _ => {
142                    return Err(JSONError::new(
143                        format!("Unexpected token {}", self.ct.value),
144                        self.ct.line,
145                        self.ct.col,
146                    ))
147                }
148            };
149        }
150
151        Ok(JSONValue::Array(values))
152    }
153
154    fn parse_value(&mut self) -> Result<JSONValue, JSONError> {
155        let ct = &self.ct;
156        let value = match ct.kind {
157            TokenKind::Null => {
158                self.consume();
159                Ok(JSONValue::Null)
160            }
161            TokenKind::False => {
162                self.consume();
163                Ok(JSONValue::Boolean(false))
164            }
165            TokenKind::True => {
166                self.consume();
167                Ok(JSONValue::Boolean(true))
168            }
169            TokenKind::String => {
170                let v = ct.value.clone();
171                self.consume();
172                Ok(JSONValue::String(v))
173            }
174            TokenKind::Number => {
175                // TODO: distinct int, float
176                match ct.value.parse::<f64>() {
177                    Ok(n) => {
178                        self.consume();
179                        Ok(JSONValue::Number(n))
180                    }
181                    Err(_) => Err(JSONError::new(
182                        format!("{} is NaN ", ct.value),
183                        ct.line,
184                        ct.col,
185                    )),
186                }
187            }
188            TokenKind::LeftBrace => self.parse_object(),
189            TokenKind::LeftBracket => self.parse_array(),
190            _ => {
191                return Err(JSONError::new(
192                    format!("Unexpected token {}", ct.value),
193                    ct.line,
194                    ct.col,
195                ))
196            }
197        };
198
199        // if self.ct.kind != TokenKind::Eof {
200        //     println!("after value consume {:?}", self.ct);
201        //     self.consume();
202        // }
203        value
204    }
205}
206
207#[cfg(test)]
208mod tests {
209
210    #[test]
211    fn test_basic_parsing() {
212        //TODO:
213    }
214
215    #[test]
216    fn complex_parsing() {
217        //TODO:
218    }
219}