Skip to main content

oak_mojo/parser/
mod.rs

1pub mod element_type;
2pub use element_type::MojoElementType;
3
4use crate::{
5    MojoLanguage,
6    ast::*,
7    lexer::{MojoLexer, MojoTokenType},
8};
9use oak_core::{
10    OakError,
11    parser::{
12        ParseCache, ParseOutput, Parser, ParserState, parse_with_lexer,
13        pratt::{Associativity, Pratt, PrattParser},
14    },
15    source::{Source, TextEdit},
16    tree::GreenNode,
17};
18
19pub(crate) type State<'a, S> = ParserState<'a, MojoLanguage, S>;
20
21/// Mojo 语法解析器
22#[derive(Default)]
23pub struct MojoParser {}
24
25impl Parser<MojoLanguage> for MojoParser {
26    fn parse<'a, S: Source + ?Sized>(&self, source: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<MojoLanguage>) -> ParseOutput<'a, MojoLanguage> {
27        let lexer = MojoLexer::new();
28        parse_with_lexer(&lexer, source, edits, cache, |state| self.parse_root(state))
29    }
30}
31
32impl MojoParser {
33    pub fn new() -> Self {
34        Self::default()
35    }
36
37    pub(crate) fn parse_root<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<&'a GreenNode<'a, MojoLanguage>, OakError> {
38        let cp = state.checkpoint();
39        while state.not_at_end() {
40            self.skip_trivia(state);
41            if !state.not_at_end() {
42                break;
43            }
44            if state.at(MojoTokenType::Newline) {
45                state.bump();
46                continue;
47            }
48            self.parse_statement(state)?;
49        }
50        Ok(state.finish_at(cp, MojoElementType::Root.into()))
51    }
52
53    fn skip_trivia<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
54        while state.not_at_end() {
55            if let Some(kind) = state.peek_kind() {
56                if kind == MojoTokenType::Whitespace || kind == MojoTokenType::Comment {
57                    state.bump();
58                    continue;
59                }
60            }
61            break;
62        }
63    }
64
65    fn parse_statement<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
66        self.skip_trivia(state);
67        if state.at(MojoTokenType::Fn) {
68            self.parse_function_def(state)
69        }
70        else if state.at(MojoTokenType::Var) || state.at(MojoTokenType::Let) {
71            self.parse_variable_decl(state)
72        }
73        else if state.at(MojoTokenType::If) {
74            self.parse_if_stmt(state)
75        }
76        else if state.at(MojoTokenType::While) {
77            self.parse_while_stmt(state)
78        }
79        else if state.at(MojoTokenType::Return) {
80            self.parse_return_stmt(state)
81        }
82        else {
83            self.parse_expression_stmt(state)
84        }
85    }
86
87    fn parse_function_def<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
88        state.incremental_node(MojoElementType::FunctionDef.into(), |state| {
89            state.expect(MojoTokenType::Fn)?;
90            self.skip_trivia(state);
91            state.expect(MojoTokenType::Identifier)?;
92            self.skip_trivia(state);
93            state.expect(MojoTokenType::LeftParen)?;
94            // TODO: Parameters
95            state.expect(MojoTokenType::RightParen)?;
96            self.skip_trivia(state);
97            if state.eat(MojoTokenType::Arrow) {
98                self.skip_trivia(state);
99                state.expect(MojoTokenType::Identifier)?; // Return type
100                self.skip_trivia(state);
101            }
102            state.expect(MojoTokenType::Colon)?;
103            self.parse_block(state)
104        })
105    }
106
107    fn parse_variable_decl<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
108        state.incremental_node(MojoElementType::VariableDecl.into(), |state| {
109            if state.at(MojoTokenType::Var) {
110                state.bump();
111            }
112            else {
113                state.expect(MojoTokenType::Let)?;
114            }
115            self.skip_trivia(state);
116            state.expect(MojoTokenType::Identifier)?;
117            self.skip_trivia(state);
118            if state.eat(MojoTokenType::Colon) {
119                self.skip_trivia(state);
120                state.expect(MojoTokenType::Identifier)?; // Type
121                self.skip_trivia(state);
122            }
123            if state.eat(MojoTokenType::Equal) {
124                self.skip_trivia(state);
125                self.parse_expression(state, 0);
126            }
127            state.eat(MojoTokenType::Newline);
128            Ok(())
129        })
130    }
131
132    fn parse_if_stmt<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
133        state.incremental_node(MojoElementType::IfStatement.into(), |state| {
134            state.expect(MojoTokenType::If)?;
135            self.skip_trivia(state);
136            self.parse_expression(state, 0);
137            self.skip_trivia(state);
138            state.expect(MojoTokenType::Colon)?;
139            self.parse_block(state)?;
140            self.skip_trivia(state);
141            if state.eat(MojoTokenType::Else) {
142                self.skip_trivia(state);
143                if state.at(MojoTokenType::If) {
144                    self.parse_if_stmt(state)?;
145                }
146                else {
147                    state.expect(MojoTokenType::Colon)?;
148                    self.parse_block(state)?;
149                }
150            }
151            Ok(())
152        })
153    }
154
155    fn parse_while_stmt<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
156        state.incremental_node(MojoElementType::WhileStatement.into(), |state| {
157            state.expect(MojoTokenType::While)?;
158            self.skip_trivia(state);
159            self.parse_expression(state, 0);
160            self.skip_trivia(state);
161            state.expect(MojoTokenType::Colon)?;
162            self.parse_block(state)
163        })
164    }
165
166    fn parse_return_stmt<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
167        state.incremental_node(MojoElementType::ReturnStatement.into(), |state| {
168            state.expect(MojoTokenType::Return)?;
169            self.skip_trivia(state);
170            if !state.at(MojoTokenType::Newline) && !state.at(MojoTokenType::EndOfStream) {
171                self.parse_expression(state, 0);
172            }
173            state.eat(MojoTokenType::Newline);
174            Ok(())
175        })
176    }
177
178    fn parse_expression_stmt<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
179        state.incremental_node(MojoElementType::ExpressionStatement.into(), |state| {
180            self.parse_expression(state, 0);
181            state.eat(MojoTokenType::Newline);
182            Ok(())
183        })
184    }
185
186    fn parse_block<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
187        state.incremental_node(MojoElementType::Block.into(), |state| {
188            // 跳过冒号后的空格
189            self.skip_trivia(state);
190            // 必须有一个换行符
191            state.expect(MojoTokenType::Newline)?;
192            // 之后可能有多个空行
193            while state.eat(MojoTokenType::Newline) {
194                self.skip_trivia(state);
195            }
196            // 缩进开始
197            state.expect(MojoTokenType::Indent)?;
198            while state.not_at_end() && !state.at(MojoTokenType::Dedent) {
199                self.skip_trivia(state);
200                if state.eat(MojoTokenType::Newline) {
201                    continue;
202                }
203                self.parse_statement(state)?;
204            }
205            state.expect(MojoTokenType::Dedent)
206        })
207    }
208
209    fn parse_expression<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>, min_precedence: u8) -> &'a GreenNode<'a, MojoLanguage> {
210        PrattParser::parse(state, min_precedence, self)
211    }
212}
213
214impl Pratt<MojoLanguage> for MojoParser {
215    fn primary<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, MojoLanguage> {
216        self.skip_trivia(state);
217        let cp = state.checkpoint();
218        if state.at(MojoTokenType::Identifier) {
219            state.bump();
220            state.finish_at(cp, MojoElementType::IdentifierExpr.into())
221        }
222        else if state.at(MojoTokenType::Integer) || state.at(MojoTokenType::Float) || state.at(MojoTokenType::String) {
223            state.bump();
224            state.finish_at(cp, MojoElementType::LiteralExpr.into())
225        }
226        else if state.at(MojoTokenType::LeftParen) {
227            state.bump();
228            self.parse_expression(state, 0);
229            state.expect(MojoTokenType::RightParen).ok();
230            state.finish_at(cp, MojoElementType::Grouping.into())
231        }
232        else {
233            state.bump(); // Error recovery
234            state.finish_at(cp, MojoElementType::Error.into())
235        }
236    }
237
238    fn prefix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> &'a GreenNode<'a, MojoLanguage> {
239        self.primary(state)
240    }
241
242    fn infix<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>, left: &'a GreenNode<'a, MojoLanguage>, min_precedence: u8) -> Option<&'a GreenNode<'a, MojoLanguage>> {
243        self.skip_trivia(state);
244        let kind = state.peek_kind()?;
245        let (precedence, associativity) = match kind {
246            MojoTokenType::Plus | MojoTokenType::Minus => (10, Associativity::Left),
247            MojoTokenType::Star | MojoTokenType::Slash | MojoTokenType::Percent => (20, Associativity::Left),
248            MojoTokenType::EqualEqual | MojoTokenType::NotEqual | MojoTokenType::Less | MojoTokenType::LessEqual | MojoTokenType::Greater | MojoTokenType::GreaterEqual => (5, Associativity::Left),
249            _ => return None,
250        };
251
252        if precedence < min_precedence {
253            return None;
254        }
255
256        let cp = state.checkpoint_before(left);
257        state.bump();
258        let next_prec = if associativity == Associativity::Left { precedence + 1 } else { precedence };
259        self.parse_expression(state, next_prec);
260        Some(state.finish_at(cp, MojoElementType::BinaryExpr.into()))
261    }
262}