Fix operator precedence parsing
This commit is contained in:
parent
47b9d7e044
commit
c6e6e1dbee
@ -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),
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
}
|
}
|
21
src/ast.rs
21
src/ast.rs
@ -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)]
|
||||||
|
@ -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),
|
||||||
|
Loading…
Reference in New Issue
Block a user