From c6e6e1dbee42e4d927ab216fdc1c5046d87e0c0f Mon Sep 17 00:00:00 2001 From: sofia Date: Wed, 17 Jul 2024 18:39:31 +0300 Subject: [PATCH] Fix operator precedence parsing --- examples/easiest.rs | 4 ++-- examples/reid/easy.reid | 6 +++--- src/ast.rs | 21 +++++++++++---------- src/token_stream.rs | 3 ++- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/examples/easiest.rs b/examples/easiest.rs index 09dd5d0..747771d 100644 --- a/examples/easiest.rs +++ b/examples/easiest.rs @@ -1,9 +1,9 @@ use reid::compile; -pub static EASIEST: &str = include_str!("./reid/easiest.reid"); +pub static EASY: &str = include_str!("./reid/easy.reid"); fn main() { - let text = match compile(EASIEST) { + let text = match compile(EASY) { Ok(t) => t, Err(e) => panic!("{}", e), }; diff --git a/examples/reid/easy.reid b/examples/reid/easy.reid index f5a77dc..6727da2 100644 --- a/examples/reid/easy.reid +++ b/examples/reid/easy.reid @@ -3,10 +3,10 @@ import std::print; fn main() { - let test = 5; + let test = 9; let simpleAdd = 2 + 2; + let simpleMult = 7 * 2; let arithmetic = 3 + 2 * 5 + 1 * 2; - let multiplier = 5 * 2; - return arithmetic + multiplier * arithmetic; + return arithmetic + simpleMult * arithmetic; } \ No newline at end of file diff --git a/src/ast.rs b/src/ast.rs index 6d240ae..46371d6 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -46,7 +46,7 @@ pub enum Expression { impl Parse for Expression { fn parse(mut stream: TokenStream) -> Result { let lhs = parse_primary_expression(&mut stream)?; - parse_binop_rhs(&mut stream, lhs, None) + parse_binop_rhs(&mut stream, lhs, 0, None).map(|(rhs, _)| rhs) } } @@ -81,27 +81,28 @@ fn parse_primary_expression(stream: &mut TokenStream) -> Result, -) -> Result { - let expr_prec = if let Some(op) = operator { - op.get_precedence() + 1 - } else { - 0 - }; - +) -> Result<(Expression, Option), Error> { while let Some(op) = operator.take().as_ref().or(stream.parse().as_ref().ok()) { let curr_token_prec = op.get_precedence(); if curr_token_prec < expr_prec { + let _ = operator.insert(*op); break; // Just return lhs } else { let mut rhs = parse_primary_expression(stream)?; + if let Ok(next_op) = stream.parse::() { let next_prec = next_op.get_precedence(); if curr_token_prec < next_prec { // Operator on the right of rhs has more precedence, turn // rhs into lhs for new binop - rhs = parse_binop_rhs(stream, rhs, Some(next_op))?; + let op; + (rhs, op) = parse_binop_rhs(stream, rhs, curr_token_prec + 1, Some(next_op))?; + if let Some(upcoming_op) = op { + let _ = operator.insert(upcoming_op); + } } else { let _ = operator.insert(next_op); } @@ -111,7 +112,7 @@ fn parse_binop_rhs( } } - Ok(lhs) + Ok((lhs, operator)) } #[derive(Debug, Clone, Copy)] diff --git a/src/token_stream.rs b/src/token_stream.rs index b86658d..395ed10 100644 --- a/src/token_stream.rs +++ b/src/token_stream.rs @@ -57,7 +57,7 @@ impl<'a, 'b> TokenStream<'a, 'b> { } } - pub fn parse(&mut self) -> Result { + pub fn parse(&mut self) -> Result { let mut ref_pos = self.position; let position = self.position; @@ -70,6 +70,7 @@ impl<'a, 'b> TokenStream<'a, 'b> { match T::parse(clone) { Ok(res) => { self.position = ref_pos.max(self.position); + dbg!(&res); Ok(res) } Err(e) => Err(e),