Compare commits

..

No commits in common. "a21b119e580e692b8796cc1220706b65167ee07f" and "a887bf4b3e8101bdc99554e5a9e25803e7dc5c6e" have entirely different histories.

5 changed files with 43 additions and 185 deletions

View file

@ -1,41 +0,0 @@
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 {}
#[derive(Debug)]
pub struct LexError {
message: String
}
impl LexError {
pub fn new(message: impl Into<String>) -> Self {
Self { message: message.into() }
}
}
impl Display for LexError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "lex error: {}", self.message)
}
}
impl Error for LexError {}

View file

@ -1,6 +1,4 @@
use crate::{error::LexError, token::Token}; use crate::token::Token;
type LexResult<T> = Result<T, LexError>;
pub struct Lexer { pub struct Lexer {
source: Vec<u8>, source: Vec<u8>,
@ -29,7 +27,7 @@ impl Lexer {
self.source.get(self.pos).copied() self.source.get(self.pos).copied()
} }
fn number(&mut self) -> LexResult<Token> { fn number(&mut self) -> Option<Token> {
let mut num = String::new(); let mut num = String::new();
while matches!(self.peek(), Some(b'0' ..= b'9')) { while matches!(self.peek(), Some(b'0' ..= b'9')) {
@ -37,97 +35,42 @@ impl Lexer {
self.advance(); self.advance();
} }
Ok(Token::Number(num.parse().unwrap())) Some(Token::Number(num.parse().unwrap()))
} }
fn ident(&mut self) -> LexResult<Token> { fn ident(&mut self) -> Option<Token> {
let mut ident = String::new(); let mut ident = String::new();
while matches!(self.peek(), Some(b'a' ..= b'z' | b'A' ..= b'Z' | b'0' ..= b'9' | b'_')) { while matches!(self.peek(), Some(b'a' ..= b'z' | b'A' ..= b'Z')) {
ident.push(self.peek().unwrap() as char); ident.push(self.peek().unwrap() as char);
self.advance();
} }
let tok = match ident.as_str() { Some(Token::Ident(ident))
"mov" => Token::Mov,
"if" => Token::If,
"else" => Token::Else,
"loop" => Token::Loop,
"while" => Token::While,
"for" => Token::For,
"in" => Token::In,
"fun" => Token::Fun,
"call" => Token::Call,
"break" => Token::Break,
"continue" => Token::Continue,
"true" => Token::True,
"false" => Token::False,
"eq" => Token::Eq,
"new" => Token::Neq,
"lt" => Token::Lt,
"gt" => Token::Gt,
"lte" => Token::Lte,
"gte" => Token::Gte,
_ => Token::Ident(ident)
};
Ok(tok)
} }
fn string(&mut self) -> LexResult<Token> { pub fn next(&mut self) -> Option<Token> {
self.advance();
let mut s = String::new();
loop {
match self.peek() {
Some(b'"') => { self.advance(); break; },
Some(c) => { s.push(c as char); self.advance(); }
None => { return Err(LexError::new(format!(
"expected closing \""
))); }
}
}
Ok(Token::StringLit(s))
}
pub fn next(&mut self) -> LexResult<Token> {
self.skip_whitespace(); self.skip_whitespace();
match self.peek() { match self.peek() {
Some(b'0' ..= b'9') => self.number(), Some(b'0' ..= b'9') => self.number(),
Some(b'a' ..= b'z' | b'A' ..= b'Z') => self.ident(), Some(b'a' ..= b'z' | b'A' ..= b'Z') => self.ident(),
Some(b'+') => {self.advance(); Ok(Token::Plus)}, Some(b'+') => {self.advance(); Some(Token::Plus)},
Some(b'-') => {self.advance(); Ok(Token::Minus)}, Some(b'-') => {self.advance(); Some(Token::Minus)},
Some(b'*') => {self.advance(); Ok(Token::Asterisk)}, Some(b'*') => {self.advance(); Some(Token::Asterisk)},
Some(b'/') => {self.advance(); Ok(Token::Slash)}, Some(b'/') => {self.advance(); Some(Token::Slash)},
Some(b'%') => {self.advance(); Ok(Token::Percent)}, Some(b'%') => {self.advance(); Some(Token::Percent)},
Some(b'^') => {self.advance(); Ok(Token::Caret)}, Some(b'^') => {self.advance(); Some(Token::Caret)},
Some(b'(') => {self.advance(); Ok(Token::LParen)}, Some(b'(') => {self.advance(); Some(Token::LParen)},
Some(b')') => {self.advance(); Ok(Token::RParen)}, Some(b')') => {self.advance(); Some(Token::RParen)},
Some(b'[') => {self.advance(); Ok(Token::LBracket)}, Some(b'[') => {self.advance(); Some(Token::LBracket)},
Some(b']') => {self.advance(); Ok(Token::RBracket)}, Some(b']') => {self.advance(); Some(Token::RBracket)},
Some(b'{') => {self.advance(); Ok(Token::LBrace)}, Some(b'{') => {self.advance(); Some(Token::LBrace)},
Some(b'}') => {self.advance(); Ok(Token::RBrace)}, Some(b'}') => {self.advance(); Some(Token::RBrace)},
Some(b';') => {self.advance(); Ok(Token::Semicolon)}, Some(b';') => {self.advance(); Some(Token::Semicolon)}
Some(b',') => {self.advance(); Ok(Token::Comma)},
Some(b'.') => { _ => None
self.advance();
match self.peek() {
Some(b'.') => { self.advance(); Ok(Token::DotDot) },
c => Err(LexError::new(format!(
"unexpected character after '.': {c:?}"
)))
}
},
Some(b'"') => self.string(),
_ => Ok(Token::EOF)
} }
} }
} }

View file

@ -3,7 +3,6 @@ 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;
@ -21,8 +20,7 @@ fn main() -> std::io::Result<()> {
let mut lexer = Lexer::new(&source); let mut lexer = Lexer::new(&source);
let mut tokens = Vec::new(); let mut tokens = Vec::new();
while let Ok(tok) = lexer.next() { while let Some(tok) = lexer.next() {
if tok == token::Token::EOF { break; }
print!("{tok:?}, "); print!("{tok:?}, ");
tokens.push(tok); tokens.push(tok);
} }
@ -31,7 +29,7 @@ fn main() -> std::io::Result<()> {
let mut parser = Parser::new(tokens); let mut parser = Parser::new(tokens);
loop { loop {
let parsed = parser.parse().unwrap_or(expr::Expr::EOL); let parsed = parser.parse();
match parsed { match parsed {
expr::Expr::EOL => break, expr::Expr::EOL => break,
_ => { _ => {

View file

@ -1,8 +1,5 @@
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>,
@ -31,49 +28,39 @@ impl Parser {
tok tok
} }
fn expect(&mut self, expected: &Token) -> ParseResult<Token> { fn parse_atom(&mut self) -> Expr {
match self.next() { match self.next() {
Some(tok) if &tok == expected => Ok(tok), Some(Token::Number(n)) => Expr::Number(n),
other => Err(ParseError::new(format!( Some(Token::Ident(id)) => Expr::Ident(id),
"expected {expected:?}, got {other:?}"
)))
}
}
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) => { Some(Token::LParen) => {
let expr = self.parse_expr(0)?; let expr = self.parse_expr(0);
self.expect(&Token::RParen)?; match self.next() {
Some(Token::RParen) => expr,
Ok(expr) _ => panic!("expected ')'")
}
}, },
tok => Err(ParseError::new(format!( tok => panic!("unknown token: {tok:?}")
"unexpected token: {tok:?}"
)))
} }
} }
fn parse_prefix(&mut self) -> ParseResult<Expr> { fn parse_prefix(&mut self) -> 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);
Ok(Expr::Unary { op, right: Box::new(rhs) }) Expr::Unary { op, right: Box::new(rhs) }
}, },
_ => self.parse_atom() _ => self.parse_atom()
} }
} }
fn parse_expr(&mut self, min_bp: u8) -> ParseResult<Expr> { fn parse_expr(&mut self, min_bp: u8) -> 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() {
@ -94,16 +81,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) }
} }
Ok(lhs) lhs
} }
pub fn parse(&mut self) -> ParseResult<Expr> { pub fn parse(&mut self) -> Expr {
if self.peek().is_none() {return Ok(Expr::EOL)} if self.peek().is_none() {return Expr::EOL}
self.parse_expr(0) self.parse_expr(0)
} }
} }

View file

@ -2,7 +2,6 @@
pub enum Token { pub enum Token {
Number(i64), Number(i64),
Ident(String), Ident(String),
StringLit(String),
// Operators // Operators
Plus, Plus,
@ -20,33 +19,5 @@ pub enum Token {
LBracket, LBracket,
RBracket, RBracket,
// Separators Semicolon
Semicolon,
Comma,
// Keywords
Mov,
If,
Else,
Loop,
While,
For,
In,
Fun,
Call,
Break,
Continue,
True,
False,
DotDot,
// Conditionals
Eq,
Neq,
Lt,
Gt,
Lte,
Gte,
EOF
} }