Add Operator token type

This commit is contained in:
Jeff 2024-03-07 05:37:26 -05:00
parent 65d2fd3270
commit 4d76023775
3 changed files with 99 additions and 28 deletions

View File

@ -11,11 +11,56 @@ pub enum Token<'src> {
Float(f64),
String(&'src str),
Identifier(&'src str),
Operator(&'src str),
Operator(Operator),
Control(&'src str),
Keyword(&'src str),
}
#[derive(Clone, Debug, PartialEq)]
pub enum Operator {
Add,
AddAssign,
And,
Assign,
Divide,
Equal,
Greater,
GreaterOrEqual,
Less,
LessOrEqual,
Modulo,
Multiply,
Not,
NotEqual,
Or,
SubAssign,
Subtract,
}
impl Display for Operator {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Operator::Add => write!(f, "+"),
Operator::AddAssign => write!(f, "+="),
Operator::And => write!(f, "&&"),
Operator::Assign => write!(f, "="),
Operator::Divide => write!(f, "="),
Operator::Equal => write!(f, "=="),
Operator::Greater => write!(f, ">"),
Operator::GreaterOrEqual => write!(f, ">="),
Operator::Less => write!(f, "<"),
Operator::LessOrEqual => write!(f, "<="),
Operator::Modulo => write!(f, "%"),
Operator::Multiply => write!(f, "*"),
Operator::Not => write!(f, "!"),
Operator::NotEqual => write!(f, "!="),
Operator::Or => write!(f, "||"),
Operator::SubAssign => write!(f, "-="),
Operator::Subtract => write!(f, "-"),
}
}
}
impl<'src> Display for Token<'src> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
@ -24,7 +69,7 @@ impl<'src> Display for Token<'src> {
Token::Float(float) => write!(f, "{float}"),
Token::String(string) => write!(f, "{string}"),
Token::Identifier(string) => write!(f, "{string}"),
Token::Operator(string) => write!(f, "{string}"),
Token::Operator(operator) => write!(f, "{operator}"),
Token::Control(string) => write!(f, "{string}"),
Token::Keyword(string) => write!(f, "{string}"),
}
@ -88,17 +133,27 @@ pub fn lexer<'src>() -> impl Parser<
let identifier = text::ident().map(|text: &str| Token::Identifier(text));
let operator = choice((
just("==").padded(),
just("!=").padded(),
just(">").padded(),
just("<").padded(),
just(">=").padded(),
just("<=").padded(),
just("&&").padded(),
just("||").padded(),
just("=").padded(),
just("+=").padded(),
just("-=").padded(),
// logic
just("&&").padded().to(Operator::And),
just("==").padded().to(Operator::Equal),
just("!=").padded().to(Operator::NotEqual),
just(">").padded().to(Operator::Greater),
just(">=").padded().to(Operator::GreaterOrEqual),
just("<").padded().to(Operator::Less),
just("<=").padded().to(Operator::LessOrEqual),
just("!").padded().to(Operator::Not),
just("!=").padded().to(Operator::NotEqual),
just("||").padded().to(Operator::Or),
// math
just("+").padded().to(Operator::Add),
just("-").padded().to(Operator::Subtract),
just("*").padded().to(Operator::Multiply),
just("/").padded().to(Operator::Divide),
just("%").padded().to(Operator::Modulo),
// assignment
just("=").padded().to(Operator::Assign),
just("+=").padded().to(Operator::AddAssign),
just("-=").padded().to(Operator::SubAssign),
))
.map(Token::Operator);

View File

@ -2,7 +2,11 @@ use std::{cell::RefCell, collections::HashMap};
use chumsky::{input::SpannedInput, pratt::*, prelude::*};
use crate::{abstract_tree::*, error::Error, lexer::Token};
use crate::{
abstract_tree::*,
error::Error,
lexer::{Operator, Token},
};
pub type DustParser<'src> = Boxed<
'src,
@ -84,33 +88,39 @@ pub fn parser<'src>() -> DustParser<'src> {
.delimited_by(just(Token::Control("(")), just(Token::Control(")"))),
));
use Operator::*;
let logic = atom
.pratt((
prefix(2, just(Token::Operator("!")), |expression| {
prefix(2, just(Token::Operator(Not)), |expression| {
Expression::Logic(Box::new(Logic::Not(expression)))
}),
infix(left(1), just(Token::Operator("==")), |left, right| {
infix(left(1), just(Token::Operator(Equal)), |left, right| {
Expression::Logic(Box::new(Logic::Equal(left, right)))
}),
infix(left(1), just(Token::Operator("!=")), |left, right| {
infix(left(1), just(Token::Operator(NotEqual)), |left, right| {
Expression::Logic(Box::new(Logic::NotEqual(left, right)))
}),
infix(left(1), just(Token::Operator(">")), |left, right| {
infix(left(1), just(Token::Operator(Greater)), |left, right| {
Expression::Logic(Box::new(Logic::Greater(left, right)))
}),
infix(left(1), just(Token::Operator("<")), |left, right| {
infix(left(1), just(Token::Operator(Less)), |left, right| {
Expression::Logic(Box::new(Logic::Less(left, right)))
}),
infix(left(1), just(Token::Operator(">=")), |left, right| {
Expression::Logic(Box::new(Logic::GreaterOrEqual(left, right)))
}),
infix(left(1), just(Token::Operator("<=")), |left, right| {
Expression::Logic(Box::new(Logic::LessOrEqual(left, right)))
}),
infix(left(1), just(Token::Operator("&&")), |left, right| {
infix(
left(1),
just(Token::Operator(GreaterOrEqual)),
|left, right| Expression::Logic(Box::new(Logic::GreaterOrEqual(left, right))),
),
infix(
left(1),
just(Token::Operator(LessOrEqual)),
|left, right| Expression::Logic(Box::new(Logic::LessOrEqual(left, right))),
),
infix(left(1), just(Token::Operator(And)), |left, right| {
Expression::Logic(Box::new(Logic::And(left, right)))
}),
infix(left(1), just(Token::Operator("||")), |left, right| {
infix(left(1), just(Token::Operator(Or)), |left, right| {
Expression::Logic(Box::new(Logic::Or(left, right)))
}),
))
@ -155,7 +165,7 @@ pub fn parser<'src>() -> DustParser<'src> {
let assignment = identifier
.then(type_specification.clone().or_not())
.then_ignore(just(Token::Operator("=")))
.then_ignore(just(Token::Operator(Operator::Assign)))
.then(statement.clone())
.map(|((identifier, r#type), statement)| {
Statement::Assignment(Assignment::new(identifier, r#type, statement))

View File

@ -8,3 +8,9 @@ fn logic() {
Ok(Value::boolean(true))
);
}
#[test]
fn math() {
assert_eq!(interpret("1 + 1"), Ok(Value::integer(2)));
assert_eq!(interpret("21 + 19 + 1 * 2"), Ok(Value::integer(42)));
}