diff --git a/src/parser/parser.rs b/src/parser/parser.rs index be9135a..4f9a396 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -1,52 +1,76 @@ use super::types::*; use crate::ast; -fn parse_simple_expr(tokens: &mut Vec) -> Result { - 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) - } else { - Err(Error::UnexpectedToken { expected: Token::CloseParen, got: start}) - } +fn parse_expr(tokens: &mut Tokens) -> ParseResult { + todo!() +} - } - Token::Number(n) => { - tokens.pop(); - Ok(ast::Expr::Value(ast::Value::Number(n))) +fn parse_simple_expr(tokens: &mut Tokens) -> ParseResult { + 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 { + { + 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 { - UnexpectedToken{expected: Token, got: LocatedToken}, - UnexpectedToken(LocatedToken), - UnexpectedEndOfInput, +fn parse_number(tokens: &mut Tokens) -> ParseResult { + { + 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) -> Result { - if let Some(start) = tokens.pop_if(|tok| tok.token == Token::Let) { +fn parse_definition(tokens: &mut Tokens) -> Result { + 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)?; - Ok(ast::Definition { - name: ast::Name(identifier), - expr, - }) + }) = 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, + }) + } } 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::UnexpectedEndOfInput) diff --git a/src/parser/types.rs b/src/parser/types.rs index 362c7c7..e722b13 100644 --- a/src/parser/types.rs +++ b/src/parser/types.rs @@ -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); impl Tokens { - fn peek(&mut self) -> Option { - self.last() + pub fn peek(&mut self) -> Option<&LocatedToken> { + self.0.last() } - fn next(&mut self) -> Option { - self.pop() + pub fn next(&mut self) -> Option { + self.0.pop() + } + pub fn next_if(&mut self, token: Token) -> Option { + 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(&mut self, start: Token, end: Token, parser: Parser) -> ParseResult { + 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(&mut self, parsers: Vec>) -> ParseResult { + for parser in parsers { + if let Some(result) = parser(self)? { + return Ok(Some(result)); + } + } + Ok(None) } } + +pub type Parser = fn(&mut Tokens) -> ParseResult; +pub type ParseResult = Result, Error>; + +pub enum Error { + UnexpectedToken { expected: Token, got: LocatedToken }, + UnexpectedEndOfInput, + UnexpectedTokenForParser, +}