oak_rhombus/parser/
mod.rs1#![doc = include_str!("readme.md")]
2
3pub mod element_type;
5
6use crate::{
7 language::RhombusLanguage,
8 lexer::{RhombusLexer, token_type::RhombusTokenType},
9 parser::element_type::RhombusElementType,
10};
11use oak_core::{
12 OakError,
13 parser::{ParseCache, ParseOutput, Parser, ParserState, parse_with_lexer},
14 source::{Source, TextEdit},
15};
16
17pub(crate) type State<'a, S> = ParserState<'a, RhombusLanguage, S>;
18
19pub struct RhombusParser<'config> {
21 pub(crate) config: &'config RhombusLanguage,
22}
23
24impl<'config> RhombusParser<'config> {
25 pub fn new(config: &'config RhombusLanguage) -> Self {
27 Self { config }
28 }
29
30 fn parse_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
31 let cp = state.checkpoint();
32
33 self.parse_expression(state)?;
35
36 state.finish_at(cp, RhombusElementType::Statement);
37 Ok(())
38 }
39
40 fn parse_expression<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
41 match state.peek_kind() {
42 Some(RhombusTokenType::LeftParen) | Some(RhombusTokenType::LeftBracket) | Some(RhombusTokenType::LeftBrace) => self.parse_block(state),
43 Some(_) => {
44 state.bump();
45 Ok(())
46 }
47 None => Ok(()),
48 }
49 }
50
51 fn parse_block<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
52 let cp = state.checkpoint();
53 let open_kind = state.peek_kind();
54 let close_kind = match open_kind {
55 Some(RhombusTokenType::LeftParen) => Some(RhombusTokenType::RightParen),
56 Some(RhombusTokenType::LeftBracket) => Some(RhombusTokenType::RightBracket),
57 Some(RhombusTokenType::LeftBrace) => Some(RhombusTokenType::RightBrace),
58 _ => None,
59 };
60
61 state.bump();
62
63 if let Some(token_type) = state.peek_kind() {
65 match token_type {
66 RhombusTokenType::Require => {
67 state.bump();
68 while state.not_at_end() {
69 if let Some(ck) = close_kind {
70 if state.at(ck) {
71 break;
72 }
73 }
74 self.parse_statement(state)?;
75 }
76 if let Some(ck) = close_kind {
77 state.expect(ck).ok();
78 }
79 state.finish_at(cp, RhombusElementType::Identifier); return Ok(());
81 }
82 RhombusTokenType::Provide => {
83 state.bump();
84 while state.not_at_end() {
85 if let Some(ck) = close_kind {
86 if state.at(ck) {
87 break;
88 }
89 }
90 self.parse_statement(state)?;
91 }
92 if let Some(ck) = close_kind {
93 state.expect(ck).ok();
94 }
95 state.finish_at(cp, RhombusElementType::Identifier); return Ok(());
97 }
98 _ => {}
99 }
100 }
101
102 while state.not_at_end() {
103 if let Some(ck) = close_kind {
104 if state.at(ck) {
105 break;
106 }
107 }
108 self.parse_statement(state)?;
109 }
110 if let Some(ck) = close_kind {
111 state.expect(ck).ok();
112 }
113 state.finish_at(cp, RhombusElementType::Block);
114 Ok(())
115 }
116}
117
118impl<'config> Parser<RhombusLanguage> for RhombusParser<'config> {
119 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<RhombusLanguage>) -> ParseOutput<'a, RhombusLanguage> {
120 let lexer = RhombusLexer::new(&self.config);
121 parse_with_lexer(&lexer, text, edits, cache, |state| {
122 let checkpoint = state.checkpoint();
123
124 while state.not_at_end() {
125 self.parse_statement(state)?
126 }
127
128 Ok(state.finish_at(checkpoint, RhombusElementType::SourceFile))
129 })
130 }
131}