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#[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 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)?; 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)?; 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 self.skip_trivia(state);
190 state.expect(MojoTokenType::Newline)?;
192 while state.eat(MojoTokenType::Newline) {
194 self.skip_trivia(state);
195 }
196 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(); 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}