1pub mod element_type;
4
5use crate::{
6 language::DLanguage,
7 lexer::{DLexer, token_type::DTokenType},
8};
9use oak_core::{
10 GreenNode, TextEdit,
11 parser::{Associativity, Parser, ParserState, Pratt, PrattParser},
12 source::Source,
13};
14
15pub(crate) type State<'a, S> = ParserState<'a, DLanguage, S>;
17
18pub struct DParser<'config> {
20 pub(crate) config: &'config DLanguage,
21}
22
23impl<'config> DParser<'config> {
24 pub fn new(config: &'config DLanguage) -> Self {
26 Self { config }
27 }
28
29 fn skip_trivia<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
31 while let Some(kind) = state.peek_kind() {
32 if matches!(kind, DTokenType::Whitespace | DTokenType::Newline | DTokenType::LineComment | DTokenType::BlockComment | DTokenType::NestedComment) {
33 state.bump();
34 }
35 else {
36 break;
37 }
38 }
39 }
40
41 fn parse_module<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), oak_core::OakError> {
43 let cp = state.checkpoint();
44 state.bump(); self.skip_trivia(state);
46 while let Some(kind) = state.peek_kind() {
48 if matches!(kind, DTokenType::Identifier | DTokenType::Dot) {
49 state.bump();
50 }
51 else {
52 break;
53 }
54 }
55 state.eat(DTokenType::Semicolon);
56 state.finish_at(cp, crate::parser::element_type::DElementType::Module);
57 Ok(())
58 }
59
60 fn parse_import<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), oak_core::OakError> {
62 let cp = state.checkpoint();
63 state.bump(); self.skip_trivia(state);
65 while let Some(kind) = state.peek_kind() {
67 if matches!(kind, DTokenType::Identifier | DTokenType::Dot) {
68 state.bump();
69 }
70 else {
71 break;
72 }
73 }
74 state.eat(DTokenType::Semicolon);
75 state.finish_at(cp, crate::parser::element_type::DElementType::Import);
76 Ok(())
77 }
78
79 fn parse_class<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), oak_core::OakError> {
81 let cp = state.checkpoint();
82 state.bump(); self.skip_trivia(state);
84 if state.at(DTokenType::Identifier) {
86 state.bump();
87 }
88 self.skip_trivia(state);
90 if state.at(DTokenType::Colon) {
91 state.bump();
92 while let Some(kind) = state.peek_kind() {
93 if !matches!(kind, DTokenType::Semicolon | DTokenType::LeftBrace) {
94 state.bump();
95 }
96 else {
97 break;
98 }
99 }
100 }
101 self.skip_trivia(state);
103 if state.at(DTokenType::LeftBrace) {
104 state.bump();
105 while let Some(kind) = state.peek_kind() {
106 if !matches!(kind, DTokenType::RightBrace) {
107 self.parse_statement(state)?;
108 }
109 else {
110 break;
111 }
112 }
113 state.eat(DTokenType::RightBrace);
114 }
115 state.eat(DTokenType::Semicolon);
116 state.finish_at(cp, crate::parser::element_type::DElementType::Class);
117 Ok(())
118 }
119
120 fn parse_struct<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), oak_core::OakError> {
122 let cp = state.checkpoint();
123 state.bump(); self.skip_trivia(state);
125 if state.at(DTokenType::Identifier) {
127 state.bump();
128 }
129 self.skip_trivia(state);
131 if state.at(DTokenType::LeftBrace) {
132 state.bump();
133 while let Some(kind) = state.peek_kind() {
134 if !matches!(kind, DTokenType::RightBrace) {
135 self.parse_statement(state)?;
136 }
137 else {
138 break;
139 }
140 }
141 state.eat(DTokenType::RightBrace);
142 }
143 state.eat(DTokenType::Semicolon);
144 state.finish_at(cp, crate::parser::element_type::DElementType::Struct);
145 Ok(())
146 }
147
148 fn parse_interface<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), oak_core::OakError> {
150 let cp = state.checkpoint();
151 state.bump(); self.skip_trivia(state);
153 if state.at(DTokenType::Identifier) {
155 state.bump();
156 }
157 self.skip_trivia(state);
159 if state.at(DTokenType::Colon) {
160 state.bump();
161 while let Some(kind) = state.peek_kind() {
162 if !matches!(kind, DTokenType::Semicolon | DTokenType::LeftBrace) {
163 state.bump();
164 }
165 else {
166 break;
167 }
168 }
169 }
170 self.skip_trivia(state);
172 if state.at(DTokenType::LeftBrace) {
173 state.bump();
174 while let Some(kind) = state.peek_kind() {
175 if !matches!(kind, DTokenType::RightBrace) {
176 self.parse_statement(state)?;
177 }
178 else {
179 break;
180 }
181 }
182 state.eat(DTokenType::RightBrace);
183 }
184 state.eat(DTokenType::Semicolon);
185 state.finish_at(cp, crate::parser::element_type::DElementType::Interface);
186 Ok(())
187 }
188
189 fn parse_function<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), oak_core::OakError> {
191 let cp = state.checkpoint();
192 state.bump(); self.skip_trivia(state);
194 while let Some(kind) = state.peek_kind() {
196 if !matches!(kind, DTokenType::Identifier) {
197 break;
198 }
199 state.bump();
200 }
201 if state.at(DTokenType::Identifier) {
203 state.bump();
204 }
205 self.skip_trivia(state);
207 if state.at(DTokenType::LeftParen) {
208 state.bump();
209 while let Some(kind) = state.peek_kind() {
210 if !matches!(kind, DTokenType::RightParen) {
211 self.skip_trivia(state);
212 while let Some(kind) = state.peek_kind() {
214 if !matches!(kind, DTokenType::Comma | DTokenType::RightParen) {
215 state.bump();
216 }
217 else {
218 break;
219 }
220 }
221 if state.at(DTokenType::Comma) {
222 state.bump();
223 }
224 }
225 else {
226 break;
227 }
228 }
229 state.eat(DTokenType::RightParen);
230 }
231 self.skip_trivia(state);
233 if state.at(DTokenType::LeftBrace) {
234 state.bump();
235 while let Some(kind) = state.peek_kind() {
236 if !matches!(kind, DTokenType::RightBrace) {
237 self.parse_statement(state)?;
238 }
239 else {
240 break;
241 }
242 }
243 state.eat(DTokenType::RightBrace);
244 }
245 state.eat(DTokenType::Semicolon);
246 state.finish_at(cp, crate::parser::element_type::DElementType::Function);
247 Ok(())
248 }
249
250 fn parse_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), oak_core::OakError> {
252 self.skip_trivia(state);
253 match state.peek_kind() {
254 Some(DTokenType::ModuleKeyword) => self.parse_module(state)?,
255 Some(DTokenType::ImportKeyword) => self.parse_import(state)?,
256 Some(DTokenType::ClassKeyword) => self.parse_class(state)?,
257 Some(DTokenType::StructKeyword) => self.parse_struct(state)?,
258 Some(DTokenType::InterfaceKeyword) => self.parse_interface(state)?,
259 Some(DTokenType::FunctionKeyword) => self.parse_function(state)?,
260 Some(DTokenType::LeftBrace) => {
261 let cp = state.checkpoint();
263 state.bump();
264 while let Some(kind) = state.peek_kind() {
265 if !matches!(kind, DTokenType::RightBrace) {
266 self.parse_statement(state)?;
267 }
268 else {
269 break;
270 }
271 }
272 state.eat(DTokenType::RightBrace);
273 state.finish_at(cp, crate::parser::element_type::DElementType::Block);
274 }
275 Some(DTokenType::IfKeyword) => {
276 let cp = state.checkpoint();
278 state.bump();
279 self.skip_trivia(state);
280 if state.at(DTokenType::LeftParen) {
281 state.bump();
282 while let Some(kind) = state.peek_kind() {
283 if !matches!(kind, DTokenType::RightParen) {
284 state.bump();
285 }
286 else {
287 break;
288 }
289 }
290 state.eat(DTokenType::RightParen);
291 }
292 self.parse_statement(state)?;
293 self.skip_trivia(state);
294 if state.at(DTokenType::ElseKeyword) {
295 state.bump();
296 self.parse_statement(state)?;
297 }
298 state.finish_at(cp, crate::parser::element_type::DElementType::IfStatement);
299 }
300 Some(DTokenType::WhileKeyword) => {
301 let cp = state.checkpoint();
303 state.bump();
304 self.skip_trivia(state);
305 if state.at(DTokenType::LeftParen) {
306 state.bump();
307 while let Some(kind) = state.peek_kind() {
308 if !matches!(kind, DTokenType::RightParen) {
309 state.bump();
310 }
311 else {
312 break;
313 }
314 }
315 state.eat(DTokenType::RightParen);
316 }
317 self.parse_statement(state)?;
318 state.finish_at(cp, crate::parser::element_type::DElementType::WhileStatement);
319 }
320 Some(DTokenType::ForKeyword) => {
321 let cp = state.checkpoint();
323 state.bump();
324 self.skip_trivia(state);
325 if state.at(DTokenType::LeftParen) {
326 state.bump();
327 while let Some(kind) = state.peek_kind() {
329 if !matches!(kind, DTokenType::Semicolon) {
330 state.bump();
331 }
332 else {
333 break;
334 }
335 }
336 state.eat(DTokenType::Semicolon);
337 while let Some(kind) = state.peek_kind() {
339 if !matches!(kind, DTokenType::Semicolon) {
340 state.bump();
341 }
342 else {
343 break;
344 }
345 }
346 state.eat(DTokenType::Semicolon);
347 while let Some(kind) = state.peek_kind() {
349 if !matches!(kind, DTokenType::RightParen) {
350 state.bump();
351 }
352 else {
353 break;
354 }
355 }
356 state.eat(DTokenType::RightParen);
357 }
358 self.parse_statement(state)?;
359 state.finish_at(cp, crate::parser::element_type::DElementType::ForStatement);
360 }
361 Some(DTokenType::ReturnKeyword) => {
362 let cp = state.checkpoint();
364 state.bump();
365 self.skip_trivia(state);
366 while let Some(kind) = state.peek_kind() {
367 if !matches!(kind, DTokenType::Semicolon) {
368 state.bump();
369 }
370 else {
371 break;
372 }
373 }
374 state.eat(DTokenType::Semicolon);
375 state.finish_at(cp, crate::parser::element_type::DElementType::ReturnStatement);
376 }
377 _ => {
378 let cp = state.checkpoint();
380 while let Some(kind) = state.peek_kind() {
381 if !matches!(kind, DTokenType::Semicolon) {
382 state.bump();
383 }
384 else {
385 break;
386 }
387 }
388 state.eat(DTokenType::Semicolon);
389 state.finish_at(cp, crate::parser::element_type::DElementType::ExpressionStatement);
390 }
391 }
392 Ok(())
393 }
394}
395
396impl<'config> Parser<DLanguage> for DParser<'config> {
397 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl oak_core::ParseCache<DLanguage>) -> oak_core::ParseOutput<'a, DLanguage> {
398 let lexer = DLexer::new(self.config);
399 oak_core::parser::parse_with_lexer(&lexer, text, edits, cache, |state| {
400 let checkpoint = state.checkpoint();
401
402 while state.not_at_end() {
403 self.parse_statement(state)?;
404 }
405
406 Ok(state.finish_at(checkpoint, crate::parser::element_type::DElementType::Root))
407 })
408 }
409}
410
411impl<'config> Pratt<DLanguage> for DParser<'config> {
412 fn primary<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, DLanguage> {
413 self.skip_trivia(state);
414 let cp = state.checkpoint();
415 match state.peek_kind() {
416 Some(DTokenType::Identifier) => {
417 state.bump();
418 state.finish_at(cp, crate::parser::element_type::DElementType::Identifier)
419 }
420 Some(DTokenType::IntegerLiteral) | Some(DTokenType::FloatLiteral) | Some(DTokenType::StringLiteral) | Some(DTokenType::CharLiteral) => {
421 state.bump();
422 state.finish_at(cp, crate::parser::element_type::DElementType::Literal)
423 }
424 Some(DTokenType::LeftParen) => {
425 state.bump();
426 let expr = PrattParser::parse(state, 0, self);
427 state.push_child(expr);
428 self.skip_trivia(state);
429 state.eat(DTokenType::RightParen);
430 state.finish_at(cp, crate::parser::element_type::DElementType::ParenthesizedExpression)
431 }
432 _ => {
433 state.bump();
434 state.finish_at(cp, crate::parser::element_type::DElementType::Error)
435 }
436 }
437 }
438
439 fn infix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>, left: &'a GreenNode<'a, DLanguage>, min_precedence: u8) -> Option<&'a GreenNode<'a, DLanguage>> {
440 self.skip_trivia(state);
441 let kind = state.peek_kind()?;
442
443 let (prec, assoc) = match kind {
444 DTokenType::Assign => (1, Associativity::Right),
445 DTokenType::PlusAssign | DTokenType::MinusAssign | DTokenType::MultiplyAssign | DTokenType::DivideAssign | DTokenType::ModuloAssign => (1, Associativity::Right),
446 DTokenType::LogicalOr => (2, Associativity::Left),
447 DTokenType::LogicalAnd => (3, Associativity::Left),
448 DTokenType::Equal | DTokenType::NotEqual | DTokenType::Less | DTokenType::LessEqual | DTokenType::Greater | DTokenType::GreaterEqual => (4, Associativity::Left),
449 DTokenType::Plus | DTokenType::Minus => (5, Associativity::Left),
450 DTokenType::Multiply | DTokenType::Divide | DTokenType::Modulo => (6, Associativity::Left),
451 DTokenType::Dot => (7, Associativity::Left),
452 _ => return None,
453 };
454
455 if prec < min_precedence {
456 return None;
457 }
458
459 let cp = state.checkpoint();
460 state.push_child(left);
461 state.bump();
462 self.skip_trivia(state);
463 let right = PrattParser::parse(state, prec + (assoc as u8), self);
464 state.push_child(right);
465 Some(state.finish_at(cp, crate::parser::element_type::DElementType::BinaryExpression))
466 }
467}