89 lines
2.8 KiB
Rust
89 lines
2.8 KiB
Rust
use chumsky::{prelude::*, Parser};
|
|
|
|
use crate::{
|
|
expression::{BinaryOperation, Expression},
|
|
lexer::Token,
|
|
statement::Statement,
|
|
value::Value,
|
|
};
|
|
|
|
fn parser() -> impl Parser<Token, Vec<Statement>, Error = Simple<Token>> {
|
|
let operator = filter_map(|span, a| match a {
|
|
Token::Operator(ref op) => match op.as_str() {
|
|
"+" => Ok(BinaryOperation::Add),
|
|
"-" => Ok(BinaryOperation::Sub),
|
|
"*" => Ok(BinaryOperation::Mul),
|
|
"/" => Ok(BinaryOperation::Div),
|
|
"<" => Ok(BinaryOperation::LessThan),
|
|
">" => Ok(BinaryOperation::GreaterThan),
|
|
"<=" => Ok(BinaryOperation::LessThanOrEqual),
|
|
">=" => Ok(BinaryOperation::GreaterThanOrEqual),
|
|
"==" => Ok(BinaryOperation::Equal),
|
|
"!=" => Ok(BinaryOperation::NotEqual),
|
|
_ => Err(Simple::expected_input_found(span, None, Some(a))),
|
|
},
|
|
_ => Err(Simple::expected_input_found(span, None, Some(a))),
|
|
});
|
|
let tokens = filter_map(|span, a| match a {
|
|
Token::ConstInt(i) => Ok(Expression::Constant(Value::Int(i))),
|
|
Token::ConstFloat(f) => Ok(Expression::Constant(Value::Float(f))),
|
|
Token::ConstString(s) => Ok(Expression::Constant(Value::String(s))),
|
|
Token::ConstBool(b) => Ok(Expression::Constant(Value::Bool(b))),
|
|
Token::ConstChar(c) => Ok(Expression::Constant(Value::Char(c))),
|
|
_ => Err(chumsky::error::Error::expected_input_found(
|
|
span,
|
|
None,
|
|
Some(a),
|
|
)),
|
|
});
|
|
|
|
let expr = recursive(|rec| {
|
|
choice((
|
|
tokens
|
|
.then(operator)
|
|
.then(rec)
|
|
.map(|((a, b), c)| Expression::Binary(Box::new(a), b, Box::new(c))),
|
|
tokens,
|
|
))
|
|
});
|
|
let val = expr.map(Statement::Expression);
|
|
val.repeated()
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use chumsky::Parser;
|
|
|
|
use crate::{
|
|
expression::{BinaryOperation, Expression},
|
|
lexer::Token,
|
|
parser::parser,
|
|
statement::Statement,
|
|
value::Value,
|
|
};
|
|
|
|
#[test]
|
|
fn parse_int() {
|
|
let input = vec![Token::ConstInt(10)];
|
|
let expected = vec![Statement::Expression(Expression::Constant(Value::Int(10)))];
|
|
let result = parser().parse(input).unwrap();
|
|
assert_eq!(result, expected);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_10_plus_10() {
|
|
let input = vec![
|
|
Token::ConstInt(10),
|
|
Token::Operator("+".into()),
|
|
Token::ConstInt(10),
|
|
];
|
|
let expected = vec![Statement::Expression(Expression::Binary(
|
|
Box::new(Expression::Constant(Value::Int(10))),
|
|
BinaryOperation::Add,
|
|
Box::new(Expression::Constant(Value::Int(10))),
|
|
))];
|
|
let result = parser().parse(input).unwrap();
|
|
assert_eq!(result, expected);
|
|
}
|
|
}
|