1use crate::ast::declaration::VariableDeclaration;
2use crate::ast::expr::{Expr, ExprNode};
3use crate::ast::stmt::{IfBranchStmt, IfStmt, MatchBranch, Stmt, StmtNode};
4use crate::context::Context;
5use crate::lexer::position::Position;
6use crate::lexer::token::Token;
7use crate::parser::Parser;
8
9impl Parser {
10 pub fn parse_match_stmt(&mut self, ctx: &Context) -> crate::core::result::Result<StmtNode> {
11 let pos = self.parse_keyword("match")?;
13
14 self.parse_special_token(Token::BraceLeft)?;
16 let expr = self.parse_expr(ctx)?;
17 self.parse_special_token(Token::BraceRight)?;
18
19 self.parse_special_token(Token::ParenLeft)?;
21
22 let mut branches = vec![];
24 loop {
25 let (token, _) = self.token_stream.peek();
26 match token {
27 Token::ParenRight => {
28 self.parse_special_token(Token::ParenRight)?;
29 break;
30 }
31 _ => {
32 let pattern = self.parse_expr(ctx)?;
34
35 self.parse_special_token(Token::Arrow)?;
37
38 let mut body = vec![];
40
41 let (token, _) = self.token_stream.peek();
43 if token == Token::ParenLeft {
44 body = self.parse_block(ctx)?;
45 } else {
46 let stmt = self.parse_stmt(ctx)?;
48 body.push(stmt);
49 }
50
51 branches.push(MatchBranch::new(pattern, body));
53
54 if self.try_parse_token(Token::Comma) {
56 continue;
57 }
58 }
59 }
60 }
61
62 let match_stmt = Stmt::Match(Box::new(expr), branches);
64 Ok(StmtNode::new(match_stmt, pos))
65 }
66
67 pub fn parse_if_let_stmt(&mut self, ctx: &Context) -> crate::core::result::Result<StmtNode> {
69 let pos = self.parse_keyword("if")?;
71
72 self.parse_keyword("let")?;
74
75 self.parse_special_token(Token::BraceLeft)?;
77
78 let pattern = self.parse_expr(ctx)?;
80
81 self.parse_special_token(Token::Assign)?;
83
84 let expr = self.parse_expr(ctx)?;
86
87 self.parse_special_token(Token::BraceRight)?;
89
90 let body = self.parse_block(ctx)?;
92
93 let mut else_body = None;
95 if self.try_parse_token(Token::Keyword("else".to_string())) {
96 else_body = Some(self.parse_block(ctx)?);
97 }
98
99 let if_let_stmt = Stmt::IfLet(Box::new(pattern), Box::new(expr), body, else_body);
101 Ok(StmtNode::new(if_let_stmt, pos))
102 }
103 pub fn parse_if_const_stmt(&mut self, ctx: &Context) -> crate::core::result::Result<StmtNode> {
104 let pos = self.parse_keyword("if")?;
106 let s = self.val_keyword.clone();
107 self.parse_keyword(s.as_str())?;
109
110 self.parse_special_token(Token::BraceLeft)?;
112
113 let pattern = self.parse_expr(ctx)?;
115
116 self.parse_special_token(Token::Assign)?;
118
119 let expr = self.parse_expr(ctx)?;
121
122 self.parse_special_token(Token::BraceRight)?;
124
125 let body = self.parse_block(ctx)?;
127
128 let mut else_body = None;
130 if self.try_parse_token(Token::Keyword("else".to_string())) {
131 else_body = Some(self.parse_block(ctx)?);
132 }
133
134 let if_let_stmt = Stmt::IfConst(Box::new(pattern), Box::new(expr), body, else_body);
136 Ok(StmtNode::new(if_let_stmt, pos))
137 }
138 pub fn parse_var_stmt(&mut self, ctx: &Context) -> crate::core::result::Result<StmtNode> {
139 let keyword = self.var_keyword.clone();
140 self.parse_decl_stmt(ctx, &keyword, |vd, _| Stmt::VarDecl(vd))
141 }
142
143 pub fn parse_val_stmt(&mut self, ctx: &Context) -> crate::core::result::Result<StmtNode> {
144 let keyword = self.val_keyword.clone();
145 self.parse_decl_stmt(ctx, &keyword, |vd, _| Stmt::ValDecl(vd))
146 }
147
148 pub fn parse_static_stmt(&mut self, ctx: &Context) -> crate::core::result::Result<StmtNode> {
149 if !self.is_in_global_scope() {
151 use crate::core::error::Error;
152 use crate::lexer::position::Position;
153 return Err(Error::Message(
154 "static declarations can only be used in global scope".to_string(),
155 Position::none(),
156 ));
157 }
158 self.parse_decl_stmt(ctx, "static", |vd, _| Stmt::StaticDecl(vd))
159 }
160
161 pub(crate) fn parse_if_branch(
162 &mut self,
163 ctx: &Context,
164 ) -> crate::core::result::Result<(IfBranchStmt, Position)> {
165 let mut p0 = self.parse_keyword("if")?;
166 let p1 = self.parse_special_token(Token::BraceLeft)?;
167 let e = self.parse_expr(ctx).unwrap();
168 let p2 = e.position();
169 let p3 = self.parse_special_token(Token::BraceRight)?;
170 let block = self.parse_block(ctx)?;
171 for b in block.iter() {
172 p0 += b.position();
173 }
174 let branch = IfBranchStmt::new(e, block);
175 Ok((branch, p0 + p1 + p2 + p3))
176 }
177 fn parse_decl_stmt(
178 &mut self,
179 ctx: &Context,
180 keyword: &str,
181 builder: fn(VariableDeclaration, ExprNode) -> Stmt,
182 ) -> crate::core::result::Result<StmtNode> {
183 let p0 = self.parse_keyword(keyword)?;
184 let (name, mut p1) = self.parse_identifier()?;
185 let mut vd = VariableDeclaration::new(name);
186
187 if let Token::Colon = self.token_stream.peek().0 {
189 p1 += self.parse_special_token(Token::Colon)?;
190 let ty = self.parse_type()?;
191 vd = vd.with_type(ty);
192 }
193
194 let p4 = self.parse_special_token(Token::Assign)?;
196 let expr = self.parse_expr(ctx)?;
197 let p5 = expr.position();
198
199 Ok(StmtNode::new(
200 builder(vd.with_default(expr.clone()), expr),
201 p0 + p1 + p4 + p5,
202 ))
203 }
204 pub(crate) fn parse_return_stmt(
205 &mut self,
206 ctx: &Context,
207 ) -> crate::core::result::Result<StmtNode> {
208 let p0 = self.parse_keyword("return")?;
209 if self.token_stream.peek().0 == Token::ParenRight {
210 return Ok(StmtNode::new(Stmt::Return(Box::new(Expr::None.into())), p0));
211 }
212 let expr = self.parse_expr(ctx).expect("parse return stmt error");
213 Ok(StmtNode::new(Stmt::Return(Box::new(expr)), p0))
214 }
215 pub fn parse_while_stmt(&mut self, ctx: &Context) -> crate::core::result::Result<StmtNode> {
216 let mut p0 = self.parse_keyword("while")?;
217 let p1 = self.parse_special_token(Token::BraceLeft)?;
218 let expr = self.parse_expr(ctx)?;
219 let p2 = expr.position();
220 let p3 = self.parse_special_token(Token::BraceRight)?;
221 let block = self.parse_block(ctx)?;
222 for s in block.iter() {
223 p0 += s.position();
224 }
225 Ok(StmtNode::new(
226 Stmt::While(Box::new(expr), block),
227 p0 + p1 + p2 + p3,
228 ))
229 }
230 pub fn parse_if_stmt(&mut self, ctx: &Context) -> crate::core::result::Result<StmtNode> {
231 let mut branches = vec![];
232 let mut else_body = None;
233 let (b, pos) = self.parse_if_branch(ctx).unwrap();
234 branches.push(b);
235
236 loop {
237 let (peek, _) = self.token_stream.peek();
238 match peek.clone() {
239 Token::Keyword(k) if k == "else" => {
240 self.token_stream.next_token();
241 let (peek0, _) = self.token_stream.peek();
242 if let Token::ParenLeft = peek0 {
243 let blocks = self.parse_block(ctx)?;
244 else_body = Some(blocks);
245 break;
246 }
247 let (b0, _) = self.parse_if_branch(ctx)?;
248 branches.push(b0);
249 }
250 _ => break,
251 }
252 }
253 Ok(StmtNode::new(
254 Stmt::If(Box::new(IfStmt::new(branches, else_body))),
255 pos,
256 ))
257 }
258 pub fn parse_for_stmt(&mut self, ctx: &Context) -> crate::core::result::Result<StmtNode> {
259 self.parse_keyword("for")?;
260 self.parse_special_token(Token::BraceLeft)?;
261 let (var_name, _) = self.parse_identifier()?;
262 let _ = self.parse_keyword("in");
263 let e0 = self.parse_expr(ctx)?;
264 self.parse_special_token(Token::BraceRight)?;
265 let body = self.parse_block(ctx)?;
266 Ok(StmtNode::new(
267 Stmt::ForIn(var_name, Box::new(e0), body),
268 Position::none(),
269 ))
270 }
271 pub(crate) fn parse_continue_stmt(&mut self) -> crate::core::result::Result<StmtNode> {
272 todo!()
273 }
274 pub(crate) fn parse_break_stmt(&mut self) -> crate::core::result::Result<StmtNode> {
275 self.parse_keyword("break")?;
276 Ok(StmtNode::new(Stmt::Break, Position::none()))
277 }
278 pub fn parse_stmt(&mut self, ctx: &Context) -> crate::core::result::Result<StmtNode> {
279 loop {
280 let (token, _) = self.token_stream.peek();
281 return Ok(match token {
282 Token::Keyword(k) => match k.as_str() {
283 t if t == self.var_keyword => self.parse_var_stmt(ctx)?,
284 t if t == self.val_keyword => self.parse_val_stmt(ctx).unwrap(),
285 "static" => self.parse_static_stmt(ctx)?,
286 "while" => self.parse_while_stmt(ctx).unwrap(),
287 "for" => self.parse_for_stmt(ctx).unwrap(),
288 "return" => self.parse_return_stmt(ctx).unwrap(),
289 "break" => self.parse_break_stmt()?,
290 "continue" => self.parse_continue_stmt()?,
291 "struct" => {
292 self.parse_struct(ctx)?;
293 continue;
294 }
295 "enum" => {
296 self.parse_enum(ctx)?;
297 continue;
298 }
299 "trait" => {
300 self.parse_trait();
301 continue;
302 }
303 "extern" => {
304 self.parse_extern_function_declaration(ctx).unwrap();
305 continue;
306 }
307 "module" => {
308 self.parse_module(ctx)?;
309 continue;
310 }
311 "match" => {
312 return self.parse_match_stmt(ctx);
313 }
314 "if" => {
315 let (next_token, _) = self.token_stream.peek_nth(1);
317 if next_token.is_keyword("let") {
318 return self.parse_if_let_stmt(ctx);
319 } else if next_token.is_keyword("const") {
320 return self.parse_if_const_stmt(ctx);
321 } else {
322 return self.parse_if_stmt(ctx);
323 }
324 }
325 t => {
326 if t == self.function_keyword {
327 self.parse_function(ctx).unwrap();
328 continue;
329 }
330 dbg!(t);
331 todo!()
332 }
333 },
334 Token::Eof | Token::ParenRight => StmtNode::new(Stmt::Noop, Position::none()),
335 _ => {
336 let e0 = self.parse_expr(ctx)?;
337 let p0 = e0.position();
338 let (peek, p1) = self.token_stream.peek();
339 if let Token::Assign = peek {
340 let p0 = self.parse_special_token(Token::Assign)?;
341 let e1 = self.parse_expr(ctx)?;
342 let p2 = e1.position();
343 return Ok(StmtNode::new(
344 Stmt::Assign(Box::new(e0), Box::new(e1)),
345 p0 + p1 + p2,
346 ));
347 }
348 return Ok(StmtNode::new(Stmt::EvalExpr(Box::new(e0)), p0));
349 }
350 });
351 }
352 }
353}