added ParseResult

This commit is contained in:
Raptorox 2026-06-16 23:37:18 +02:00
parent a887bf4b3e
commit 8aeb6e543e
No known key found for this signature in database
GPG key ID: 8B3556FC3ED1F6D8
3 changed files with 56 additions and 22 deletions

20
src/error.rs Normal file
View file

@ -0,0 +1,20 @@
use std::{error::Error, fmt::Display};
#[derive(Debug)]
pub struct ParseError {
message: String
}
impl ParseError {
pub fn new(message: impl Into<String>) -> Self {
Self { message: message.into() }
}
}
impl Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "parse error: {}", self.message)
}
}
impl Error for ParseError {}

View file

@ -3,6 +3,7 @@ use std::{fs::File, io::Read};
mod token; mod token;
mod expr; mod expr;
mod lexer; mod lexer;
mod error;
use lexer::Lexer; use lexer::Lexer;
mod parser; mod parser;
use parser::Parser; use parser::Parser;
@ -29,7 +30,7 @@ fn main() -> std::io::Result<()> {
let mut parser = Parser::new(tokens); let mut parser = Parser::new(tokens);
loop { loop {
let parsed = parser.parse(); let parsed = parser.parse().unwrap_or(expr::Expr::EOL);
match parsed { match parsed {
expr::Expr::EOL => break, expr::Expr::EOL => break,
_ => { _ => {

View file

@ -1,5 +1,8 @@
use crate::token::Token; use crate::token::Token;
use crate::expr::{Expr, UnaryOp, BinaryOp, infix_bp, prefix_bp}; use crate::expr::{Expr, UnaryOp, BinaryOp, infix_bp, prefix_bp};
use crate::error::ParseError;
type ParseResult<T> = Result<T, ParseError>;
pub struct Parser { pub struct Parser {
tokens: Vec<Token>, tokens: Vec<Token>,
@ -28,39 +31,49 @@ impl Parser {
tok tok
} }
fn parse_atom(&mut self) -> Expr { fn expect(&mut self, expected: &Token) -> ParseResult<Token> {
match self.next() { match self.next() {
Some(Token::Number(n)) => Expr::Number(n), Some(tok) if &tok == expected => Ok(tok),
Some(Token::Ident(id)) => Expr::Ident(id), other => Err(ParseError::new(format!(
Some(Token::LParen) => { "expected {expected:?}, got {other:?}"
let expr = self.parse_expr(0); )))
match self.next() {
Some(Token::RParen) => expr,
_ => panic!("expected ')'")
}
},
tok => panic!("unknown token: {tok:?}")
} }
} }
fn parse_prefix(&mut self) -> Expr { fn parse_atom(&mut self) -> ParseResult<Expr> {
match self.next() {
Some(Token::Number(n)) => Ok(Expr::Number(n)),
Some(Token::Ident(id)) => Ok(Expr::Ident(id)),
Some(Token::LParen) => {
let expr = self.parse_expr(0)?;
self.expect(&Token::RParen)?;
Ok(expr)
},
tok => Err(ParseError::new(format!(
"unexpected token: {tok:?}"
)))
}
}
fn parse_prefix(&mut self) -> ParseResult<Expr> {
match self.peek() { match self.peek() {
Some(Token::Minus) => { Some(Token::Minus) => {
self.advance(); self.advance();
let op = UnaryOp::Neg; let op = UnaryOp::Neg;
let bp = prefix_bp(&op); let bp = prefix_bp(&op);
let rhs = self.parse_expr(bp); let rhs = self.parse_expr(bp)?;
Expr::Unary { op, right: Box::new(rhs) } Ok(Expr::Unary { op, right: Box::new(rhs) })
}, },
_ => self.parse_atom() _ => self.parse_atom()
} }
} }
fn parse_expr(&mut self, min_bp: u8) -> Expr { fn parse_expr(&mut self, min_bp: u8) -> ParseResult<Expr> {
let mut lhs = self.parse_prefix(); let mut lhs = self.parse_prefix()?;
loop { loop {
let op = match self.peek() { let op = match self.peek() {
@ -81,16 +94,16 @@ impl Parser {
self.advance(); self.advance();
let rhs = self.parse_expr(right_bp); let rhs = self.parse_expr(right_bp)?;
lhs = Expr::Binary { left: Box::new(lhs), op, right: Box::new(rhs) } lhs = Expr::Binary { left: Box::new(lhs), op, right: Box::new(rhs) }
} }
lhs Ok(lhs)
} }
pub fn parse(&mut self) -> Expr { pub fn parse(&mut self) -> ParseResult<Expr> {
if self.peek().is_none() {return Expr::EOL} if self.peek().is_none() {return Ok(Expr::EOL)}
self.parse_expr(0) self.parse_expr(0)
} }
} }