remove boxed errors

This commit is contained in:
2025-06-01 16:41:51 +02:00
parent 8a0fbac739
commit 35f0823432
4 changed files with 168 additions and 130 deletions

View File

@@ -1,4 +1,4 @@
use std::{collections::HashMap, error::Error, fmt::Write}; use std::{collections::HashMap, fmt::Write};
use crate::{ use crate::{
parser::{Expr, Stmt}, parser::{Expr, Stmt},
@@ -51,6 +51,12 @@ impl Env {
} }
} }
macro_rules! emit {
($($arg:tt)*) => {
let _ = writeln!($($arg)*);
};
}
pub struct CodegenX86_64 { pub struct CodegenX86_64 {
output: String, output: String,
data_section: String, data_section: String,
@@ -94,26 +100,26 @@ impl CodegenX86_64 {
) )
} }
pub fn emit_prologue(&mut self) -> Result<(), Box<dyn Error>> { pub fn emit_prologue(&mut self) -> Result<(), ZernError> {
writeln!( emit!(
&mut self.output, &mut self.output,
" "
section .text section .text
extern printf extern printf
extern puts extern puts
print equ puts print equ puts
" ",
)?; );
Ok(()) Ok(())
} }
pub fn emit_epilogue(&mut self) -> Result<(), Box<dyn Error>> { pub fn emit_epilogue(&mut self) -> Result<(), ZernError> {
writeln!(&mut self.output, "section .note.GNU-stack")?; emit!(&mut self.output, "section .note.GNU-stack");
writeln!(&mut self.output, " db 0")?; emit!(&mut self.output, " db 0");
Ok(()) Ok(())
} }
pub fn compile_stmt(&mut self, env: &mut Env, stmt: Stmt) -> Result<(), Box<dyn Error>> { pub fn compile_stmt(&mut self, env: &mut Env, stmt: Stmt) -> Result<(), ZernError> {
match stmt { match stmt {
Stmt::Expression(expr) => self.compile_expr(env, expr)?, Stmt::Expression(expr) => self.compile_expr(env, expr)?,
Stmt::Let { Stmt::Let {
@@ -126,7 +132,7 @@ print equ puts
self.compile_expr(env, initializer)?; self.compile_expr(env, initializer)?;
let offset = env.define_var(name.lexeme.clone(), var_type.lexeme); let offset = env.define_var(name.lexeme.clone(), var_type.lexeme);
writeln!(&mut self.output, " mov QWORD [rbp-{}], rax", offset)?; emit!(&mut self.output, " mov QWORD [rbp-{}], rax", offset);
} }
Stmt::Block(statements) => { Stmt::Block(statements) => {
env.push_scope(); env.push_scope();
@@ -144,25 +150,25 @@ print equ puts
let end_label = self.label(); let end_label = self.label();
self.compile_expr(env, condition)?; self.compile_expr(env, condition)?;
writeln!(&mut self.output, " test rax, rax")?; emit!(&mut self.output, " test rax, rax");
writeln!(&mut self.output, " je {}", else_label)?; emit!(&mut self.output, " je {}", else_label);
self.compile_stmt(env, *then_branch.clone())?; self.compile_stmt(env, *then_branch.clone())?;
writeln!(&mut self.output, " jmp {}", end_label)?; emit!(&mut self.output, " jmp {}", end_label);
writeln!(&mut self.output, "{}:", else_label)?; emit!(&mut self.output, "{}:", else_label);
self.compile_stmt(env, *else_branch.clone())?; self.compile_stmt(env, *else_branch.clone())?;
writeln!(&mut self.output, "{}:", end_label)?; emit!(&mut self.output, "{}:", end_label);
} }
Stmt::While { condition, body } => { Stmt::While { condition, body } => {
let begin_label = self.label(); let begin_label = self.label();
let end_label = self.label(); let end_label = self.label();
writeln!(&mut self.output, "{}:", begin_label)?; emit!(&mut self.output, "{}:", begin_label);
self.compile_expr(env, condition)?; self.compile_expr(env, condition)?;
writeln!(&mut self.output, " test rax, rax")?; emit!(&mut self.output, " test rax, rax");
writeln!(&mut self.output, " je {}", end_label)?; emit!(&mut self.output, " je {}", end_label);
self.compile_stmt(env, *body.clone())?; self.compile_stmt(env, *body.clone())?;
writeln!(&mut self.output, " jmp {}", begin_label)?; emit!(&mut self.output, " jmp {}", begin_label);
writeln!(&mut self.output, "{}:", end_label)?; emit!(&mut self.output, "{}:", end_label);
} }
Stmt::Function { Stmt::Function {
name, name,
@@ -172,115 +178,130 @@ print equ puts
} => { } => {
assert!(return_type.lexeme == "I64"); // TODO assert!(return_type.lexeme == "I64"); // TODO
writeln!(&mut self.output, "global {}", name.lexeme)?; emit!(&mut self.output, "global {}", name.lexeme);
writeln!(&mut self.output, "{}:", name.lexeme)?; emit!(&mut self.output, "{}:", name.lexeme);
writeln!(&mut self.output, " push rbp")?; emit!(&mut self.output, " push rbp");
writeln!(&mut self.output, " mov rbp, rsp")?; emit!(&mut self.output, " mov rbp, rsp");
writeln!(&mut self.output, " sub rsp, 256")?; // TODO emit!(&mut self.output, " sub rsp, 256"); // TODO
for (i, param) in params.iter().enumerate() { for (i, param) in params.iter().enumerate() {
let offset = env let offset = env
.define_var(param.var_name.lexeme.clone(), param.var_type.lexeme.clone()); .define_var(param.var_name.lexeme.clone(), param.var_type.lexeme.clone());
writeln!( emit!(
&mut self.output, &mut self.output,
" mov QWORD [rbp-{}], {}", " mov QWORD [rbp-{}], {}",
offset, offset,
CodegenX86_64::nth_register(i) CodegenX86_64::nth_register(i),
)?; );
} }
self.compile_stmt(env, *body)?; self.compile_stmt(env, *body)?;
writeln!(&mut self.output, " mov rax, 0")?; // TODO: remove default return value emit!(&mut self.output, " mov rax, 0"); // TODO: remove default return value
writeln!(&mut self.output, " mov rsp, rbp")?; emit!(&mut self.output, " mov rsp, rbp");
writeln!(&mut self.output, " pop rbp")?; emit!(&mut self.output, " pop rbp");
writeln!(&mut self.output, " ret")?; emit!(&mut self.output, " ret");
} }
Stmt::Return(expr) => { Stmt::Return(expr) => {
self.compile_expr(env, expr)?; self.compile_expr(env, expr)?;
writeln!(&mut self.output, " mov rsp, rbp")?; emit!(&mut self.output, " mov rsp, rbp");
writeln!(&mut self.output, " pop rbp")?; emit!(&mut self.output, " pop rbp");
writeln!(&mut self.output, " ret")?; emit!(&mut self.output, " ret");
} }
} }
Ok(()) Ok(())
} }
pub fn compile_expr(&mut self, env: &mut Env, expr: Expr) -> Result<(), Box<dyn Error>> { pub fn compile_expr(&mut self, env: &mut Env, expr: Expr) -> Result<(), ZernError> {
match expr { match expr {
Expr::Binary { left, op, right } => { Expr::Binary { left, op, right } => {
self.compile_expr(env, *left)?; self.compile_expr(env, *left)?;
writeln!(&mut self.output, " push rax")?; emit!(&mut self.output, " push rax");
self.compile_expr(env, *right)?; self.compile_expr(env, *right)?;
writeln!(&mut self.output, " mov rbx, rax")?; emit!(&mut self.output, " mov rbx, rax");
writeln!(&mut self.output, " pop rax")?; emit!(&mut self.output, " pop rax");
match op.token_type { match op.token_type {
TokenType::Plus => writeln!(&mut self.output, " add rax, rbx")?, TokenType::Plus => {
TokenType::Minus => writeln!(&mut self.output, " sub rax, rbx")?, emit!(&mut self.output, " add rax, rbx");
TokenType::Star => writeln!(&mut self.output, " imul rax, rbx")?, }
TokenType::Minus => {
emit!(&mut self.output, " sub rax, rbx");
}
TokenType::Star => {
emit!(&mut self.output, " imul rax, rbx");
}
TokenType::Slash => { TokenType::Slash => {
writeln!(&mut self.output, " cqo")?; emit!(&mut self.output, " cqo");
writeln!(&mut self.output, " idiv rbx")?; emit!(&mut self.output, " idiv rbx");
} }
TokenType::Mod => { TokenType::Mod => {
writeln!(&mut self.output, " cqo")?; emit!(&mut self.output, " cqo");
writeln!(&mut self.output, " idiv rbx")?; emit!(&mut self.output, " idiv rbx");
writeln!(&mut self.output, " mov rax, rdx")?; emit!(&mut self.output, " mov rax, rdx");
}
TokenType::Xor => {
emit!(&mut self.output, " xor rax, rbx");
}
TokenType::And => {
emit!(&mut self.output, " and rax, rbx");
}
TokenType::Or => {
emit!(&mut self.output, " or rax, rbx");
} }
TokenType::Xor => writeln!(&mut self.output, " xor rax, rbx")?,
TokenType::And => writeln!(&mut self.output, " and rax, rbx")?,
TokenType::Or => writeln!(&mut self.output, " or rax, rbx")?,
TokenType::DoubleEqual => { TokenType::DoubleEqual => {
writeln!(&mut self.output, " cmp rax, rbx")?; emit!(&mut self.output, " cmp rax, rbx");
writeln!(&mut self.output, " sete al")?; emit!(&mut self.output, " sete al");
writeln!(&mut self.output, " movzx rax, al")?; emit!(&mut self.output, " movzx rax, al");
} }
TokenType::NotEqual => { TokenType::NotEqual => {
writeln!(&mut self.output, " cmp rax, rbx")?; emit!(&mut self.output, " cmp rax, rbx");
writeln!(&mut self.output, " setne al")?; emit!(&mut self.output, " setne al");
writeln!(&mut self.output, " movzx rax, al")?; emit!(&mut self.output, " movzx rax, al");
} }
TokenType::Greater => { TokenType::Greater => {
writeln!(&mut self.output, " cmp rax, rbx")?; emit!(&mut self.output, " cmp rax, rbx");
writeln!(&mut self.output, " setg al")?; emit!(&mut self.output, " setg al");
writeln!(&mut self.output, " movzx rax, al")?; emit!(&mut self.output, " movzx rax, al");
} }
TokenType::GreaterEqual => { TokenType::GreaterEqual => {
writeln!(&mut self.output, " cmp rax, rbx")?; emit!(&mut self.output, " cmp rax, rbx");
writeln!(&mut self.output, " setge al")?; emit!(&mut self.output, " setge al");
writeln!(&mut self.output, " movzx rax, al")?; emit!(&mut self.output, " movzx rax, al");
} }
TokenType::Less => { TokenType::Less => {
writeln!(&mut self.output, " cmp rax, rbx")?; emit!(&mut self.output, " cmp rax, rbx");
writeln!(&mut self.output, " setl al")?; emit!(&mut self.output, " setl al");
writeln!(&mut self.output, " movzx rax, al")?; emit!(&mut self.output, " movzx rax, al");
} }
TokenType::LessEqual => { TokenType::LessEqual => {
writeln!(&mut self.output, " cmp rax, rbx")?; emit!(&mut self.output, " cmp rax, rbx");
writeln!(&mut self.output, " setle al")?; emit!(&mut self.output, " setle al");
writeln!(&mut self.output, " movzx rax, al")?; emit!(&mut self.output, " movzx rax, al");
} }
_ => unreachable!(), _ => unreachable!(),
} }
} }
Expr::Grouping(expr) => self.compile_expr(env, *expr)?, Expr::Grouping(expr) => self.compile_expr(env, *expr)?,
Expr::Literal(token) => match token.token_type { Expr::Literal(token) => match token.token_type {
TokenType::Number => writeln!(&mut self.output, " mov rax, {}", token.lexeme)?, TokenType::Number => {
emit!(&mut self.output, " mov rax, {}", token.lexeme);
}
TokenType::String => { TokenType::String => {
// TODO: actual string parsing in the tokenizer // TODO: actual string parsing in the tokenizer
let value = &token.lexeme[1..token.lexeme.len() - 1].replace("\\n", "\n"); let value = &token.lexeme[1..token.lexeme.len() - 1].replace("\\n", "\n");
let charcodes = value let charcodes = value
.chars() .chars()
.map(|x| format!("{}", x as u8)) .map(|x| (x as u8).to_string())
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join(","); .join(",");
writeln!( emit!(
&mut self.data_section, &mut self.data_section,
" S{} db {},0", " S{} db {},0",
self.data_counter, charcodes self.data_counter,
)?; charcodes,
writeln!(&mut self.output, " mov rax, S{}", self.data_counter)?; );
emit!(&mut self.output, " mov rax, S{}", self.data_counter);
self.data_counter += 1; self.data_counter += 1;
} }
_ => unreachable!(), _ => unreachable!(),
@@ -288,11 +309,13 @@ print equ puts
Expr::Unary { op, right } => { Expr::Unary { op, right } => {
self.compile_expr(env, *right)?; self.compile_expr(env, *right)?;
match op.token_type { match op.token_type {
TokenType::Minus => writeln!(&mut self.output, " neg rax")?, TokenType::Minus => {
emit!(&mut self.output, " neg rax");
}
TokenType::Bang => { TokenType::Bang => {
writeln!(&mut self.output, " test rax, rax")?; emit!(&mut self.output, " test rax, rax");
writeln!(&mut self.output, " sete al")?; emit!(&mut self.output, " sete al");
writeln!(&mut self.output, " movzx rax, al")?; emit!(&mut self.output, " movzx rax, al");
} }
_ => unreachable!(), _ => unreachable!(),
} }
@@ -304,11 +327,11 @@ print equ puts
return error!(name.loc, format!("undefined variable: {}", &name.lexeme)); return error!(name.loc, format!("undefined variable: {}", &name.lexeme));
} }
}; };
writeln!( emit!(
&mut self.output, &mut self.output,
" mov rax, QWORD [rbp-{}]", " mov rax, QWORD [rbp-{}]",
var.stack_offset var.stack_offset,
)? );
} }
Expr::Assign { name, value } => { Expr::Assign { name, value } => {
self.compile_expr(env, *value)?; self.compile_expr(env, *value)?;
@@ -319,11 +342,11 @@ print equ puts
return error!(name.loc, format!("undefined variable: {}", &name.lexeme)); return error!(name.loc, format!("undefined variable: {}", &name.lexeme));
} }
}; };
writeln!( emit!(
&mut self.output, &mut self.output,
" mov QWORD [rbp-{}], rax", " mov QWORD [rbp-{}], rax",
var.stack_offset var.stack_offset,
)?; );
} }
Expr::Call { Expr::Call {
callee, callee,
@@ -337,14 +360,14 @@ print equ puts
for (i, arg) in args.iter().enumerate() { for (i, arg) in args.iter().enumerate() {
self.compile_expr(env, arg.clone())?; self.compile_expr(env, arg.clone())?;
writeln!( emit!(
&mut self.output, &mut self.output,
" mov {}, rax", " mov {}, rax",
CodegenX86_64::nth_register(i) CodegenX86_64::nth_register(i),
)?; );
} }
writeln!(&mut self.output, " call {}", callee)?; emit!(&mut self.output, " call {}", callee);
} }
} }
Ok(()) Ok(())

View File

@@ -3,15 +3,21 @@ mod parser;
mod tokenizer; mod tokenizer;
use std::{ use std::{
env, env, fs,
error::Error,
fs,
path::Path, path::Path,
process::{self, Command}, process::{self, Command},
}; };
fn compile_file(path: String) -> Result<(), Box<dyn Error>> { use tokenizer::ZernError;
let source = fs::read_to_string(path.clone())?;
fn compile_file(path: String) -> Result<(), ZernError> {
let source = match fs::read_to_string(path.clone()) {
Ok(x) => x,
Err(_) => {
eprintln!("\x1b[91mERROR\x1b[0m: failed to open {}", path);
process::exit(1);
}
};
let filename = Path::new(&path).file_name().unwrap().to_str().unwrap(); let filename = Path::new(&path).file_name().unwrap().to_str().unwrap();
@@ -29,27 +35,38 @@ fn compile_file(path: String) -> Result<(), Box<dyn Error>> {
} }
codegen.emit_epilogue()?; codegen.emit_epilogue()?;
fs::write("out.s", codegen.get_output())?; // TODO: handle error
fs::write("out.s", codegen.get_output()).unwrap();
// TODO: stop on nasm/gcc error
Command::new("nasm") Command::new("nasm")
.args(["-f", "elf64", "-o", "out.o", "out.s"]) .args(["-f", "elf64", "-o", "out.o", "out.s"])
.status()?; .status()
.unwrap();
// TODO: drop libc entirely // TODO: drop libc entirely
Command::new("./musl-1.2.4/root/bin/musl-gcc") Command::new("./musl-1.2.4/root/bin/musl-gcc")
.args(["-static", "-o", "out", "out.o"]) .args(["-static", "-o", "out", "out.o"])
.status()?; .status()
.unwrap();
Ok(()) Ok(())
} }
fn main() -> Result<(), Box<dyn Error>> { fn main() {
let mut args = env::args(); let mut args = env::args();
let path = args.nth(1).unwrap(); let _ = args.next();
let path = match args.next() {
Some(x) => x,
None => {
eprintln!("\x1b[91mERROR\x1b[0m: expected an argument");
process::exit(1);
}
};
if let Err(err) = compile_file(path) { if let Err(err) = compile_file(path) {
eprintln!("{}", err); eprintln!("{}", err);
process::exit(1); process::exit(1);
} }
Ok(())
} }

View File

@@ -1,5 +1,3 @@
use std::error::Error;
use crate::tokenizer::{Token, TokenType, ZernError, error}; use crate::tokenizer::{Token, TokenType, ZernError, error};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@@ -75,7 +73,7 @@ impl Parser {
} }
} }
pub fn parse(mut self) -> Result<Vec<Stmt>, Box<dyn Error>> { pub fn parse(mut self) -> Result<Vec<Stmt>, ZernError> {
let mut statements = vec![]; let mut statements = vec![];
while !self.eof() { while !self.eof() {
statements.push(self.declaration()?); statements.push(self.declaration()?);
@@ -83,7 +81,7 @@ impl Parser {
Ok(statements) Ok(statements)
} }
fn declaration(&mut self) -> Result<Stmt, Box<dyn Error>> { fn declaration(&mut self) -> Result<Stmt, ZernError> {
if !self.is_inside_function { if !self.is_inside_function {
if self.match_token(&[TokenType::KeywordFunc]) { if self.match_token(&[TokenType::KeywordFunc]) {
return self.func_declaration(); return self.func_declaration();
@@ -103,7 +101,7 @@ impl Parser {
} }
// TOOD: parse return type // TOOD: parse return type
fn func_declaration(&mut self) -> Result<Stmt, Box<dyn Error>> { fn func_declaration(&mut self) -> Result<Stmt, ZernError> {
let name = self.consume(TokenType::Identifier, "expected function name")?; let name = self.consume(TokenType::Identifier, "expected function name")?;
self.consume(TokenType::LeftBracket, "expected '[' after function name")?; self.consume(TokenType::LeftBracket, "expected '[' after function name")?;
@@ -136,7 +134,7 @@ impl Parser {
}) })
} }
fn let_declaration(&mut self) -> Result<Stmt, Box<dyn Error>> { fn let_declaration(&mut self) -> Result<Stmt, ZernError> {
let name = self.consume(TokenType::Identifier, "expected variable name")?; let name = self.consume(TokenType::Identifier, "expected variable name")?;
self.consume(TokenType::Colon, "expected ':' after variable name")?; self.consume(TokenType::Colon, "expected ':' after variable name")?;
let var_type = self.consume(TokenType::Identifier, "expected variable type")?; let var_type = self.consume(TokenType::Identifier, "expected variable type")?;
@@ -149,7 +147,7 @@ impl Parser {
}) })
} }
fn block(&mut self) -> Result<Stmt, Box<dyn Error>> { fn block(&mut self) -> Result<Stmt, ZernError> {
self.consume(TokenType::Indent, "expected an indent")?; self.consume(TokenType::Indent, "expected an indent")?;
let mut statements = vec![]; let mut statements = vec![];
@@ -160,7 +158,7 @@ impl Parser {
Ok(Stmt::Block(statements)) Ok(Stmt::Block(statements))
} }
fn statement(&mut self) -> Result<Stmt, Box<dyn Error>> { fn statement(&mut self) -> Result<Stmt, ZernError> {
if self.match_token(&[TokenType::KeywordIf]) { if self.match_token(&[TokenType::KeywordIf]) {
self.if_statement() self.if_statement()
} else if self.match_token(&[TokenType::KeywordWhile]) { } else if self.match_token(&[TokenType::KeywordWhile]) {
@@ -172,11 +170,11 @@ impl Parser {
} }
} }
fn return_statement(&mut self) -> Result<Stmt, Box<dyn Error>> { fn return_statement(&mut self) -> Result<Stmt, ZernError> {
Ok(Stmt::Return(self.expression()?)) Ok(Stmt::Return(self.expression()?))
} }
fn if_statement(&mut self) -> Result<Stmt, Box<dyn Error>> { fn if_statement(&mut self) -> Result<Stmt, ZernError> {
let condition = self.expression()?; let condition = self.expression()?;
let then_branch = self.block()?; let then_branch = self.block()?;
let else_branch = if self.match_token(&[TokenType::KeywordElse]) { let else_branch = if self.match_token(&[TokenType::KeywordElse]) {
@@ -195,7 +193,7 @@ impl Parser {
}) })
} }
fn while_statement(&mut self) -> Result<Stmt, Box<dyn Error>> { fn while_statement(&mut self) -> Result<Stmt, ZernError> {
let condition = self.expression()?; let condition = self.expression()?;
let body = self.block()?; let body = self.block()?;
Ok(Stmt::While { Ok(Stmt::While {
@@ -204,11 +202,11 @@ impl Parser {
}) })
} }
fn expression(&mut self) -> Result<Expr, Box<dyn Error>> { fn expression(&mut self) -> Result<Expr, ZernError> {
self.assignment() self.assignment()
} }
fn assignment(&mut self) -> Result<Expr, Box<dyn Error>> { fn assignment(&mut self) -> Result<Expr, ZernError> {
let expr = self.pipe()?; let expr = self.pipe()?;
if self.match_token(&[TokenType::Equal]) { if self.match_token(&[TokenType::Equal]) {
@@ -227,7 +225,7 @@ impl Parser {
Ok(expr) Ok(expr)
} }
fn pipe(&mut self) -> Result<Expr, Box<dyn Error>> { fn pipe(&mut self) -> Result<Expr, ZernError> {
let mut expr = self.logical_or()?; let mut expr = self.logical_or()?;
while self.match_token(&[TokenType::Pipe]) { while self.match_token(&[TokenType::Pipe]) {
@@ -257,7 +255,7 @@ impl Parser {
Ok(expr) Ok(expr)
} }
fn logical_or(&mut self) -> Result<Expr, Box<dyn Error>> { fn logical_or(&mut self) -> Result<Expr, ZernError> {
let mut expr = self.logical_and()?; let mut expr = self.logical_and()?;
while self.match_token(&[TokenType::Or]) { while self.match_token(&[TokenType::Or]) {
@@ -273,7 +271,7 @@ impl Parser {
Ok(expr) Ok(expr)
} }
fn logical_and(&mut self) -> Result<Expr, Box<dyn Error>> { fn logical_and(&mut self) -> Result<Expr, ZernError> {
let mut expr = self.equality()?; let mut expr = self.equality()?;
while self.match_token(&[TokenType::And]) { while self.match_token(&[TokenType::And]) {
@@ -289,7 +287,7 @@ impl Parser {
Ok(expr) Ok(expr)
} }
fn equality(&mut self) -> Result<Expr, Box<dyn Error>> { fn equality(&mut self) -> Result<Expr, ZernError> {
let mut expr = self.comparison()?; let mut expr = self.comparison()?;
while self.match_token(&[TokenType::DoubleEqual, TokenType::NotEqual]) { while self.match_token(&[TokenType::DoubleEqual, TokenType::NotEqual]) {
@@ -305,7 +303,7 @@ impl Parser {
Ok(expr) Ok(expr)
} }
fn comparison(&mut self) -> Result<Expr, Box<dyn Error>> { fn comparison(&mut self) -> Result<Expr, ZernError> {
let mut expr = self.term()?; let mut expr = self.term()?;
while self.match_token(&[ while self.match_token(&[
@@ -326,7 +324,7 @@ impl Parser {
Ok(expr) Ok(expr)
} }
fn term(&mut self) -> Result<Expr, Box<dyn Error>> { fn term(&mut self) -> Result<Expr, ZernError> {
let mut expr = self.factor()?; let mut expr = self.factor()?;
while self.match_token(&[TokenType::Plus, TokenType::Minus, TokenType::Xor]) { while self.match_token(&[TokenType::Plus, TokenType::Minus, TokenType::Xor]) {
@@ -342,7 +340,7 @@ impl Parser {
Ok(expr) Ok(expr)
} }
fn factor(&mut self) -> Result<Expr, Box<dyn Error>> { fn factor(&mut self) -> Result<Expr, ZernError> {
let mut expr = self.unary()?; let mut expr = self.unary()?;
while self.match_token(&[TokenType::Star, TokenType::Slash, TokenType::Mod]) { while self.match_token(&[TokenType::Star, TokenType::Slash, TokenType::Mod]) {
@@ -358,7 +356,7 @@ impl Parser {
Ok(expr) Ok(expr)
} }
fn unary(&mut self) -> Result<Expr, Box<dyn Error>> { fn unary(&mut self) -> Result<Expr, ZernError> {
if self.match_token(&[TokenType::Bang, TokenType::Minus]) { if self.match_token(&[TokenType::Bang, TokenType::Minus]) {
let op = self.previous().clone(); let op = self.previous().clone();
let right = self.unary()?; let right = self.unary()?;
@@ -371,7 +369,7 @@ impl Parser {
self.call() self.call()
} }
fn call(&mut self) -> Result<Expr, Box<dyn Error>> { fn call(&mut self) -> Result<Expr, ZernError> {
let mut expr = self.primary()?; let mut expr = self.primary()?;
while self.match_token(&[TokenType::LeftParen]) { while self.match_token(&[TokenType::LeftParen]) {
@@ -397,7 +395,7 @@ impl Parser {
Ok(expr) Ok(expr)
} }
fn primary(&mut self) -> Result<Expr, Box<dyn Error>> { fn primary(&mut self) -> Result<Expr, ZernError> {
if self.match_token(&[TokenType::Number, TokenType::String]) { if self.match_token(&[TokenType::Number, TokenType::String]) {
Ok(Expr::Literal(self.previous().clone())) Ok(Expr::Literal(self.previous().clone()))
} else if self.match_token(&[TokenType::LeftParen]) { } else if self.match_token(&[TokenType::LeftParen]) {
@@ -411,7 +409,7 @@ impl Parser {
} }
} }
fn consume(&mut self, token_type: TokenType, message: &str) -> Result<Token, Box<dyn Error>> { fn consume(&mut self, token_type: TokenType, message: &str) -> Result<Token, ZernError> {
if self.check(&token_type) { if self.check(&token_type) {
Ok(self.advance().clone()) Ok(self.advance().clone())
} else { } else {

View File

@@ -1,4 +1,4 @@
use std::{cmp::Ordering, error::Error, fmt}; use std::{cmp::Ordering, fmt};
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum TokenType { pub enum TokenType {
@@ -59,10 +59,10 @@ impl std::error::Error for ZernError {}
macro_rules! error { macro_rules! error {
($loc:expr, $msg:expr) => { ($loc:expr, $msg:expr) => {
Err(Box::new(ZernError { Err(ZernError {
loc: $loc.clone(), loc: $loc.clone(),
message: $msg.into(), message: $msg.into(),
})) })
}; };
} }
@@ -115,7 +115,7 @@ impl Tokenizer {
} }
} }
pub fn tokenize(mut self) -> Result<Vec<Token>, Box<dyn Error>> { pub fn tokenize(mut self) -> Result<Vec<Token>, ZernError> {
while !self.eof() { while !self.eof() {
self.start = self.current; self.start = self.current;
self.scan_token()?; self.scan_token()?;
@@ -129,7 +129,7 @@ impl Tokenizer {
Ok(self.tokens) Ok(self.tokens)
} }
fn scan_token(&mut self) -> Result<(), Box<dyn Error>> { fn scan_token(&mut self) -> Result<(), ZernError> {
match self.advance() { match self.advance() {
'(' => self.add_token(TokenType::LeftParen), '(' => self.add_token(TokenType::LeftParen),
')' => self.add_token(TokenType::RightParen), ')' => self.add_token(TokenType::RightParen),
@@ -224,7 +224,7 @@ impl Tokenizer {
Ok(()) Ok(())
} }
fn handle_indentation(&mut self) -> Result<(), Box<dyn Error>> { fn handle_indentation(&mut self) -> Result<(), ZernError> {
if self.peek() == '\n' { if self.peek() == '\n' {
return Ok(()); return Ok(());
} }