format!("Type error: {}\n\tExpected: arithmetic expression\n\tGot: comparison expression", &ctx.source_code[node.start_byte()..node.end_byte()]),
format!("Type error: {}\n\tExpected: arithmetic expression\n\tGot: comparison expression", &ctx.source_code[node.start_byte()..node.end_byte()]),
format!("Type error: {}\n\tExpected: arithmetic expression\n\tGot: comparison expression", &ctx.source_code[node.start_byte()..node.end_byte()]),
// Equality works on any type, typechecking of operands will be handled within parse_binary_expression
"and_expr" | "or_expr" | "implication" | "iff_expr" => parse_binary_expression(ctx, &inner),
let operator_str = &ctx.source_code[operator_node.start_byte()..operator_node.end_byte()];
// The inner context is either Boolean or Arithmetic so the elements of the set/matrix are typechecked correctly.
// looking for the operator node (either '!' at the end or 'factorial' at the start) to add hover info
let operator_str = &ctx.source_code[operator_node.start_byte()..operator_node.end_byte()];
fn require_int_operand(ctx: &mut ParseContext, node: &Node, expr: &Expression) -> bool {