From 85d954181bed8630f9ac54076e05a9d9de5f1d11 Mon Sep 17 00:00:00 2001 From: Jeff Date: Thu, 7 Mar 2024 06:57:33 -0500 Subject: [PATCH] Add Control token type --- src/lexer.rs | 58 ++++++++++++++++++++++++++++++++++++++++----------- src/parser.rs | 45 ++++++++++++++++++++++++--------------- 2 files changed, 74 insertions(+), 29 deletions(-) diff --git a/src/lexer.rs b/src/lexer.rs index c2aa7b0..5fc1d81 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -12,7 +12,7 @@ pub enum Token<'src> { String(&'src str), Identifier(&'src str), Operator(Operator), - Control(&'src str), + Control(Control), Keyword(&'src str), } @@ -61,6 +61,39 @@ impl Display for Operator { } } +#[derive(Clone, Debug, PartialEq)] +pub enum Control { + CurlyOpen, + CurlyClose, + SquareOpen, + SquareClose, + ParenOpen, + ParenClose, + Comma, + DoubleColon, + Colon, + Dot, + Semicolon, +} + +impl Display for Control { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + Control::CurlyOpen => write!(f, "{{"), + Control::CurlyClose => write!(f, "}}"), + Control::SquareOpen => write!(f, "["), + Control::SquareClose => write!(f, "]"), + Control::ParenOpen => write!(f, "("), + Control::ParenClose => write!(f, ")"), + Control::Comma => write!(f, ","), + Control::DoubleColon => write!(f, "::"), + Control::Colon => write!(f, ":"), + Control::Dot => write!(f, "."), + Control::Semicolon => write!(f, ";"), + } + } +} + impl<'src> Display for Token<'src> { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { @@ -70,7 +103,7 @@ impl<'src> Display for Token<'src> { Token::String(string) => write!(f, "{string}"), Token::Identifier(string) => write!(f, "{string}"), Token::Operator(operator) => write!(f, "{operator}"), - Token::Control(string) => write!(f, "{string}"), + Token::Control(control) => write!(f, "{control}"), Token::Keyword(string) => write!(f, "{string}"), } } @@ -158,16 +191,17 @@ pub fn lexer<'src>() -> impl Parser< .map(Token::Operator); let control = choice(( - just("[").padded(), - just("]").padded(), - just("(").padded(), - just(")").padded(), - just("{").padded(), - just("}").padded(), - just(",").padded(), - just(";").padded(), - just("::").padded(), - just(":").padded(), + just("{").padded().to(Control::CurlyOpen), + just("}").padded().to(Control::CurlyClose), + just("[").padded().to(Control::SquareOpen), + just("]").padded().to(Control::SquareClose), + just("(").padded().to(Control::ParenOpen), + just(")").padded().to(Control::ParenClose), + just(",").padded().to(Control::Comma), + just(";").padded().to(Control::Semicolon), + just("::").padded().to(Control::DoubleColon), + just(":").padded().to(Control::Colon), + just(".").padded().to(Control::Dot), )) .map(Token::Control); diff --git a/src/parser.rs b/src/parser.rs index d96b609..b195ccd 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -5,7 +5,7 @@ use chumsky::{input::SpannedInput, pratt::*, prelude::*}; use crate::{ abstract_tree::*, error::Error, - lexer::{Operator, Token}, + lexer::{Control, Operator, Token}, }; pub type DustParser<'src> = Boxed< @@ -64,16 +64,19 @@ pub fn parser<'src>() -> DustParser<'src> { let list = expression .clone() - .separated_by(just(Token::Control(","))) + .separated_by(just(Token::Control(Control::Comma))) .allow_trailing() .collect() - .delimited_by(just(Token::Control("[")), just(Token::Control("]"))) + .delimited_by( + just(Token::Control(Control::SquareOpen)), + just(Token::Control(Control::SquareClose)), + ) .map(|list| Expression::Value(ValueNode::List(list))) .boxed(); let r#enum = identifier .clone() - .then_ignore(just(Token::Control("::"))) + .then_ignore(just(Token::Control(Control::DoubleColon))) .then(identifier.clone()) .map(|(name, variant)| Expression::Value(ValueNode::Enum(name, variant))) .boxed(); @@ -83,9 +86,10 @@ pub fn parser<'src>() -> DustParser<'src> { basic_value.clone(), list.clone(), r#enum.clone(), - expression - .clone() - .delimited_by(just(Token::Control("(")), just(Token::Control(")"))), + expression.clone().delimited_by( + just(Token::Control(Control::ParenOpen)), + just(Token::Control(Control::ParenClose)), + ), )); use Operator::*; @@ -165,16 +169,20 @@ pub fn parser<'src>() -> DustParser<'src> { just(Token::Keyword("list")).to(Type::List), )); - let type_arguments = basic_type - .clone() - .delimited_by(just(Token::Control("(")), just(Token::Control(")"))); + let type_arguments = basic_type.clone().delimited_by( + just(Token::Control(Control::ParenOpen)), + just(Token::Control(Control::ParenClose)), + ); - let type_specification = just(Token::Control(":")).ignore_then(choice(( + let type_specification = just(Token::Control(Control::Colon)).ignore_then(choice(( basic_type .clone() - .separated_by(just(Token::Control(","))) + .separated_by(just(Token::Control(Control::Comma))) .collect() - .delimited_by(just(Token::Control("[")), just(Token::Control("]"))) + .delimited_by( + just(Token::Control(Control::SquareOpen)), + just(Token::Control(Control::SquareClose)), + ) .map(|types| Type::ListExact(types)), just(Token::Keyword("list")) .then(type_arguments) @@ -198,7 +206,10 @@ pub fn parser<'src>() -> DustParser<'src> { .clone() .repeated() .collect() - .delimited_by(just(Token::Control("{")), just(Token::Control("}"))) + .delimited_by( + just(Token::Control(Control::CurlyOpen)), + just(Token::Control(Control::CurlyClose)), + ) .map(|statements| Statement::Block(Block::new(statements))) .boxed(); @@ -207,14 +218,14 @@ pub fn parser<'src>() -> DustParser<'src> { .repeated() .collect() .delimited_by( - just(Token::Keyword("loop")).then(just(Token::Control("{"))), - just(Token::Control("}")), + just(Token::Keyword("loop")).then(just(Token::Control(Control::CurlyOpen))), + just(Token::Control(Control::CurlyClose)), ) .map(|statements| Statement::Loop(Loop::new(statements))) .boxed(); choice((assignment, expression_statement, block, r#loop)) - .then_ignore(just(Token::Control(";")).or_not()) + .then_ignore(just(Token::Control(Control::Semicolon)).or_not()) }); statement