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

View file

@ -21,7 +21,6 @@ pub enum Token {
Comma, Comma,
Semicolon, Semicolon,
Colon, Colon,
Name(String),
Number(u32), Number(u32),
String(String), String(String),
Identifier(String), Identifier(String),
@ -30,10 +29,45 @@ pub enum Token {
pub struct Tokens(Vec<LocatedToken>); pub struct Tokens(Vec<LocatedToken>);
impl Tokens { impl Tokens {
fn peek(&mut self) -> Option<LocatedToken> { pub fn peek(&mut self) -> Option<&LocatedToken> {
self.last() self.0.last()
} }
fn next(&mut self) -> Option<LocatedToken> { pub fn next(&mut self) -> Option<LocatedToken> {
self.pop() 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,
}