From f544bd008e28c4057f2376bfd6f93c0fa5124403 Mon Sep 17 00:00:00 2001 From: Jeff Date: Sat, 9 Mar 2024 20:57:46 -0500 Subject: [PATCH] Fix lexing error --- src/lexer.rs | 9 ++-- src/parser.rs | 100 +++++++++++++++++++++++++++++++++------------ tests/functions.rs | 2 +- 3 files changed, 81 insertions(+), 30 deletions(-) diff --git a/src/lexer.rs b/src/lexer.rs index e1fe795..6a96502 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -63,6 +63,7 @@ impl Display for Operator { #[derive(Copy, Clone, Debug, PartialEq)] pub enum Control { + Arrow, CurlyOpen, CurlyClose, SquareOpen, @@ -80,6 +81,7 @@ pub enum Control { impl Display for Control { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { + Control::Arrow => write!(f, "->"), Control::CurlyOpen => write!(f, "{{"), Control::CurlyClose => write!(f, "}}"), Control::SquareOpen => write!(f, "["), @@ -173,10 +175,10 @@ pub fn lexer<'src>() -> impl Parser< 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::Greater), + just("<").padded().to(Operator::Less), just("!").padded().to(Operator::Not), just("!=").padded().to(Operator::NotEqual), just("||").padded().to(Operator::Or), @@ -194,6 +196,7 @@ pub fn lexer<'src>() -> impl Parser< .map(Token::Operator); let control = choice(( + just("->").padded().to(Control::Arrow), just("{").padded().to(Control::CurlyOpen), just("}").padded().to(Control::CurlyClose), just("[").padded().to(Control::SquareOpen), @@ -227,7 +230,7 @@ pub fn lexer<'src>() -> impl Parser< .map(Token::Keyword); choice(( - boolean, float, integer, string, keyword, identifier, operator, control, + boolean, float, integer, string, keyword, identifier, control, operator, )) .map_with(|token, state| (token, state.span())) .padded() diff --git a/src/parser.rs b/src/parser.rs index 1cca56f..9bee5b2 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -66,15 +66,34 @@ pub fn parser<'src>() -> DustParser<'src> { just(Token::Control(Control::ParenOpen)), just(Token::Control(Control::ParenClose)), ) - .then_ignore(just(Token::Control(Control::Colon))) + .then_ignore(just(Token::Control(Control::Arrow))) .then(r#type.clone()) .map(|(parameter_types, return_type)| Type::Function { parameter_types, return_type: Box::new(return_type), }); + let list_of = just(Token::Keyword("list")) + .ignore_then(r#type.clone().delimited_by( + just(Token::Control(Control::ParenOpen)), + just(Token::Control(Control::ParenClose)), + )) + .map(|item_type| Type::ListOf(Box::new(item_type))); + + let list_exact = r#type + .clone() + .separated_by(just(Token::Control(Control::Comma))) + .collect() + .delimited_by( + just(Token::Control(Control::SquareOpen)), + just(Token::Control(Control::SquareClose)), + ) + .map(|types| Type::ListExact(types)); + choice(( function_type, + list_of, + list_exact, just(Token::Keyword("any")).to(Type::Any), just(Token::Keyword("bool")).to(Type::Boolean), just(Token::Keyword("float")).to(Type::Float), @@ -83,32 +102,13 @@ pub fn parser<'src>() -> DustParser<'src> { just(Token::Keyword("range")).to(Type::Range), just(Token::Keyword("str")).to(Type::String), just(Token::Keyword("list")).to(Type::List), + identifier + .clone() + .map(|identifier| Type::Custom(identifier)), )) }); - let type_arguments = r#type.clone().delimited_by( - just(Token::Control(Control::ParenOpen)), - just(Token::Control(Control::ParenClose)), - ); - - just(Token::Control(Control::Colon)).ignore_then(choice(( - r#type - .clone() - .separated_by(just(Token::Control(Control::Comma))) - .collect() - .delimited_by( - just(Token::Control(Control::SquareOpen)), - just(Token::Control(Control::SquareClose)), - ) - .map(|types| Type::ListExact(types)), - just(Token::Keyword("list")) - .then(type_arguments) - .map(|(_, item_type)| Type::ListOf(Box::new(item_type))), - r#type.clone(), - identifier - .clone() - .map(|identifier| Type::Custom(identifier)), - ))) + just(Token::Control(Control::Colon)).ignore_then(r#type) }); let statement = recursive(|statement| { @@ -350,12 +350,12 @@ pub fn parser<'src>() -> DustParser<'src> { .boxed(); choice(( + if_else, assignment, expression_statement, r#break, block_statement, r#loop, - if_else, )) .then_ignore(just(Token::Control(Control::Semicolon)).or_not()) .boxed() @@ -374,6 +374,54 @@ mod tests { use super::*; + #[test] + fn types() { + assert_eq!( + parse(&lex("foobar : bool = true").unwrap()).unwrap()[0].0, + Statement::Assignment(Assignment::new( + Identifier::new("foobar"), + Some(Type::Boolean), + AssignmentOperator::Assign, + Statement::Expression(Expression::Value(ValueNode::Boolean(true))) + )) + ); + assert_eq!( + parse(&lex("foobar : list(bool) = [true]").unwrap()).unwrap()[0].0, + Statement::Assignment(Assignment::new( + Identifier::new("foobar"), + Some(Type::ListOf(Box::new(Type::Boolean))), + AssignmentOperator::Assign, + Statement::Expression(Expression::Value(ValueNode::List(vec![Expression::Value( + ValueNode::Boolean(true) + )]))) + )) + ); + assert_eq!( + parse(&lex("foobar : [bool, str] = [true, '42']").unwrap()).unwrap()[0].0, + Statement::Assignment(Assignment::new( + Identifier::new("foobar"), + Some(Type::ListExact(vec![Type::Boolean, Type::String])), + AssignmentOperator::Assign, + Statement::Expression(Expression::Value(ValueNode::List(vec![ + Expression::Value(ValueNode::Boolean(true)), + Expression::Value(ValueNode::String("42".to_string())) + ]))) + )) + ); + assert_eq!( + parse(&lex("foobar : () -> any = some_function").unwrap()).unwrap()[0].0, + Statement::Assignment(Assignment::new( + Identifier::new("foobar"), + Some(Type::Function { + parameter_types: vec![], + return_type: Box::new(Type::Any) + }), + AssignmentOperator::Assign, + Statement::Expression(Expression::Identifier(Identifier::new("some_function"))) + )) + ); + } + #[test] fn function_call() { assert_eq!( @@ -418,7 +466,7 @@ mod tests { ))]), None )) - ) + ); } #[test] diff --git a/tests/functions.rs b/tests/functions.rs index bd905f6..7cbda53 100644 --- a/tests/functions.rs +++ b/tests/functions.rs @@ -38,7 +38,7 @@ fn callback() { foobar = (cb : () -> str) : str { cb() } - foobar(() : str 'Hiya') + foobar(() : str { 'Hiya' }) ", ), Ok(Some(Value::string("Hiya".to_string())))