Skip to main content

oak_json/parser/
mod.rs

1/// Element types for JSON.
2pub mod element_type;
3
4use crate::{language::JsonLanguage, lexer::token_type::JsonTokenType, parser::element_type::JsonElementType};
5use oak_core::{OakError, Parser, ParserState, Source, TextEdit, TokenType};
6
7pub(crate) type State<'a, S> = ParserState<'a, JsonLanguage, S>;
8
9/// Parser for JSON.
10pub struct JsonParser<'config> {
11    /// Language configuration.
12    pub(crate) config: &'config JsonLanguage,
13}
14
15impl<'config> JsonParser<'config> {
16    /// Creates a new `JsonParser` with the given language configuration.
17    pub fn new(config: &'config JsonLanguage) -> Self {
18        Self { config }
19    }
20
21    pub(crate) fn parse_value<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
22        self.skip_trivia(state);
23        let token = if let Some(t) = state.current() {
24            if t.kind == JsonTokenType::Eof {
25                return Err(state.unexpected_eof());
26            }
27            t
28        }
29        else {
30            return Err(state.unexpected_eof());
31        };
32
33        let kind = match token.kind {
34            JsonTokenType::LeftBrace => JsonTokenType::Object,
35            JsonTokenType::LeftBracket => JsonTokenType::Array,
36            JsonTokenType::StringLiteral => JsonTokenType::String,
37            JsonTokenType::NumberLiteral => JsonTokenType::Number,
38            JsonTokenType::BooleanLiteral => JsonTokenType::Boolean,
39            JsonTokenType::NullLiteral => JsonTokenType::Null,
40            _ => {
41                if self.config.bare_keys && token.kind == JsonTokenType::BareKey {
42                    state.record_unexpected_token(format!("{:?}", token.kind));
43                    return Err(state.errors.last().unwrap().clone());
44                }
45                state.record_unexpected_token(format!("{:?}", token.kind));
46                return Err(state.errors.last().unwrap().clone());
47            }
48        };
49
50        state.incremental_node(kind.into(), |state| match kind {
51            JsonTokenType::Object => self.parse_object(state),
52            JsonTokenType::Array => self.parse_array(state),
53            _ => {
54                state.bump();
55                Ok(())
56            }
57        })
58    }
59
60    fn parse_object<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
61        if !state.eat(JsonTokenType::LeftBrace) {
62            state.record_expected("{");
63            return Err(state.errors.last().cloned().expect("Error should have been recorded"));
64        }
65
66        let mut first = true;
67        while state.not_at_end() {
68            self.skip_trivia(state);
69            if state.at(JsonTokenType::RightBrace) {
70                break;
71            }
72
73            if state.at(JsonTokenType::Eof) {
74                return Err(state.unexpected_eof());
75            }
76
77            if !first {
78                if !state.eat(JsonTokenType::Comma) {
79                    state.record_expected(",");
80                    // Don't break here to try recover
81                    break;
82                }
83
84                self.skip_trivia(state);
85                if state.at(JsonTokenType::RightBrace) {
86                    if !self.config.trailing_comma {
87                        state.record_trailing_comma_not_allowed();
88                        return Err(state.errors.last().cloned().expect("Error should have been recorded"));
89                    }
90                    break;
91                }
92            }
93            first = false;
94
95            self.parse_object_entry(state)?;
96            self.skip_trivia(state);
97        }
98
99        if !state.eat(JsonTokenType::RightBrace) {
100            // Check if we are at EOF, if so return unexpected EOF
101            if state.at(JsonTokenType::Eof) || !state.not_at_end() {
102                return Err(state.unexpected_eof());
103            }
104            state.record_expected("}");
105            return Err(state.errors.last().cloned().expect("Error should have been recorded"));
106        }
107        Ok(())
108    }
109
110    fn parse_object_entry<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
111        state.incremental_node(JsonElementType::ObjectEntry, |state| {
112            if state.at(JsonTokenType::StringLiteral) || (self.config.bare_keys && state.at(JsonTokenType::BareKey)) {
113                state.bump();
114            }
115            else {
116                state.record_expected("key");
117                return Err(state.errors.last().cloned().expect("Error should have been recorded"));
118            }
119
120            self.skip_trivia(state);
121            if !state.eat(JsonTokenType::Colon) {
122                state.record_expected(":");
123            }
124            self.skip_trivia(state);
125            self.parse_value(state)?;
126            Ok(())
127        })
128    }
129
130    fn parse_array<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
131        if !state.eat(JsonTokenType::LeftBracket) {
132            state.record_expected("[");
133            return Err(state.errors.last().cloned().expect("Error should have been recorded"));
134        }
135
136        let mut first = true;
137        while state.not_at_end() {
138            self.skip_trivia(state);
139            if state.at(JsonTokenType::RightBracket) {
140                break;
141            }
142
143            if state.at(JsonTokenType::Eof) {
144                return Err(state.unexpected_eof());
145            }
146
147            if !first {
148                if !state.eat(JsonTokenType::Comma) {
149                    state.record_expected(",");
150                    break;
151                }
152
153                self.skip_trivia(state);
154                if state.at(JsonTokenType::RightBracket) {
155                    if !self.config.trailing_comma {
156                        state.record_trailing_comma_not_allowed();
157                        return Err(state.errors.last().cloned().expect("Error should have been recorded"));
158                    }
159                    break;
160                }
161            }
162            first = false;
163
164            self.parse_value(state)?;
165            self.skip_trivia(state);
166        }
167
168        if !state.eat(JsonTokenType::RightBracket) {
169            if state.at(JsonTokenType::Eof) || !state.not_at_end() {
170                return Err(state.unexpected_eof());
171            }
172            state.record_expected("]");
173            return Err(state.errors.last().cloned().expect("Error should have been recorded"));
174        }
175        Ok(())
176    }
177
178    fn skip_trivia<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
179        while let Some(token) = state.current() {
180            if token.kind.is_ignored() {
181                state.bump();
182            }
183            else {
184                break;
185            }
186        }
187    }
188}
189
190impl<'config> Parser<JsonLanguage> for JsonParser<'config> {
191    fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl oak_core::ParseCache<JsonLanguage>) -> oak_core::ParseOutput<'a, JsonLanguage> {
192        let lexer = crate::lexer::JsonLexer::new(self.config);
193        oak_core::parser::parse_with_lexer(&lexer, text, edits, cache, |state| {
194            let checkpoint = state.checkpoint();
195            let res = self.parse_value(state);
196            if res.is_err() {
197                // If parsing fails, we might still want to return a partial tree or an error tree
198                // But parse_value handles errors by returning Result<(), OakError>
199                // And it records errors in state.errors
200            }
201
202            // Ensure we consume all remaining trivia/whitespace
203            while state.not_at_end() {
204                if let Some(token) = state.current() {
205                    if token.kind.is_ignored() {
206                        state.bump(); // Changed from state.advance() to state.bump() to include in tree
207                        continue;
208                    }
209                }
210                break;
211            }
212
213            let root = state.finish_at(checkpoint, crate::parser::element_type::JsonElementType::Root);
214            Ok(root)
215        })
216    }
217}