feat: Add support for expression and let statements.
This commit is contained in:
11
src/ast.rs
11
src/ast.rs
@@ -58,3 +58,14 @@ pub enum BinaryOp {
|
||||
Assign,
|
||||
Member,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Statement {
|
||||
Let {
|
||||
name: Box<str>,
|
||||
name_span: Span,
|
||||
value: Option<Expression>,
|
||||
},
|
||||
|
||||
Expr(Expression),
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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<Token<'src>> {
|
||||
self.tokens.next()
|
||||
}
|
||||
|
||||
fn expect(&mut self, kinds: &'static [TokenKind]) -> ParserResult<Token<'src>> {
|
||||
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<Statement> {
|
||||
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<Statement> {
|
||||
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<Expression> {
|
||||
let mut left = self.parse_leading_expression()?;
|
||||
|
||||
@@ -71,6 +125,8 @@ impl<'src> Parser<'src> {
|
||||
span,
|
||||
};
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Ok(left)
|
||||
|
||||
Reference in New Issue
Block a user