commit - ebe3a0a72c98c733977195ad2a30c57189ce8701
commit + a40058a5b5365b5e05a32eb8ba8ef34d2d3b51ab
blob - 8aaab798979dedf14befb4da4574d361936120d1
blob + 0e3ae3e1108786e6afd353e596e2f0870e775006
--- src/main.rs
+++ src/main.rs
};
let mut parser = parser::Parser::new(tokens);
- match parser.parse_expression() {
- Ok(expr) => println!("{:#?}", expr),
+ match parser.parse_program() {
+ Ok(program) => println!("{:#?}", program),
Err(e) => {
eprintln!("{e}");
process::exit(1);
blob - 1445329a8518ba61dfc298e9e4c639e637afe502
blob + a88808288eaec57a056546e818e1e2810e707b67
--- src/parser/ast.rs
+++ src/parser/ast.rs
use crate::span::Span;
#[derive(Debug, Clone)]
+pub enum Type {
+ Int,
+ Float,
+ Str,
+ Bool,
+}
+
+#[derive(Debug, Clone)]
+pub struct Param {
+ pub name: String,
+ pub ty: Type,
+ pub span: Span,
+}
+
+#[derive(Debug, Clone)]
+pub struct FnDecl {
+ pub name: String,
+ pub params: Vec<Param>,
+ pub return_ty: Option<Type>,
+ pub body: Block,
+ pub span: Span,
+}
+
+#[derive(Debug, Clone)]
+pub struct Program {
+ pub functions: Vec<FnDecl>,
+}
+
+pub type Block = Vec<Stmt>;
+
+#[derive(Debug, Clone)]
+pub enum Stmt {
+ Let {
+ name: String,
+ mutable: bool,
+ ty: Option<Type>,
+ value: Expr,
+ span: Span,
+ },
+ Assign {
+ name: String,
+ value: Expr,
+ span: Span,
+ },
+ If {
+ condition: Expr,
+ then_block: Block,
+ else_block: Option<Block>,
+ span: Span,
+ },
+ For {
+ var: String,
+ iter: Expr,
+ body: Block,
+ span: Span,
+ },
+ While {
+ condition: Expr,
+ body: Block,
+ span: Span,
+ },
+ Return {
+ value: Option<Expr>,
+ span: Span,
+ },
+ Print {
+ args: Vec<Expr>,
+ span: Span,
+ },
+ ExprStmt {
+ expr: Expr,
+ span: Span,
+ },
+}
+
+#[derive(Debug, Clone)]
pub enum BinOp {
Add,
Sub,
blob - fefc755e3dac17e7b89ce7583e1752d34287c4b7
blob + 4d736731fc3365f00b0fa9ef325be1462bb09896
--- src/parser/mod.rs
+++ src/parser/mod.rs
use crate::error::OlangError;
use crate::lexer::token::{Token, TokenKind};
use crate::span::Span;
-use ast::{BinOp, Expr, UnaryOp};
+use ast::{
+ BinOp, Block, Expr, FnDecl, Param, Program, Stmt,
+ Type, UnaryOp,
+};
pub struct Parser {
tokens: Vec<Token>,
}
}
+ fn expect_ident(
+ &mut self,
+ ) -> Result<(String, Span), OlangError> {
+ let token = self.advance().clone();
+ if let TokenKind::Ident(name) = token.kind {
+ Ok((name, token.span))
+ } else {
+ Err(OlangError::new(
+ format!(
+ "expected identifier, found {:?}",
+ token.kind
+ ),
+ token.span,
+ ))
+ }
+ }
+
+ // --- Program ---
+
+ pub fn parse_program(
+ &mut self,
+ ) -> Result<Program, OlangError> {
+ let mut functions = Vec::new();
+
+ while *self.peek() != TokenKind::Eof {
+ functions.push(self.parse_fn_decl()?);
+ }
+
+ Ok(Program { functions })
+ }
+
+ fn parse_fn_decl(
+ &mut self,
+ ) -> Result<FnDecl, OlangError> {
+ let start = self.expect(&TokenKind::Fn)?;
+ let (name, _) = self.expect_ident()?;
+
+ self.expect(&TokenKind::LParen)?;
+ let params = self.parse_params()?;
+ self.expect(&TokenKind::RParen)?;
+
+ let return_ty = if *self.peek() == TokenKind::Arrow
+ {
+ self.advance();
+ Some(self.parse_type()?)
+ } else {
+ None
+ };
+
+ let body = self.parse_block()?;
+ let end = self.tokens[self.pos - 1].span;
+
+ Ok(FnDecl {
+ name,
+ params,
+ return_ty,
+ body,
+ span: Span::new(start.start, end.end),
+ })
+ }
+
+ fn parse_params(
+ &mut self,
+ ) -> Result<Vec<Param>, OlangError> {
+ let mut params = Vec::new();
+
+ if *self.peek() == TokenKind::RParen {
+ return Ok(params);
+ }
+
+ params.push(self.parse_param()?);
+ while *self.peek() == TokenKind::Comma {
+ self.advance();
+ params.push(self.parse_param()?);
+ }
+
+ Ok(params)
+ }
+
+ fn parse_param(
+ &mut self,
+ ) -> Result<Param, OlangError> {
+ let (name, start) = self.expect_ident()?;
+ self.expect(&TokenKind::Colon)?;
+ let ty = self.parse_type()?;
+ let end = self.tokens[self.pos - 1].span;
+
+ Ok(Param {
+ name,
+ ty,
+ span: Span::new(start.start, end.end),
+ })
+ }
+
+ fn parse_type(
+ &mut self,
+ ) -> Result<Type, OlangError> {
+ let token = self.advance().clone();
+ match token.kind {
+ TokenKind::IntType => Ok(Type::Int),
+ TokenKind::FloatType => Ok(Type::Float),
+ TokenKind::StrType => Ok(Type::Str),
+ TokenKind::BoolType => Ok(Type::Bool),
+ _ => Err(OlangError::new(
+ format!(
+ "expected type, found {:?}",
+ token.kind
+ ),
+ token.span,
+ )),
+ }
+ }
+
+ // --- Block ---
+
+ fn parse_block(
+ &mut self,
+ ) -> Result<Block, OlangError> {
+ self.expect(&TokenKind::LBrace)?;
+ let mut stmts = Vec::new();
+
+ while *self.peek() != TokenKind::RBrace {
+ stmts.push(self.parse_statement()?);
+ }
+
+ self.expect(&TokenKind::RBrace)?;
+ Ok(stmts)
+ }
+
+ // --- Statements ---
+
+ fn parse_statement(
+ &mut self,
+ ) -> Result<Stmt, OlangError> {
+ match self.peek() {
+ TokenKind::Let => self.parse_let(),
+ TokenKind::If => self.parse_if(),
+ TokenKind::For => self.parse_for(),
+ TokenKind::While => self.parse_while(),
+ TokenKind::Return => self.parse_return(),
+ TokenKind::Print => self.parse_print(),
+ _ => self.parse_assign_or_expr(),
+ }
+ }
+
+ fn parse_let(
+ &mut self,
+ ) -> Result<Stmt, OlangError> {
+ let start = self.expect(&TokenKind::Let)?;
+
+ let mutable =
+ if *self.peek() == TokenKind::Mut {
+ self.advance();
+ true
+ } else {
+ false
+ };
+
+ let (name, _) = self.expect_ident()?;
+
+ let ty = if *self.peek() == TokenKind::Colon {
+ self.advance();
+ Some(self.parse_type()?)
+ } else {
+ None
+ };
+
+ self.expect(&TokenKind::Eq)?;
+ let value = self.parse_expression()?;
+ let end = self.expect(&TokenKind::Semicolon)?;
+
+ Ok(Stmt::Let {
+ name,
+ mutable,
+ ty,
+ value,
+ span: Span::new(start.start, end.end),
+ })
+ }
+
+ fn parse_if(
+ &mut self,
+ ) -> Result<Stmt, OlangError> {
+ let start = self.expect(&TokenKind::If)?;
+ let condition = self.parse_expression()?;
+ let then_block = self.parse_block()?;
+
+ let else_block =
+ if *self.peek() == TokenKind::Else {
+ self.advance();
+ if *self.peek() == TokenKind::If {
+ // else if -> wrap in a block with
+ // one If statement
+ let if_stmt = self.parse_if()?;
+ Some(vec![if_stmt])
+ } else {
+ Some(self.parse_block()?)
+ }
+ } else {
+ None
+ };
+
+ let end = self.tokens[self.pos - 1].span;
+
+ Ok(Stmt::If {
+ condition,
+ then_block,
+ else_block,
+ span: Span::new(start.start, end.end),
+ })
+ }
+
+ fn parse_for(
+ &mut self,
+ ) -> Result<Stmt, OlangError> {
+ let start = self.expect(&TokenKind::For)?;
+ let (var, _) = self.expect_ident()?;
+ self.expect(&TokenKind::In)?;
+
+ // Parse range(expr)
+ let range_start = self.peek_span();
+ self.expect(&TokenKind::Range)?;
+ self.expect(&TokenKind::LParen)?;
+ let limit = self.parse_expression()?;
+ let range_end =
+ self.expect(&TokenKind::RParen)?;
+
+ let iter = Expr::Call {
+ name: "range".to_string(),
+ args: vec![limit],
+ span: Span::new(
+ range_start.start,
+ range_end.end,
+ ),
+ };
+
+ let body = self.parse_block()?;
+ let end = self.tokens[self.pos - 1].span;
+
+ Ok(Stmt::For {
+ var,
+ iter,
+ body,
+ span: Span::new(start.start, end.end),
+ })
+ }
+
+ fn parse_while(
+ &mut self,
+ ) -> Result<Stmt, OlangError> {
+ let start = self.expect(&TokenKind::While)?;
+ let condition = self.parse_expression()?;
+ let body = self.parse_block()?;
+ let end = self.tokens[self.pos - 1].span;
+
+ Ok(Stmt::While {
+ condition,
+ body,
+ span: Span::new(start.start, end.end),
+ })
+ }
+
+ fn parse_return(
+ &mut self,
+ ) -> Result<Stmt, OlangError> {
+ let start = self.expect(&TokenKind::Return)?;
+
+ let value =
+ if *self.peek() == TokenKind::Semicolon {
+ None
+ } else {
+ Some(self.parse_expression()?)
+ };
+
+ let end = self.expect(&TokenKind::Semicolon)?;
+
+ Ok(Stmt::Return {
+ value,
+ span: Span::new(start.start, end.end),
+ })
+ }
+
+ fn parse_print(
+ &mut self,
+ ) -> Result<Stmt, OlangError> {
+ let start = self.expect(&TokenKind::Print)?;
+ self.expect(&TokenKind::LParen)?;
+
+ let mut args = Vec::new();
+ if *self.peek() != TokenKind::RParen {
+ args.push(self.parse_expression()?);
+ while *self.peek() == TokenKind::Comma {
+ self.advance();
+ args.push(self.parse_expression()?);
+ }
+ }
+
+ self.expect(&TokenKind::RParen)?;
+ let end = self.expect(&TokenKind::Semicolon)?;
+
+ Ok(Stmt::Print {
+ args,
+ span: Span::new(start.start, end.end),
+ })
+ }
+
+ fn parse_assign_or_expr(
+ &mut self,
+ ) -> Result<Stmt, OlangError> {
+ let expr = self.parse_expression()?;
+
+ // Check if it's an assignment: ident = expr;
+ if let Expr::Ident(ref name, _) = expr {
+ if *self.peek() == TokenKind::Eq {
+ let name = name.clone();
+ let start = self.span_of(&expr);
+ self.advance();
+ let value = self.parse_expression()?;
+ let end =
+ self.expect(&TokenKind::Semicolon)?;
+ return Ok(Stmt::Assign {
+ name,
+ value,
+ span: Span::new(
+ start.start,
+ end.end,
+ ),
+ });
+ }
+ }
+
+ let span = self.span_of(&expr);
+
+ // Expression statement with ;
+ if *self.peek() == TokenKind::Semicolon {
+ let end =
+ self.expect(&TokenKind::Semicolon)?;
+ return Ok(Stmt::ExprStmt {
+ expr,
+ span: Span::new(span.start, end.end),
+ });
+ }
+
+ // Expression without ; (implicit return)
+ Ok(Stmt::ExprStmt { expr, span })
+ }
+
+ // --- Expressions ---
+
pub fn parse_expression(
&mut self,
) -> Result<Expr, OlangError> {
&mut self,
) -> Result<Expr, OlangError> {
let mut left = self.parse_comparison()?;
+
loop {
let op = match self.peek() {
TokenKind::EqEq => BinOp::Eq,
span,
};
}
+
Ok(left)
}
&mut self,
) -> Result<Expr, OlangError> {
let mut left = self.parse_addition()?;
+
loop {
let op = match self.peek() {
TokenKind::Less => BinOp::Less,
TokenKind::LessEq => BinOp::LessEq,
TokenKind::Greater => BinOp::Greater,
- TokenKind::GreaterEq => {
- BinOp::GreaterEq
- }
+ TokenKind::GreaterEq => BinOp::GreaterEq,
_ => break,
};
self.advance();
span,
};
}
+
Ok(left)
}
&mut self,
) -> Result<Expr, OlangError> {
let mut left = self.parse_multiply()?;
+
loop {
let op = match self.peek() {
TokenKind::Plus => BinOp::Add,
span,
};
}
+
Ok(left)
}
&mut self,
) -> Result<Expr, OlangError> {
let mut left = self.parse_unary()?;
+
loop {
let op = match self.peek() {
TokenKind::Star => BinOp::Mul,
span,
};
}
+
Ok(left)
}
&mut self,
) -> Result<Expr, OlangError> {
let start = self.peek_span();
+
if *self.peek() == TokenKind::Minus {
self.advance();
let expr = self.parse_unary()?;
span,
});
}
+
self.parse_call()
}
&mut self,
) -> Result<Expr, OlangError> {
let expr = self.parse_primary()?;
+
if let Expr::Ident(ref name, _) = expr {
if *self.peek() == TokenKind::LParen {
let name = name.clone();
let start = self.span_of(&expr);
self.advance();
let mut args = Vec::new();
+
if *self.peek() != TokenKind::RParen {
- args.push(
- self.parse_expression()?,
- );
- while *self.peek()
- == TokenKind::Comma
+ args.push(self.parse_expression()?);
+ while *self.peek() == TokenKind::Comma
{
self.advance();
args.push(
);
}
}
+
let end =
self.expect(&TokenKind::RParen)?;
let span =
});
}
}
+
Ok(expr)
}
&mut self,
) -> Result<Expr, OlangError> {
let token = self.advance().clone();
+
match token.kind {
TokenKind::IntLit(v) => {
Ok(Expr::IntLit(v, token.span))