diff --git a/src/parser/expression.rs b/src/parser/expression.rs index 8864b46..790e30d 100644 --- a/src/parser/expression.rs +++ b/src/parser/expression.rs @@ -35,10 +35,11 @@ pub fn parse<'de>( } .with_source_code(parser.source.to_string()), )?; - let mut lhs = handler(parser)?; - while let Some(token) = parser.lexer.peek() { + let mut next_token = parser.lexer.peek(); + + while let Some(token) = next_token { let token = match token { Ok(token) => token, Err(err) => return Err(miette::miette!(err.to_string())), // FIXME: better error handling @@ -64,22 +65,9 @@ pub fn parse<'de>( parser.lexer.next(); lhs = handler(parser, lhs, token_binding_power)?; + + next_token = parser.lexer.peek(); } Ok(lhs) } - -pub fn add_handlers<'de>(lookup: &'de mut Lookup<'de>) { - lookup.add_left_expression_handler( - TokenKind::Plus, - BindingPower::Additive, - |parser: &mut Parser<'_>, lhs: Expression<'_>, bp| -> Result> { - let rhs = parse(parser, bp)?; - Ok(Expression::Binary { - operator: BinaryOperator::Add, - left: Box::new(lhs), - right: Box::new(rhs), - }) - }, - ); -} diff --git a/src/parser/lookup.rs b/src/parser/lookup.rs index 086f926..3d6dd4b 100644 --- a/src/parser/lookup.rs +++ b/src/parser/lookup.rs @@ -1,9 +1,9 @@ -use crate::lexer::TokenKind; +use crate::lexer::{TokenKind, TokenValue}; use miette::Result; use std::collections::HashMap; use super::{ - ast::{Expression, Statement}, + ast::{BinaryOperator, Expression, Primitive, Statement}, expression, Parser, }; @@ -25,10 +25,10 @@ pub enum BindingPower { // pub type TypeHandler<'de> = fn(&mut Parser<'de>) -> Result<(Type, usize), Error<'de>>; // pub type LeftTypeHandler<'de> = // fn(&'de Parser<'de>, usize, Type, &BindingPower) -> Result<(Type, usize), Error<'de>>; -pub type StatementHandler<'de> = fn(&'de mut Parser<'de>) -> Result>; -pub type ExpressionHandler<'de> = fn(&'de mut Parser<'de>) -> Result>; +pub type StatementHandler<'de> = fn(&mut Parser<'de>) -> Result>; +pub type ExpressionHandler<'de> = fn(&mut Parser<'de>) -> Result>; pub type LeftExpressionHandler<'de> = - fn(&'de mut Parser<'de>, Expression, BindingPower) -> Result>; + fn(&mut Parser<'de>, Expression, BindingPower) -> Result>; pub struct Lookup<'de> { pub statement_lookup: HashMap>, @@ -41,41 +41,44 @@ pub struct Lookup<'de> { impl<'de> Lookup<'de> { pub(crate) fn add_statement_handler( - &'de mut self, + mut self, token: TokenKind, handler: StatementHandler<'de>, - ) { + ) -> Self { if self.statement_lookup.contains_key(&token) { panic!("Token already has a statement handler"); } self.statement_lookup.insert(token, handler); + self } pub(crate) fn add_expression_handler( - &'de mut self, + mut self, token: TokenKind, handler: ExpressionHandler<'de>, - ) { + ) -> Self { if self.expression_lookup.contains_key(&token) { panic!("Token already has an expression handler"); } self.expression_lookup.insert(token, handler); + self } pub(crate) fn add_left_expression_handler( - &'de mut self, + mut self, token: TokenKind, binding_power: BindingPower, handler: LeftExpressionHandler<'de>, - ) { + ) -> Self { if self.binding_power_lookup.contains_key(&token) { panic!("Token already has a binding power"); } self.left_expression_lookup.insert(token.clone(), handler); self.binding_power_lookup.insert(token, binding_power); + self } // pub(crate) fn add_type_handler(&mut self, token: TokenType, handler: TypeHandler<'de>) { @@ -98,17 +101,46 @@ impl<'de> Lookup<'de> { impl<'de> Default for Lookup<'de> { fn default() -> Self { - let mut lookup = Lookup { + Lookup { statement_lookup: HashMap::new(), expression_lookup: HashMap::new(), left_expression_lookup: HashMap::new(), binding_power_lookup: HashMap::new(), // type_lookup: HashMap::new(), // left_type_lookup: HashMap::new(), - }; + } + .add_expression_handler(TokenKind::Integer, integer) + .add_left_expression_handler(TokenKind::Plus, BindingPower::Additive, addition) + } +} - expression::add_handlers(&mut lookup); +fn integer<'de>(parser: &mut Parser) -> Result> { + let token = parser + .lexer + .expect(TokenKind::Integer, "expected an integer")?; - lookup - } + let value = match token.value { + TokenValue::Integer(v) => v, + _ => unreachable!(), + }; + + Ok(Expression::Primitive(Primitive::Integer(value))) +} + +fn addition<'de>( + parser: &mut Parser, + lhs: Expression, + bp: BindingPower, +) -> Result> { + let token = parser + .lexer + .expect(TokenKind::Plus, "expected a plus sign")?; + + let rhs = expression::parse(parser, bp)?; + + Ok(Expression::Binary { + operator: BinaryOperator::Add, + left: Box::new(lhs), + right: Box::new(rhs), + }) }