Fix operator precedence parsing

This commit is contained in:
Sofia 2024-07-17 18:39:31 +03:00
parent 47b9d7e044
commit c6e6e1dbee
4 changed files with 18 additions and 16 deletions

View File

@ -1,9 +1,9 @@
use reid::compile; use reid::compile;
pub static EASIEST: &str = include_str!("./reid/easiest.reid"); pub static EASY: &str = include_str!("./reid/easy.reid");
fn main() { fn main() {
let text = match compile(EASIEST) { let text = match compile(EASY) {
Ok(t) => t, Ok(t) => t,
Err(e) => panic!("{}", e), Err(e) => panic!("{}", e),
}; };

View File

@ -3,10 +3,10 @@
import std::print; import std::print;
fn main() { fn main() {
let test = 5; let test = 9;
let simpleAdd = 2 + 2; let simpleAdd = 2 + 2;
let simpleMult = 7 * 2;
let arithmetic = 3 + 2 * 5 + 1 * 2; let arithmetic = 3 + 2 * 5 + 1 * 2;
let multiplier = 5 * 2;
return arithmetic + multiplier * arithmetic; return arithmetic + simpleMult * arithmetic;
} }

View File

@ -46,7 +46,7 @@ pub enum Expression {
impl Parse for Expression { impl Parse for Expression {
fn parse(mut stream: TokenStream) -> Result<Expression, Error> { fn parse(mut stream: TokenStream) -> Result<Expression, Error> {
let lhs = parse_primary_expression(&mut stream)?; 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<Expression, Erro
fn parse_binop_rhs( fn parse_binop_rhs(
stream: &mut TokenStream, stream: &mut TokenStream,
mut lhs: Expression, mut lhs: Expression,
expr_prec: i8,
mut operator: Option<BinaryOperator>, mut operator: Option<BinaryOperator>,
) -> Result<Expression, Error> { ) -> Result<(Expression, Option<BinaryOperator>), Error> {
let expr_prec = if let Some(op) = operator {
op.get_precedence() + 1
} else {
0
};
while let Some(op) = operator.take().as_ref().or(stream.parse().as_ref().ok()) { while let Some(op) = operator.take().as_ref().or(stream.parse().as_ref().ok()) {
let curr_token_prec = op.get_precedence(); let curr_token_prec = op.get_precedence();
if curr_token_prec < expr_prec { if curr_token_prec < expr_prec {
let _ = operator.insert(*op);
break; // Just return lhs break; // Just return lhs
} else { } else {
let mut rhs = parse_primary_expression(stream)?; let mut rhs = parse_primary_expression(stream)?;
if let Ok(next_op) = stream.parse::<BinaryOperator>() { if let Ok(next_op) = stream.parse::<BinaryOperator>() {
let next_prec = next_op.get_precedence(); let next_prec = next_op.get_precedence();
if curr_token_prec < next_prec { if curr_token_prec < next_prec {
// Operator on the right of rhs has more precedence, turn // Operator on the right of rhs has more precedence, turn
// rhs into lhs for new binop // 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 { } else {
let _ = operator.insert(next_op); let _ = operator.insert(next_op);
} }
@ -111,7 +112,7 @@ fn parse_binop_rhs(
} }
} }
Ok(lhs) Ok((lhs, operator))
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]

View File

@ -57,7 +57,7 @@ impl<'a, 'b> TokenStream<'a, 'b> {
} }
} }
pub fn parse<T: Parse>(&mut self) -> Result<T, Error> { pub fn parse<T: Parse + std::fmt::Debug>(&mut self) -> Result<T, Error> {
let mut ref_pos = self.position; let mut ref_pos = self.position;
let position = self.position; let position = self.position;
@ -70,6 +70,7 @@ impl<'a, 'b> TokenStream<'a, 'b> {
match T::parse(clone) { match T::parse(clone) {
Ok(res) => { Ok(res) => {
self.position = ref_pos.max(self.position); self.position = ref_pos.max(self.position);
dbg!(&res);
Ok(res) Ok(res)
} }
Err(e) => Err(e), Err(e) => Err(e),