diff --git a/src/ast.rs b/src/ast.rs index ec6f86f..bc0c7f8 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -58,3 +58,14 @@ pub enum BinaryOp { Assign, Member, } + +#[derive(Debug, PartialEq, Eq)] +pub enum Statement { + Let { + name: Box, + name_span: Span, + value: Option, + }, + + Expr(Expression), +} diff --git a/src/main.rs b/src/main.rs index 8ff526e..243a3fb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ pub mod parser; pub mod token; fn main() { - let mut parser = Parser::new("user.age >= 18"); + let mut parser = Parser::new("let index = 12 + 3;"); - println!("{:#?}", parser.parse_expression(0)); + println!("{:#?}", parser.parse_statement()); } diff --git a/src/parser.rs b/src/parser.rs index 2c66e2a..6051c1a 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -36,10 +36,64 @@ impl<'src> Parser<'src> { self.peek().ok_or(ParserError::UnexpectedEof) } + fn is_peek(&mut self, kind: TokenKind) -> bool { + self.peek().is_some_and(|tok| tok.kind == kind) + } + fn consume(&mut self) -> Option> { self.tokens.next() } + fn expect(&mut self, kinds: &'static [TokenKind]) -> ParserResult> { + match self.consume() { + Some(tok) if kinds.contains(&tok.kind) => Ok(tok), + Some(tok) => Err(ParserError::UnexpectedToken { + expected: kinds, + found: tok.kind, + span: tok.span, + }), + None => Err(ParserError::UnexpectedEof), + } + } + + pub fn parse_statement(&mut self) -> ParserResult { + match self.peek_no_eof()?.kind { + TokenKind::KwLet => self.parse_let_statement(), + + _ => { + let expr = self.parse_expression(0)?; + self.expect(&[TokenKind::Semicolon])?; + Ok(Statement::Expr(expr)) + } + } + } + + fn parse_let_statement(&mut self) -> ParserResult { + self.expect(&[TokenKind::KwLet])?; + + let (name, name_span) = { + let token = self.expect(&[TokenKind::Identifier])?; + + (token.text.to_string().into_boxed_str(), token.span) + }; + + let value = if self.is_peek(TokenKind::Assign) { + self.consume(); + + Some(self.parse_expression(0)?) + } else { + None + }; + + self.expect(&[TokenKind::Semicolon])?; + + Ok(Statement::Let { + name, + name_span, + value, + }) + } + pub fn parse_expression(&mut self, min_binding_power: u8) -> ParserResult { let mut left = self.parse_leading_expression()?; @@ -71,6 +125,8 @@ impl<'src> Parser<'src> { span, }; } + + break; } Ok(left)