Skip to main content

oak_rhombus/parser/
mod.rs

1#![doc = include_str!("readme.md")]
2
3/// Element type definitions for Rhombus parser.
4pub 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
19/// Parser for the Rhombus language.
20pub struct RhombusParser<'config> {
21    pub(crate) config: &'config RhombusLanguage,
22}
23
24impl<'config> RhombusParser<'config> {
25    /// Creates a new `RhombusParser` with the given configuration.
26    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        // Rhombus statements often end with a newline or are grouped in blocks
34        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        // Check for special forms
64        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); // Using Identifier for now
80                    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); // Using Identifier for now
96                    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}