ephemeris_documents/json/
parser.rs1use super::Dialect;
4use super::cst::{
5 Array, Comma, Document, Item, Key, Kind, Member, Object, Scalar, Tail, Trivia, Value,
6};
7use super::lexer::{Lexer, Token, TokenKind};
8use crate::error::{JsonError, JsonErrorKind};
9
10const MAX_DEPTH: usize = 128;
11
12struct Next {
14 comma: Comma,
16 leading: String,
19}
20
21pub(super) struct Parser<'a> {
22 tokens: Vec<Token<'a>>,
23 index: usize,
24 end: usize,
25}
26
27impl<'a> Parser<'a> {
28 pub(super) fn parse(source: &'a str, dialect: Dialect) -> Result<Document, JsonError> {
30 let mut parser = Self {
31 tokens: Lexer::tokenize(source)?,
32 index: 0,
33 end: source.len(),
34 };
35 let leading = Trivia::new(parser.trivia());
36 if parser.peek().is_none() {
37 let value = Value::new(leading, Kind::Object(Object::new()));
38 return Ok(Document::parsed(
39 dialect,
40 value,
41 Trivia::new("\n".to_owned()),
42 ));
43 }
44 let value = parser.value(0, leading)?;
45 let trailing = Trivia::new(parser.trivia());
46 if let Some(token) = parser.peek() {
47 return Err(JsonError {
48 offset: token.start,
49 kind: JsonErrorKind::TrailingContent,
50 });
51 }
52 Ok(Document::parsed(dialect, value, trailing))
53 }
54
55 fn peek(&self) -> Option<&Token<'a>> {
56 self.tokens.get(self.index)
57 }
58
59 const fn advance(&mut self) {
60 self.index = self.index.saturating_add(1);
61 }
62
63 fn at(&self, kind: &TokenKind) -> bool {
64 self.peek().is_some_and(|token| token.kind == *kind)
65 }
66
67 fn eat(&mut self, kind: &TokenKind) -> bool {
68 let found = self.at(kind);
69 if found {
70 self.advance();
71 }
72 found
73 }
74
75 fn unexpected(&self) -> JsonError {
77 self.peek().map_or(
78 JsonError {
79 offset: self.end,
80 kind: JsonErrorKind::UnexpectedEnd,
81 },
82 |token| JsonError {
83 offset: token.start,
84 kind: JsonErrorKind::UnexpectedCharacter {
85 found: token.text.chars().next().unwrap_or_default(),
86 },
87 },
88 )
89 }
90
91 fn expect(&mut self, kind: &TokenKind) -> Result<(), JsonError> {
92 if self.eat(kind) {
93 Ok(())
94 } else {
95 Err(self.unexpected())
96 }
97 }
98
99 fn trivia(&mut self) -> String {
101 let mut text = String::new();
102 while let Some(token) = self.peek()
103 && token.kind.is_trivia()
104 {
105 text.push_str(token.text);
106 self.advance();
107 }
108 text
109 }
110
111 fn split_line(&mut self) -> (String, String) {
114 let mut head = String::new();
115 while let Some(token) = self.peek()
116 && token.kind.is_trivia()
117 {
118 let text = token.text;
119 let cut = if token.kind == TokenKind::Whitespace {
120 text.find(Lexer::is_line_terminator)
121 } else {
122 None
123 };
124 self.advance();
125 let Some((before, after)) = cut.and_then(|at| text.split_at_checked(at)) else {
126 head.push_str(text);
127 continue;
128 };
129 head.push_str(before);
130 let mut rest = after.to_owned();
131 rest.push_str(&self.trivia());
132 return (head, rest);
133 }
134 (head, String::new())
135 }
136
137 fn tail(&mut self) -> (Tail, Next) {
139 let saved = self.index;
140 let between = self.trivia();
141 if self.eat(&TokenKind::Comma) {
142 let (trailing, rest) = self.split_line();
143 let tail = Tail::new(Trivia::new(between), Comma::Present, Trivia::new(trailing));
144 return (
145 tail,
146 Next {
147 comma: Comma::Present,
148 leading: rest,
149 },
150 );
151 }
152 self.index = saved;
153 let (trailing, rest) = self.split_line();
154 let tail = Tail::new(Trivia::default(), Comma::Absent, Trivia::new(trailing));
155 (
156 tail,
157 Next {
158 comma: Comma::Absent,
159 leading: rest,
160 },
161 )
162 }
163
164 fn value(&mut self, depth: usize, leading: Trivia) -> Result<Value, JsonError> {
165 self.kind(depth).map(|kind| Value::new(leading, kind))
166 }
167
168 fn kind(&mut self, depth: usize) -> Result<Kind, JsonError> {
169 let Some(token) = self.peek() else {
170 return Err(self.unexpected());
171 };
172 let (start, text) = (token.start, token.text);
173 match &token.kind {
174 TokenKind::OpenBrace | TokenKind::OpenBracket if depth >= MAX_DEPTH => Err(JsonError {
175 offset: start,
176 kind: JsonErrorKind::DepthExceeded,
177 }),
178 TokenKind::OpenBrace => {
179 self.advance();
180 self.object(depth).map(Kind::Object)
181 }
182 TokenKind::OpenBracket => {
183 self.advance();
184 self.array(depth).map(Kind::Array)
185 }
186 TokenKind::String(_) | TokenKind::Number => Ok(self.scalar(text, start)),
187 TokenKind::Identifier(_)
188 if matches!(text, "true" | "false" | "null" | "Infinity" | "NaN") =>
189 {
190 Ok(self.scalar(text, start))
191 }
192 TokenKind::CloseBrace
193 | TokenKind::CloseBracket
194 | TokenKind::Colon
195 | TokenKind::Comma
196 | TokenKind::Identifier(_)
197 | TokenKind::Whitespace
198 | TokenKind::LineComment
199 | TokenKind::BlockComment => Err(self.unexpected()),
200 }
201 }
202
203 fn scalar(&mut self, text: &str, offset: usize) -> Kind {
204 self.advance();
205 Kind::Scalar(Scalar::from_source(text.to_owned(), offset))
206 }
207
208 fn key(&mut self) -> Result<Key, JsonError> {
209 let Some(token) = self.peek() else {
210 return Err(self.unexpected());
211 };
212 let name = match &token.kind {
213 TokenKind::String(Some(name)) | TokenKind::Identifier(name) => name.clone(),
214 TokenKind::String(None) => {
215 return Err(JsonError {
216 offset: token.start,
217 kind: JsonErrorKind::InvalidEscape,
218 });
219 }
220 TokenKind::OpenBrace
221 | TokenKind::CloseBrace
222 | TokenKind::OpenBracket
223 | TokenKind::CloseBracket
224 | TokenKind::Colon
225 | TokenKind::Comma
226 | TokenKind::Number
227 | TokenKind::Whitespace
228 | TokenKind::LineComment
229 | TokenKind::BlockComment => return Err(self.unexpected()),
230 };
231 let key = Key::from_source(token.text.to_owned(), name);
232 self.advance();
233 Ok(key)
234 }
235
236 fn elements(
239 &mut self,
240 close: &TokenKind,
241 mut element: impl FnMut(&mut Self, Trivia) -> Result<Next, JsonError>,
242 ) -> Result<Trivia, JsonError> {
243 let mut next = Next {
244 comma: Comma::Present,
245 leading: String::new(),
246 };
247 loop {
248 let mut leading = next.leading;
249 leading.push_str(&self.trivia());
250 if self.eat(close) {
251 return Ok(Trivia::new(leading));
252 }
253 if next.comma == Comma::Absent {
254 return Err(self.unexpected());
255 }
256 next = element(self, Trivia::new(leading))?;
257 }
258 }
259
260 fn object(&mut self, depth: usize) -> Result<Object, JsonError> {
262 let mut object = Object::new();
263 let inner = self.elements(&TokenKind::CloseBrace, |parser, leading| {
264 let key_start = parser.peek().map_or(parser.end, |token| token.start);
265 let key = parser.key()?;
266 let after_key = Trivia::new(parser.trivia());
267 parser.expect(&TokenKind::Colon)?;
268 let after_colon = Trivia::new(parser.trivia());
269 let value = parser.value(depth.saturating_add(1), leading)?;
270 let (tail, next) = parser.tail();
271 object
272 .push(Member::parsed(key, after_key, after_colon, value, tail))
273 .map_err(|duplicate| JsonError {
274 offset: key_start,
275 kind: JsonErrorKind::DuplicateKey {
276 name: duplicate.name,
277 },
278 })?;
279 Ok(next)
280 })?;
281 Ok(object.closed_by(inner))
282 }
283
284 fn array(&mut self, depth: usize) -> Result<Array, JsonError> {
286 let mut items = Vec::new();
287 let inner = self.elements(&TokenKind::CloseBracket, |parser, leading| {
288 let value = parser.value(depth.saturating_add(1), leading)?;
289 let (tail, next) = parser.tail();
290 items.push(Item::parsed(value, tail));
291 Ok(next)
292 })?;
293 Ok(Array::parsed(items, inner))
294 }
295}