Add support for !=, <, <=, >, >=

This commit is contained in:
Olivier 'reivilibre' 2024-05-01 22:36:26 +01:00
parent 407a6b267e
commit f638ec66b4
4 changed files with 53 additions and 2 deletions

View File

@ -150,6 +150,14 @@ pub enum Expression {
left: Box<Expression>,
right: Box<Expression>,
},
LessThan {
left: Box<Expression>,
right: Box<Expression>,
},
LessThanOrEquals {
left: Box<Expression>,
right: Box<Expression>,
},
// Other Operators
ListAdd {

View File

@ -152,7 +152,7 @@ wshack = _{ (wsnc | (comment ~ &(ws* ~ Expr)))* }
Expr = { prefix* ~ ws* ~ Term ~ ws* ~ postfix* ~ (ws* ~ infix ~ ws* ~ prefix* ~ ws* ~ Term ~ wshack ~ postfix*)* }
// INFIX
infix = _{ add | sub | mul | div | pow | modulo | listAdd | equals | band | bor }
infix = _{ add | sub | mul | div | pow | modulo | listAdd | equals | notEquals | greaterThanOrEqual | lessThanOrEqual | greaterThan | lessThan | band | bor }
add = { "+" }
sub = { "-" }
mul = { "*" }
@ -161,6 +161,11 @@ pow = { "^" }
modulo = { "%" }
listAdd = { "++" }
equals = { "==" }
notEquals = { "!=" }
greaterThan = { ">" }
lessThan = { "<" }
greaterThanOrEqual = { ">=" }
lessThanOrEqual = { "<=" }
// BUG: these should have forced whitespace at the start!
// (lookbehind wouldn't be the worst feature in the world for a parser grammar!)

View File

@ -42,7 +42,12 @@ fn error<R: Copy + Debug + Hash + Ord>(msg: &str, span: Span) -> PCError<R> {
lazy_static! {
static ref PRATT_PARSER: PrattParser<Rule> = PrattParser::new()
.op(Op::infix(Rule::band, Assoc::Left) | Op::infix(Rule::bor, Assoc::Left))
.op(Op::infix(Rule::equals, Assoc::Left))
.op(Op::infix(Rule::equals, Assoc::Left)
| Op::infix(Rule::notEquals, Assoc::Left)
| Op::infix(Rule::lessThan, Assoc::Left)
| Op::infix(Rule::greaterThan, Assoc::Left)
| Op::infix(Rule::greaterThanOrEqual, Assoc::Left)
| Op::infix(Rule::lessThanOrEqual, Assoc::Left))
.op(Op::infix(Rule::add, Assoc::Left) | Op::infix(Rule::sub, Assoc::Left))
.op(Op::infix(Rule::mul, Assoc::Left) | Op::infix(Rule::div, Assoc::Left))
.op(Op::infix(Rule::pow, Assoc::Right))
@ -294,6 +299,11 @@ impl HornbeamParser {
Rule::mul => Expression::Mul { left: Box::new(lhs?), right: Box::new(rhs?) },
Rule::div => Expression::Div { left: Box::new(lhs?), right: Box::new(rhs?) },
Rule::equals => Expression::Equals { left: Box::new(lhs?), right: Box::new(rhs?) },
Rule::notEquals => Expression::BNot { sub: Box::new(Expression::Equals { left: Box::new(lhs?), right: Box::new(rhs?) }) },
Rule::lessThan => Expression::LessThan { left: Box::new(lhs?), right: Box::new(rhs?) },
Rule::lessThanOrEqual => Expression::LessThanOrEquals { left: Box::new(lhs?), right: Box::new(rhs?) },
Rule::greaterThan => Expression::BNot { sub: Box::new(Expression::LessThanOrEquals { left: Box::new(lhs?), right: Box::new(rhs?) }) },
Rule::greaterThanOrEqual => Expression::BNot { sub: Box::new(Expression::LessThan { left: Box::new(lhs?), right: Box::new(rhs?) }) },
Rule::bor => Expression::BOr { left: Box::new(lhs?), right: Box::new(rhs?) },
Rule::band => Expression::BAnd { left: Box::new(lhs?), right: Box::new(rhs?) },
other => unimplemented!("unimp infix {other:?}!"),

View File

@ -618,6 +618,34 @@ impl<'a, O: OutputSystem + Send, LS: LocalisationSystem + Sync + Send> Interpret
}),
}
}
Expression::LessThan { left, right } => {
let lval = self.evaluate_expression(scope_idx, &left, loc)?;
let rval = self.evaluate_expression(scope_idx, &right, loc)?;
match (lval, rval) {
(Value::Int(lint), Value::Int(rint)) => Ok(Value::Bool(lint < rint)),
(Value::Str(lstr), Value::Str(rstr)) => Ok(Value::Bool(lstr < rstr)),
(lother, rother) => Err(InterpreterError::TypeError {
context: "LessThan".to_string(),
conflict: format!("can't test {lother:?} < {rother:?}!"),
location: loc.clone(),
}),
}
}
Expression::LessThanOrEquals { left, right } => {
let lval = self.evaluate_expression(scope_idx, &left, loc)?;
let rval = self.evaluate_expression(scope_idx, &right, loc)?;
match (lval, rval) {
(Value::Int(lint), Value::Int(rint)) => Ok(Value::Bool(lint <= rint)),
(Value::Str(lstr), Value::Str(rstr)) => Ok(Value::Bool(lstr <= rstr)),
(lother, rother) => Err(InterpreterError::TypeError {
context: "LessThanOrEquals".to_string(),
conflict: format!("can't test {lother:?} <= {rother:?}!"),
location: loc.clone(),
}),
}
}
Expression::ListAdd { left, right } => {
let lval = self.evaluate_expression(scope_idx, &left, loc)?;
let rval = self.evaluate_expression(scope_idx, &right, loc)?;