Skip to main content

oak_von/parser/
mod.rs

1use oak_core::{
2    OakError, Source, TextEdit, TokenType,
3    parser::{ParseCache, Parser, ParserState},
4};
5
6/// Element types for the VON parser.
7pub mod element_type;
8use crate::{
9    language::VonLanguage,
10    lexer::{VonLexer, VonTokenType},
11};
12pub use element_type::VonElementType;
13
14pub(crate) type State<'a, S> = ParserState<'a, VonLanguage, S>;
15
16/// Parser for VON (Value-Oriented Notation).
17pub struct VonParser<'config> {
18    pub(crate) config: &'config VonLanguage,
19}
20
21impl<'config> VonParser<'config> {
22    /// Creates a new VON parser.
23    pub fn new(config: &'config VonLanguage) -> Self {
24        Self { config }
25    }
26
27    /// Parses a value in VON.
28    ///
29    /// Values can be objects, arrays, enums, strings, numbers, booleans, or null.
30    pub(crate) fn parse_value<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
31        self.skip_trivia(state);
32        state.incremental_node(VonElementType::Value, |state| {
33            let token = if let Some(t) = state.current() {
34                if t.kind == VonTokenType::Eof {
35                    return Err(state.unexpected_eof());
36                }
37                t
38            }
39            else {
40                return Err(state.unexpected_eof());
41            };
42
43            match token.kind {
44                VonTokenType::LeftBrace => self.parse_object(state),
45                VonTokenType::LeftBracket => self.parse_array(state),
46                VonTokenType::Identifier => self.parse_enum(state),
47                VonTokenType::StringLiteral | VonTokenType::NumberLiteral | VonTokenType::BoolLiteral | VonTokenType::NullLiteral => {
48                    state.bump();
49                    Ok(())
50                }
51                _ => {
52                    state.record_unexpected_token(format!("{:?}", token.kind));
53                    Err(state.errors.last().unwrap().clone())
54                }
55            }
56        })
57    }
58
59    /// Parses an enum variant in VON.
60    fn parse_enum<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
61        state.incremental_node(VonElementType::Enum, |state| {
62            if !state.eat(VonTokenType::Identifier) {
63                state.record_expected("variant");
64                return Err(state.errors.last().cloned().expect("Error should have been recorded"));
65            }
66
67            self.skip_trivia(state);
68            if state.at(VonTokenType::LeftBrace) || state.at(VonTokenType::LeftBracket) {
69                self.parse_value(state)?;
70            }
71            Ok(())
72        })
73    }
74
75    /// Parses the content of an object in VON.
76    pub(crate) fn parse_object_inner<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
77        let mut first = true;
78        while state.not_at_end() {
79            self.skip_trivia(state);
80            if state.at(VonTokenType::RightBrace) {
81                break;
82            }
83
84            if state.at(VonTokenType::Eof) {
85                break;
86            }
87
88            if !first {
89                // Comma is optional, but consume it if it exists
90                if state.eat(VonTokenType::Comma) {
91                    self.skip_trivia(state);
92                    if state.at(VonTokenType::RightBrace) || state.at(VonTokenType::Eof) {
93                        break;
94                    }
95                }
96            }
97            first = false;
98
99            // Check if it's actually an ObjectEntry (starts with Identifier or StringLiteral)
100            if !state.at(VonTokenType::Identifier) && !state.at(VonTokenType::StringLiteral) {
101                break;
102            }
103
104            self.parse_object_entry(state)?;
105            self.skip_trivia(state);
106        }
107        Ok(())
108    }
109
110    /// Parses an object in VON.
111    fn parse_object<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
112        state.incremental_node(VonElementType::Object, |state| {
113            if !state.eat(VonTokenType::LeftBrace) {
114                state.record_expected("{");
115                return Err(state.errors.last().cloned().expect("Error should have been recorded"));
116            }
117
118            self.parse_object_inner(state)?;
119
120            if !state.eat(VonTokenType::RightBrace) {
121                if state.at(VonTokenType::Eof) || !state.not_at_end() {
122                    return Err(state.unexpected_eof());
123                }
124                state.record_expected("}");
125            }
126            Ok(())
127        })
128    }
129
130    /// Parses an entry in an object in VON.
131    fn parse_object_entry<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
132        state.incremental_node(VonElementType::ObjectEntry, |state| {
133            if state.at(VonTokenType::Identifier) || state.at(VonTokenType::StringLiteral) {
134                state.bump();
135            }
136            else {
137                state.record_expected("key");
138                return Err(state.errors.last().cloned().expect("Error should have been recorded"));
139            }
140
141            self.skip_trivia(state);
142            if state.at(VonTokenType::Eq) {
143                state.bump();
144            }
145            else {
146                state.record_expected("=");
147            }
148            self.skip_trivia(state);
149            // Ensure we haven't reached EOF or } before trying to parse a value
150            if state.at(VonTokenType::RightBrace) || state.at(VonTokenType::Eof) {
151                state.record_expected("value");
152                return Err(state.errors.last().cloned().expect("Error should have been recorded"));
153            }
154            self.parse_value(state)?;
155            Ok(())
156        })
157    }
158
159    /// Parses an array in VON.
160    fn parse_array<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
161        state.incremental_node(VonElementType::Array, |state| {
162            if !state.eat(VonTokenType::LeftBracket) {
163                state.record_expected("[");
164                return Err(state.errors.last().cloned().expect("Error should have been recorded"));
165            }
166
167            let mut first = true;
168            while state.not_at_end() {
169                self.skip_trivia(state);
170                if state.at(VonTokenType::RightBracket) {
171                    break;
172                }
173
174                if state.at(VonTokenType::Eof) {
175                    return Err(state.unexpected_eof());
176                }
177
178                if !first {
179                    // Comma is optional
180                    if state.eat(VonTokenType::Comma) {
181                        self.skip_trivia(state);
182                        if state.at(VonTokenType::RightBracket) {
183                            break;
184                        }
185                    }
186                }
187                first = false;
188
189                state.incremental_node(VonElementType::ArrayElement, |state| self.parse_value(state))?;
190                self.skip_trivia(state);
191            }
192
193            if !state.eat(VonTokenType::RightBracket) {
194                if state.at(VonTokenType::Eof) || !state.not_at_end() {
195                    return Err(state.unexpected_eof());
196                }
197                state.record_expected("]");
198            }
199            Ok(())
200        })
201    }
202
203    /// Skips whitespace and comments.
204    fn skip_trivia<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
205        while let Some(token) = state.current() {
206            if token.kind.is_ignored() {
207                state.bump();
208            }
209            else {
210                break;
211            }
212        }
213    }
214}
215
216impl<'config> Parser<VonLanguage> for VonParser<'config> {
217    fn parse<'a, S: Source + ?Sized>(&self, source: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<VonLanguage>) -> oak_core::ParseOutput<'a, VonLanguage> {
218        let lexer = VonLexer::new(&self.config);
219        oak_core::parser::parse_with_lexer(&lexer, source, edits, cache, |state| {
220            let checkpoint = state.checkpoint();
221            self.skip_trivia(state);
222
223            // Check if it is an implicit root object (does not start with { or [)
224            if state.at(VonTokenType::LeftBrace) || state.at(VonTokenType::LeftBracket) {
225                let _ = self.parse_value(state);
226            }
227            else if state.at(VonTokenType::Identifier) {
228                // If it starts with an identifier, it might be an implicit object or Enum
229                // We first try to parse as an implicit object, if it fails then backtrack (here simply handled as an implicit object)
230                let _ = state.incremental_node(VonElementType::Object, |state| self.parse_object_inner(state));
231            }
232            else if state.at(VonTokenType::Eof) {
233                // Empty file
234            }
235            else {
236                // Otherwise, try to parse as a normal value
237                let _ = self.parse_value(state);
238            }
239
240            while state.not_at_end() {
241                if let Some(token) = state.current() {
242                    if token.kind.is_ignored() {
243                        state.bump();
244                        continue;
245                    }
246                }
247                break;
248            }
249
250            Ok(state.finish_at(checkpoint, crate::parser::element_type::VonElementType::Root))
251        })
252    }
253}