added statement parsing

This commit is contained in:
Raptorox 2026-06-17 21:02:41 +02:00
parent a21b119e58
commit 9932c83d6f
No known key found for this signature in database
GPG key ID: 8B3556FC3ED1F6D8
4 changed files with 226 additions and 17 deletions

View file

@ -30,8 +30,9 @@ pub fn infix_bp(op: &BinaryOp) -> (u8, u8) {
#[derive(Debug, Clone)]
pub enum Expr {
Number(i64),
Bool(bool),
Ident(String),
EOL,
StringLit(String),
Binary {
op: BinaryOp,
@ -42,6 +43,8 @@ pub enum Expr {
Unary {
op: UnaryOp,
right: Box<Expr>
}
},
EOL
}

View file

@ -2,13 +2,14 @@ use std::{fs::File, io::Read};
mod token;
mod expr;
mod stmt;
mod lexer;
mod error;
use lexer::Lexer;
mod parser;
use parser::Parser;
mod eval;
use eval::Evaluator;
// mod eval;
// use eval::Evaluator;
fn main() -> std::io::Result<()> {
let args = std::env::args().collect::<Vec<String>>();
@ -30,17 +31,23 @@ fn main() -> std::io::Result<()> {
println!("\n");
let mut parser = Parser::new(tokens);
loop {
let parsed = parser.parse().unwrap_or(expr::Expr::EOL);
match parsed {
expr::Expr::EOL => break,
_ => {
println!("AST: {:?}", parsed);
let eval = Evaluator::new(parsed);
println!("Eval: {:?}", eval.eval());
}
}
let parsed = parser.parse();
match parsed {
Ok(parsed) => println!("AST: {:?}", parsed),
Err(e) => eprintln!("{e}")
}
// loop {
// let parsed = parser.parse().unwrap_or(Vec::new());
// match parsed {
// expr::Expr::EOL => break,
// _ => {
// println!("AST: {:?}", parsed);
// // let eval = Evaluator::new(parsed);
// // println!("Eval: {:?}", eval.eval());
// }
// }
// }
Ok(())
}

View file

@ -1,5 +1,6 @@
use crate::token::Token;
use crate::expr::{Expr, UnaryOp, BinaryOp, infix_bp, prefix_bp};
use crate::stmt::{CondOp, Condition, Stmt};
use crate::error::ParseError;
type ParseResult<T> = Result<T, ParseError>;
@ -40,9 +41,19 @@ impl Parser {
}
}
fn expect_ident(&mut self) -> ParseResult<String> {
match self.next() {
Some(Token::Ident(ident)) => Ok(ident),
other => Err(ParseError::new(format!(
"expected identifier, got {other:?}"
)))
}
}
fn parse_atom(&mut self) -> ParseResult<Expr> {
match self.next() {
Some(Token::Number(n)) => Ok(Expr::Number(n)),
Some(Token::StringLit(s)) => Ok(Expr::StringLit(s)),
Some(Token::Ident(id)) => Ok(Expr::Ident(id)),
Some(Token::LParen) => {
let expr = self.parse_expr(0)?;
@ -102,8 +113,164 @@ impl Parser {
Ok(lhs)
}
pub fn parse(&mut self) -> ParseResult<Expr> {
if self.peek().is_none() {return Ok(Expr::EOL)}
self.parse_expr(0)
fn parse_block(&mut self) -> ParseResult<Vec<Stmt>> {
self.expect(&Token::LBrace)?;
let mut stmts = Vec::new();
while !matches!(self.peek(), Some(Token::RBrace) | None) {
stmts.push(self.parse_stmt()?);
}
self.expect(&Token::RBrace)?;
Ok(stmts)
}
fn parse_condition(&mut self) -> ParseResult<Condition> {
let op = match self.next() {
Some(Token::Eq) => CondOp::Eq,
Some(Token::Neq) => CondOp::Neq,
Some(Token::Lt) => CondOp::Lt,
Some(Token::Gt) => CondOp::Gt,
Some(Token::Lte) => CondOp::Lte,
Some(Token::Gte) => CondOp::Gte,
tok => return Err(ParseError::new(format!(
"expected condition operator, got {tok:?}"
)))
};
let left = self.parse_expr(0)?;
self.expect(&Token::Comma)?;
let right = self.parse_expr(0)?;
Ok(Condition { op, left, right })
}
fn parse_mov(&mut self) -> ParseResult<Stmt> {
self.expect(&Token::Mov)?;
let src = self.parse_expr(0)?;
self.expect(&Token::Comma)?;
let dst = self.expect_ident()?;
self.expect(&Token::Semicolon)?;
Ok(Stmt::Mov { src, dst })
}
fn parse_ifelse(&mut self) -> ParseResult<Stmt> {
self.expect(&Token::If)?;
let condition = self.parse_condition()?;
let then = if matches!(self.peek(), Some(Token::LBrace)) {
self.parse_block()?
} else {
self.expect(&Token::Comma)?;
vec![self.parse_stmt()?]
};
let else_ = if matches!(self.peek(), Some(Token::Else)) {
self.advance();
Some(if matches!(self.peek(), Some(Token::LBrace)) {
self.parse_block()?
} else {
vec![self.parse_stmt()?]
})
} else {
None
};
Ok(Stmt::IfElse { condition, then, else_ })
}
fn parse_loop(&mut self) -> ParseResult<Stmt> {
self.expect(&Token::Loop)?;
let body = self.parse_block()?;
Ok(Stmt::Loop { body })
}
fn parse_while(&mut self) -> ParseResult<Stmt> {
self.expect(&Token::While)?;
let condition = self.parse_condition()?;
let body = self.parse_block()?;
Ok(Stmt::While { condition, body })
}
fn parse_for(&mut self) -> ParseResult<Stmt> {
self.expect(&Token::For)?;
let var = self.expect_ident()?;
match self.peek() {
Some(Token::In) => {
self.advance();
let list = self.parse_expr(0)?;
let body = self.parse_block()?;
Ok(Stmt::ForIn { var, list, body })
},
Some(Token::Comma) => {
self.advance();
let start = self.parse_expr(0)?;
self.expect(&Token::DotDot)?;
let end = self.parse_expr(0)?;
let step = if matches!(self.peek(), Some(Token::Comma)) {
self.advance();
Some(self.parse_expr(0)?)
} else {
None
};
let body = self.parse_block()?;
Ok(Stmt::ForRange { var, start, end, step, body })
},
tok => Err(ParseError::new(format!(
"expected 'in' or ',' after for variable, got {tok:?}"
)))
}
}
fn parse_call(&mut self) -> ParseResult<Stmt> {
self.expect(&Token::Call)?;
let name = self.expect_ident()?;
let mut args = Vec::new();
while matches!(self.peek(), Some(Token::Comma)) {
self.advance();
args.push(self.parse_expr(0)?);
}
self.expect(&Token::Semicolon)?;
Ok(Stmt::Call { name, args })
}
fn parse_func_def(&mut self) -> ParseResult<Stmt> {
self.expect(&Token::Fun)?;
let name = self.expect_ident()?;
let mut params = Vec::new();
while matches!(self.peek(), Some(Token::Comma)) {
self.advance();
params.push(self.expect_ident()?);
}
let body = self.parse_block()?;
Ok(Stmt::FuncDef { name, params, body })
}
fn parse_stmt(&mut self) -> ParseResult<Stmt> {
match self.peek() {
Some(Token::Mov) => self.parse_mov(),
Some(Token::If) => self.parse_ifelse(),
Some(Token::Loop) => self.parse_loop(),
Some(Token::While) => self.parse_while(),
Some(Token::For) => self.parse_for(),
Some(Token::Call) => self.parse_call(),
Some(Token::Fun) => self.parse_func_def(),
Some(Token::Break) => { self.advance(); self.expect(&Token::Semicolon)?; Ok(Stmt::Break) },
Some(Token::Continue) => { self.advance(); self.expect(&Token::Semicolon)?; Ok(Stmt::Continue) },
tok => Err(ParseError::new(format!(
"expected start of statement, got {tok:?}"
)))
}
}
pub fn parse(&mut self) -> ParseResult<Vec<Stmt>> {
let mut stmts = Vec::new();
while self.peek().is_some() {
match self.parse_stmt() {
Ok(stmt) => stmts.push(stmt),
Err(e) => return Err(e)
}
}
Ok(stmts)
}
}

32
src/stmt.rs Normal file
View file

@ -0,0 +1,32 @@
use crate::expr::Expr;
#[derive(Debug)]
pub enum CondOp {
Eq,
Neq,
Lt,
Gt,
Lte,
Gte
}
#[derive(Debug)]
pub struct Condition {
pub op: CondOp,
pub left: Expr,
pub right: Expr
}
#[derive(Debug)]
pub enum Stmt {
Mov { src: Expr, dst: String },
IfElse { condition: Condition, then: Vec<Stmt>, else_: Option<Vec<Stmt>> },
Loop { body: Vec<Stmt> },
While { condition: Condition, body: Vec<Stmt> },
ForRange { var: String, start: Expr, end: Expr, step: Option<Expr>, body: Vec<Stmt> },
ForIn { var: String, list: Expr, body: Vec<Stmt> },
Call { name: String, args: Vec<Expr> },
FuncDef { name: String, params: Vec<String>, body: Vec<Stmt> },
Break,
Continue
}