diff --git a/src/lexer/mod.rs b/src/lexer/mod.rs index 95587cf..4acaa68 100644 --- a/src/lexer/mod.rs +++ b/src/lexer/mod.rs @@ -29,9 +29,9 @@ impl<'de> Lexer<'de> { Some(Ok(token)) if expected == token.kind => Ok(token), Some(Ok(token)) => Err(miette::miette! { labels = vec![ - token.label(format!("Expected {} here", expected)) + token.label(format!("expected {} here", expected)) ], - help = format!("Expected {}, got {}", expected, token.kind), + help = format!("expected {}, got {} instead", expected, token.kind), "{unexpected}", } .with_source_code(self.whole.to_string())), @@ -59,14 +59,14 @@ impl<'de> Lexer<'de> { labels = vec![ token.label("here") ], - help = format!("Expected {token:?}"), + help = format!("expected {token:?}"), "{unexpected}", } .with_source_code(self.whole.to_string())), Some(Err(e)) => Err(e), None => Err(miette::miette! { labels = vec![ - LabeledSpan::at_offset(self.byte_offset - 1, "Expected more source code here") + LabeledSpan::at_offset(self.byte_offset - 1, "expected more source code here") ], help = "more source code was expected, but none was found", "{unexpected}", diff --git a/src/main.rs b/src/main.rs index ebbe624..ce27db3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,7 @@ pub mod lexer; pub mod parser; fn main() { - let input = "1 + 1111;"; + let input = "1 * 2 + 3;"; let mut parser = Parser::new(input); let symbol = match parser.parse() { diff --git a/src/parser/ast.rs b/src/parser/ast.rs index cd68ad8..00df1ca 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -25,7 +25,7 @@ pub enum Expression<'de> { #[derive(Debug)] pub enum Primitive<'de> { Integer(i64), - Float(f64), + Decimal(f64), String(Cow<'de, str>), Boolean(bool), } diff --git a/src/parser/expression.rs b/src/parser/expression.rs index 790e30d..0c1031a 100644 --- a/src/parser/expression.rs +++ b/src/parser/expression.rs @@ -20,8 +20,8 @@ pub fn parse<'de>( Some(Err(err)) => return Err(miette::miette!(err.to_string())), // FIXME: better error handling None => { return Err(miette::miette! { - help = "expected a new expression", - "expected a new expression, found EOF" + help = "expected an expression", + "expected an expression" } .with_source_code(parser.source.to_string())) } @@ -29,9 +29,9 @@ pub fn parse<'de>( let handler = parser.lookup.expression_lookup.get(&token.kind).ok_or( miette::miette! { - labels = vec![token.label("expected a new expression")], - help = format!("cannot parse {} into a new expression", token.kind), - "expected a new expression, found {}", token.kind + labels = vec![token.label("expected an expression")], + help = format!("{} is not an expression", token.kind), + "expected an expression, found {}", token.kind } .with_source_code(parser.source.to_string()), )?; diff --git a/src/parser/lookup.rs b/src/parser/lookup.rs index b5343d8..7c92578 100644 --- a/src/parser/lookup.rs +++ b/src/parser/lookup.rs @@ -110,7 +110,13 @@ impl<'de> Default for Lookup<'de> { // left_type_lookup: HashMap::new(), } .add_expression_handler(TokenKind::Integer, integer) + .add_expression_handler(TokenKind::Decimal, decimal) .add_left_expression_handler(TokenKind::Plus, BindingPower::Additive, addition) + .add_left_expression_handler( + TokenKind::Star, + BindingPower::Multiplicative, + multiplication, + ) } } @@ -127,6 +133,19 @@ fn integer<'de>(parser: &mut Parser) -> Result> { Ok(Expression::Primitive(Primitive::Integer(value))) } +fn decimal<'de>(parser: &mut Parser) -> Result> { + let token = parser + .lexer + .expect(TokenKind::Decimal, "expected a decimal")?; + + let value = match token.value { + TokenValue::Decimal(v) => v, + _ => unreachable!(), + }; + + Ok(Expression::Primitive(Primitive::Decimal(value))) +} + fn addition<'de>( parser: &mut Parser<'de>, lhs: Expression<'de>, @@ -140,3 +159,17 @@ fn addition<'de>( right: Box::new(rhs), }) } + +fn multiplication<'de>( + parser: &mut Parser<'de>, + lhs: Expression<'de>, + bp: BindingPower, +) -> Result> { + let rhs = expression::parse(parser, bp)?; + + Ok(Expression::Binary { + operator: BinaryOperator::Multiply, + left: Box::new(lhs), + right: Box::new(rhs), + }) +} diff --git a/src/parser/statement.rs b/src/parser/statement.rs index a46a6b5..89da7a2 100644 --- a/src/parser/statement.rs +++ b/src/parser/statement.rs @@ -5,9 +5,10 @@ use miette::{Context, Result}; pub fn parse<'de>(parser: &mut Parser<'de>) -> Result> { let expression = expression::parse(parser, BindingPower::None)?; - parser - .lexer - .expect(TokenKind::Semicolon, "expected a semicolon")?; + parser.lexer.expect( + TokenKind::Semicolon, + "expected a semicolon at the end of an expression", + )?; Ok(Statement::Expression(expression)) }