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), Float(f64),
String(&'src str), String(&'src str),
Identifier(&'src str), Identifier(&'src str),
Operator(&'src str), Operator(Operator),
Control(&'src str), Control(&'src str),
Keyword(&'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> { impl<'src> Display for Token<'src> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { match self {
@ -24,7 +69,7 @@ impl<'src> Display for Token<'src> {
Token::Float(float) => write!(f, "{float}"), Token::Float(float) => write!(f, "{float}"),
Token::String(string) => write!(f, "{string}"), Token::String(string) => write!(f, "{string}"),
Token::Identifier(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::Control(string) => write!(f, "{string}"),
Token::Keyword(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 identifier = text::ident().map(|text: &str| Token::Identifier(text));
let operator = choice(( let operator = choice((
just("==").padded(), // logic
just("!=").padded(), just("&&").padded().to(Operator::And),
just(">").padded(), just("==").padded().to(Operator::Equal),
just("<").padded(), just("!=").padded().to(Operator::NotEqual),
just(">=").padded(), just(">").padded().to(Operator::Greater),
just("<=").padded(), just(">=").padded().to(Operator::GreaterOrEqual),
just("&&").padded(), just("<").padded().to(Operator::Less),
just("||").padded(), just("<=").padded().to(Operator::LessOrEqual),
just("=").padded(), just("!").padded().to(Operator::Not),
just("+=").padded(), just("!=").padded().to(Operator::NotEqual),
just("-=").padded(), 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); .map(Token::Operator);

View File

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

View File

@ -8,3 +8,9 @@ fn logic() {
Ok(Value::boolean(true)) 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)));
}