use crate::{ ast::err::ParseError, ast::types::{ BlockStmt, BreakStmt, ContinueStmt, ForInit, ForStmt, IfElseBranch, IfStmt, ReturnStmt, Statement, WhileStmt, }, lexer::types::TokenValue, }; use super::{ParseProcessError, ParseType, Parser}; impl Parser { pub(super) fn parse_block_stmt(&mut self, parse_type: ParseType) -> Result { if self.peek().value != TokenValue::LBrace { if parse_type == ParseType::MustParse { let token = self.next().clone(); self.diagnostics.add_from_frontend_error( ParseError::ExpectedBefore(token.value, "`{`"), token.span, ); return Err(ParseProcessError::ErrorInMatch); } return Err(ParseProcessError::TryNext); } self.advance(1); let mut statements = vec![]; // println!("parse block stmt"); loop { if self.is_eof() { let span = self.last().span; self.diagnostics .add_from_frontend_error(ParseError::ExpectedBefore(TokenValue::Eof, "`}`"), span); return Err(ParseProcessError::ErrorInMatch); } if matches!(self.peek().value, TokenValue::Semicolon) { // like a();; self.advance(1); continue; } if matches!(self.peek().value, TokenValue::RBrace) { self.advance(1); break; } // parse statement here match self.parse_stmt() { Ok(stmt) => statements.push(stmt), Err(_) => { self.until_next_token(&[TokenValue::Semicolon, TokenValue::RBrace]); if self.last().value == TokenValue::RBrace { break; } } } } // println!("finish parse block stmt"); Ok(BlockStmt { statements }) } fn parse_stmt(&mut self) -> Result { if self.peek().value == TokenValue::Semicolon { self.advance(1); return Ok(Statement::Block(BlockStmt { statements: vec![] })); } match self.parse_var_decl_stmt(ParseType::TryParse) { Ok(var_decl) => return Ok(Statement::VarDecl(var_decl)), Err(ParseProcessError::ErrorInMatch) => return Err(ParseProcessError::ErrorInMatch), Err(_) => {}, }; match self.parse_return_stmt() { Ok(return_stmt) => return Ok(Statement::Return(return_stmt)), Err(ParseProcessError::ErrorInMatch) => return Err(ParseProcessError::ErrorInMatch), Err(_) => {}, }; match self.parse_if_stmt() { Ok(if_stmt) => return Ok(Statement::If(if_stmt)), Err(ParseProcessError::ErrorInMatch) => return Err(ParseProcessError::ErrorInMatch), Err(_) => {}, } match self.parse_while_stmt() { Ok(while_stmt) => return Ok(Statement::While(while_stmt)), Err(ParseProcessError::ErrorInMatch) => return Err(ParseProcessError::ErrorInMatch), Err(_) => {}, } match self.parse_for_stmt() { Ok(for_stmt) => return Ok(Statement::For(for_stmt)), Err(ParseProcessError::ErrorInMatch) => return Err(ParseProcessError::ErrorInMatch), Err(_) => {}, } match self.parse_break_stmt() { Ok(break_stmt) => return Ok(Statement::Break(break_stmt)), Err(ParseProcessError::ErrorInMatch) => return Err(ParseProcessError::ErrorInMatch), Err(_) => {}, } match self.parse_continue_stmt() { Ok(continue_stmt) => return Ok(Statement::Continue(continue_stmt)), Err(ParseProcessError::ErrorInMatch) => return Err(ParseProcessError::ErrorInMatch), Err(_) => {}, } match self.parse_block_stmt(ParseType::TryParse) { Ok(block_stmt) => return Ok(Statement::Block(block_stmt)), Err(ParseProcessError::ErrorInMatch) => return Err(ParseProcessError::ErrorInMatch), Err(_) => {}, } match self.parse_expr() { Ok(expr) => { self.must_match_token(&TokenValue::Semicolon, "`;`")?; return Ok(Statement::Expr(expr)) }, Err(ParseProcessError::ErrorInMatch) => return Err(ParseProcessError::ErrorInMatch), Err(_) => {}, } self.until_next_token(&[TokenValue::Semicolon]); Err(ParseProcessError::ErrorInMatch) } fn parse_return_stmt(&mut self) -> Result { if self.peek().value != TokenValue::Return { return Err(ParseProcessError::TryNext); } let span = self.next().span; let value = if matches!(self.peek().value, TokenValue::Semicolon) { None } else { Some(self.parse_expr()?) }; self.must_match_token(&TokenValue::Semicolon, "`;`")?; Ok(ReturnStmt { value, span, }) } fn parse_if_stmt(&mut self) -> Result { if self.peek().value != TokenValue::If { return Err(ParseProcessError::TryNext); } self.advance(1); self.must_match_token(&TokenValue::LParen, "`(`")?; self.must_have_some("if condition expr")?; let condition = self.parse_expr()?; self.must_match_token(&TokenValue::RParen, "`)`")?; let then_branch; let mut ifelse_branch = vec![]; let mut else_branch = None; self.must_have_some("if statement body")?; if self.peek().value != TokenValue::LBrace { let stmt = self.parse_stmt()?; then_branch = BlockStmt { statements: vec![stmt] }; } else { then_branch = self.parse_block_stmt(ParseType::MustParse)?; } loop { if self.is_eof() { break; } if self.peek().value == TokenValue::Else { self.advance(1); self.must_have_some("else body")?; if self.peek().value != TokenValue::If { self.back(1); break; } // else if self.advance(1); self.must_match_token(&TokenValue::LParen, "`(`")?; self.must_have_some("else if condition expr")?; let condition = self.parse_expr()?; self.must_match_token(&TokenValue::RParen, "`)`")?; let then_branch; if self.peek().value != TokenValue::LBrace { let stmt = self.parse_stmt()?; then_branch = BlockStmt { statements: vec![stmt] }; } else { then_branch = self.parse_block_stmt(ParseType::MustParse)?; } ifelse_branch.push(IfElseBranch { condition, then_branch }); } else { // if end ? break; } } if self.peek().value == TokenValue::Else { // Parse else branch self.advance(1); self.must_have_some("else body")?; if self.peek().value != TokenValue::LBrace { let stmt = self.parse_stmt()?; else_branch = Some(BlockStmt { statements: vec![stmt] }); } else { else_branch = Some(self.parse_block_stmt(ParseType::MustParse)?); } } Ok(IfStmt { condition, then_branch, ifelse_branch, else_branch, }) } fn parse_while_stmt(&mut self) -> Result { if self.peek().value != TokenValue::While { return Err(ParseProcessError::TryNext); } self.advance(1); self.must_match_token(&TokenValue::LParen, "`(`")?; self.must_have_some("while condition expr")?; let condition = self.parse_expr()?; self.must_match_token(&TokenValue::RParen, "`)`")?; let body; if self.peek().value != TokenValue::LBrace { let stmt = self.parse_stmt()?; body = BlockStmt { statements: vec![stmt] }; } else { body = self.parse_block_stmt(ParseType::MustParse)?; } Ok(WhileStmt { condition, body, }) } fn parse_for_stmt(&mut self) -> Result { if self.peek().value != TokenValue::For { return Err(ParseProcessError::TryNext); } self.advance(1); self.must_match_token(&TokenValue::LParen, "`(`")?; let init = if self.peek().value == TokenValue::Semicolon { None } else if matches!(self.peek().value, TokenValue::Static | TokenValue::TypeIdent(_)) { Some(ForInit::VarDecl(self.parse_var_decl_stmt_inner(ParseType::MustParse, false)?)) } else { Some(ForInit::Expr(self.parse_expr()?)) }; self.must_match_token(&TokenValue::Semicolon, "`;`")?; let condition = if self.peek().value == TokenValue::Semicolon { None } else { Some(self.parse_expr()?) }; self.must_match_token(&TokenValue::Semicolon, "`;`")?; let update = if self.peek().value == TokenValue::RParen { None } else { Some(self.parse_expr()?) }; self.must_match_token(&TokenValue::RParen, "`)`")?; let body; if self.peek().value != TokenValue::LBrace { let stmt = self.parse_stmt()?; body = BlockStmt { statements: vec![stmt] }; } else { body = self.parse_block_stmt(ParseType::MustParse)?; } Ok(ForStmt { init, condition, update, body, }) } fn parse_break_stmt(&mut self) -> Result { let start_span = self.peek().span; if self.peek().value == TokenValue::Break { self.advance(1); self.must_match_token(&TokenValue::Semicolon, "`;`")?; Ok(BreakStmt { span: start_span, }) } else { Err(ParseProcessError::TryNext) } } fn parse_continue_stmt(&mut self) -> Result { let start_span = self.peek().span; if self.peek().value == TokenValue::Continue { self.advance(1); self.must_match_token(&TokenValue::Semicolon, "`;`")?; Ok(ContinueStmt { span: start_span, }) } else { Err(ParseProcessError::TryNext) } } }