some improvements on parser

This commit is contained in:
me 2025-12-15 22:50:48 +02:00
parent ebbc4be8f6
commit 290dcab5e9
2 changed files with 96 additions and 38 deletions

View file

@ -1,52 +1,76 @@
use super::types::*;
use crate::ast;
fn parse_simple_expr(tokens: &mut Vec<LocatedToken>) -> Result<ast::Expr, Error> {
let start = tokens.last()?;
match start {
Token::OpenParen => {
tokens.pop();
let expr = parse_expr(tokens)?;
if Some(p) = tokens.pop_if(|t| t.token == Token::CloseParen) {
Ok(expr)
fn parse_expr(tokens: &mut Tokens) -> ParseResult<ast::Expr> {
todo!()
}
fn parse_simple_expr(tokens: &mut Tokens) -> ParseResult<ast::Expr> {
tokens.one_of(vec![
|t| t.between(Token::OpenParen, Token::CloseParen, parse_expr),
parse_number,
|_| Err(Error::UnexpectedEndOfInput),
])
}
fn parse_string(tokens: &mut Tokens) -> ParseResult<ast::Expr> {
{
if let Some(LocatedToken {
token: Token::String(string),
..
}) = tokens.next_if(Token::String("".into()))
{
Ok(Some(ast::Expr::Value(ast::Value::String(string))))
} else {
Err(Error::UnexpectedToken { expected: Token::CloseParen, got: start})
}
}
Token::Number(n) => {
tokens.pop();
Ok(ast::Expr::Value(ast::Value::Number(n)))
Ok(None)
}
}
}
enum Error {
UnexpectedToken{expected: Token, got: LocatedToken},
UnexpectedToken(LocatedToken),
UnexpectedEndOfInput,
fn parse_number(tokens: &mut Tokens) -> ParseResult<ast::Expr> {
{
if let Some(LocatedToken {
token: Token::Number(number),
..
}) = tokens.next_if(Token::Number(0))
{
Ok(Some(ast::Expr::Value(ast::Value::Int(number.into()))))
} else {
Ok(None)
}
}
}
fn parse_definition(tokens: &mut Vec<LocatedToken>) -> Result<ast::Definition, Error> {
if let Some(start) = tokens.pop_if(|tok| tok.token == Token::Let) {
fn parse_definition(tokens: &mut Tokens) -> Result<ast::Definition, Error> {
if let Some(start) = tokens.next_if(Token::Let) {
if let Some(LocatedToken {
token: Token::Identifier(identifier),
..
}) = tokens.pop_if(|tok| match tok.token {
Token::Identifier(_) => true,
_ => false,
}) {
if let Some(_eq) = tokens.pop_if(|tok| tok.token == Token::Equals) {
let expr = parse_expr(tokens)?;
}) = tokens.next_if(Token::Identifier("".into()))
{
if let Some(_eq) = tokens.next_if(Token::Equals) {
if let Some(expr) = parse_expr(tokens)? {
Ok(ast::Definition {
name: ast::Name(identifier),
expr,
})
} else {
Err(Error::UnexpectedToken{expected: Token::Equals, got: start})
Err(Error::UnexpectedToken {
expected: Token::Equals,
got: start,
})
}
} else {
Err(Error::UnexpectedToken{expected: Token::Equals, got: start})
Err(Error::UnexpectedToken {
expected: Token::Equals,
got: start,
})
}
} else {
Err(Error::UnexpectedToken {
expected: Token::Equals,
got: start,
})
}
} else {
Err(Error::UnexpectedEndOfInput)

View file

@ -21,7 +21,6 @@ pub enum Token {
Comma,
Semicolon,
Colon,
Name(String),
Number(u32),
String(String),
Identifier(String),
@ -30,10 +29,45 @@ pub enum Token {
pub struct Tokens(Vec<LocatedToken>);
impl Tokens {
fn peek(&mut self) -> Option<LocatedToken> {
self.last()
pub fn peek(&mut self) -> Option<&LocatedToken> {
self.0.last()
}
fn next(&mut self) -> Option<LocatedToken> {
self.pop()
pub fn next(&mut self) -> Option<LocatedToken> {
self.0.pop()
}
pub fn next_if(&mut self, token: Token) -> Option<LocatedToken> {
self.0.pop_if(|t| match (&t.token, &token) {
(a, b) if a == b => true,
(Token::Identifier(_), Token::Identifier(_)) => true,
(Token::Number(_), Token::Number(_)) => true,
(Token::String(_), Token::String(_)) => true,
_ => false,
})
}
pub fn between<T>(&mut self, start: Token, end: Token, parser: Parser<T>) -> ParseResult<T> {
let _start = self.next_if(start).ok_or(Error::UnexpectedEndOfInput)?;
if let Some(result) = parser(self)? {
let _end = self.next_if(end).ok_or(Error::UnexpectedEndOfInput)?;
Ok(Some(result))
} else {
Err(Error::UnexpectedTokenForParser)
}
}
pub fn one_of<T>(&mut self, parsers: Vec<Parser<T>>) -> ParseResult<T> {
for parser in parsers {
if let Some(result) = parser(self)? {
return Ok(Some(result));
}
}
Ok(None)
}
}
pub type Parser<T> = fn(&mut Tokens) -> ParseResult<T>;
pub type ParseResult<T> = Result<Option<T>, Error>;
pub enum Error {
UnexpectedToken { expected: Token, got: LocatedToken },
UnexpectedEndOfInput,
UnexpectedTokenForParser,
}