Add precedent operators * and /
This commit is contained in:
parent
3c45dcbb4c
commit
10f7e32046
1 changed files with 71 additions and 3 deletions
|
@ -83,18 +83,31 @@ fn parse_identifier<'source>(pos: &mut usize, tokens: &[Token<'source>]) -> Expr
|
||||||
Identifier(token.text)
|
Identifier(token.text)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_term<'source>(pos: &mut usize, tokens: &[Token<'source>]) -> Expression<'source> {
|
fn parse_factor<'source>(pos: &mut usize, tokens: &[Token<'source>]) -> Expression<'source> {
|
||||||
match peek(pos, tokens).token_type {
|
match peek(pos, tokens).token_type {
|
||||||
TokenType::Integer => parse_int_literal(pos, tokens),
|
TokenType::Integer => parse_int_literal(pos, tokens),
|
||||||
TokenType::Identifier => parse_identifier(pos, tokens),
|
TokenType::Identifier => parse_identifier(pos, tokens),
|
||||||
_ => panic!("Unexpected token {}", peek(pos, tokens)),
|
_ => panic!("Unexpected {}", peek(pos, tokens)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_term<'source>(pos: &mut usize, tokens: &[Token<'source>]) -> Expression<'source> {
|
||||||
|
let mut left = parse_factor(pos, tokens);
|
||||||
|
|
||||||
|
while ["*", "/"].contains(&peek(pos, tokens).text) {
|
||||||
|
let operator_token = next_expect_strings(pos, tokens, &vec!["*", "/"]);
|
||||||
|
let right = parse_factor(pos, tokens);
|
||||||
|
|
||||||
|
left = BinaryOp(Box::new(left), operator_token.text, Box::new(right));
|
||||||
|
}
|
||||||
|
|
||||||
|
left
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_expression<'source>(pos: &mut usize, tokens: &[Token<'source>]) -> Expression<'source> {
|
fn parse_expression<'source>(pos: &mut usize, tokens: &[Token<'source>]) -> Expression<'source> {
|
||||||
let mut left = parse_term(pos, tokens);
|
let mut left = parse_term(pos, tokens);
|
||||||
|
|
||||||
while vec!["+", "-"].contains(&peek(pos, tokens).text) {
|
while ["+", "-"].contains(&peek(pos, tokens).text) {
|
||||||
let operator_token = next_expect_strings(pos, tokens, &vec!["+", "-"]);
|
let operator_token = next_expect_strings(pos, tokens, &vec!["+", "-"]);
|
||||||
let right = parse_term(pos, tokens);
|
let right = parse_term(pos, tokens);
|
||||||
|
|
||||||
|
@ -138,6 +151,18 @@ mod tests {
|
||||||
result,
|
result,
|
||||||
BinaryOp(Box::new(IntLiteral(4)), "-", Box::new(IntLiteral(56)))
|
BinaryOp(Box::new(IntLiteral(4)), "-", Box::new(IntLiteral(56)))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let result = parse(&vec![new_int("1"), new_id("*"), new_int("2")]);
|
||||||
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
BinaryOp(Box::new(IntLiteral(1)), "*", Box::new(IntLiteral(2)))
|
||||||
|
);
|
||||||
|
|
||||||
|
let result = parse(&vec![new_int("1"), new_id("/"), new_int("2")]);
|
||||||
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
BinaryOp(Box::new(IntLiteral(1)), "/", Box::new(IntLiteral(2)))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -177,4 +202,47 @@ mod tests {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_binary_op_precedence() {
|
||||||
|
let result = parse(&vec![
|
||||||
|
new_int("1"),
|
||||||
|
new_id("+"),
|
||||||
|
new_int("2"),
|
||||||
|
new_id("*"),
|
||||||
|
new_int("3"),
|
||||||
|
]);
|
||||||
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
BinaryOp(
|
||||||
|
Box::new(IntLiteral(1)),
|
||||||
|
"+",
|
||||||
|
Box::new(BinaryOp(
|
||||||
|
Box::new(IntLiteral(2)),
|
||||||
|
"*",
|
||||||
|
Box::new(IntLiteral(3))
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
let result = parse(&vec![
|
||||||
|
new_int("1"),
|
||||||
|
new_id("-"),
|
||||||
|
new_int("2"),
|
||||||
|
new_id("/"),
|
||||||
|
new_int("3"),
|
||||||
|
]);
|
||||||
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
BinaryOp(
|
||||||
|
Box::new(IntLiteral(1)),
|
||||||
|
"-",
|
||||||
|
Box::new(BinaryOp(
|
||||||
|
Box::new(IntLiteral(2)),
|
||||||
|
"/",
|
||||||
|
Box::new(IntLiteral(3))
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue