Consolidate token symbols

This commit is contained in:
Jeff 2024-06-20 19:25:46 -04:00
parent a94251e707
commit 880fb7cd1b
4 changed files with 229 additions and 242 deletions

View File

@ -12,7 +12,7 @@ use super::{Block, Evaluate, Evaluation, ExpectedType, Expression, Type, WithPos
pub struct IfElse { pub struct IfElse {
if_expression: Expression, if_expression: Expression,
if_block: WithPosition<Block>, if_block: WithPosition<Block>,
else_ifs: Vec<(Expression, WithPosition<Block>)>, else_ifs: Option<Vec<(Expression, WithPosition<Block>)>>,
else_block: Option<WithPosition<Block>>, else_block: Option<WithPosition<Block>>,
} }
@ -20,7 +20,7 @@ impl IfElse {
pub fn new( pub fn new(
if_expression: Expression, if_expression: Expression,
if_block: WithPosition<Block>, if_block: WithPosition<Block>,
else_ifs: Vec<(Expression, WithPosition<Block>)>, else_ifs: Option<Vec<(Expression, WithPosition<Block>)>>,
else_block: Option<WithPosition<Block>>, else_block: Option<WithPosition<Block>>,
) -> Self { ) -> Self {
Self { Self {
@ -61,26 +61,28 @@ impl Evaluate for IfElse {
}); });
} }
for (expression, block) in &self.else_ifs { if let Some(else_ifs) = &self.else_ifs {
let expression_type = expression.expected_type(context)?; for (expression, block) in else_ifs {
let expression_type = expression.expected_type(context)?;
if let Type::Boolean = expression_type { if let Type::Boolean = expression_type {
block.node.validate(context, manage_memory)?; block.node.validate(context, manage_memory)?;
let actual = block.node.expected_type(context)?; let actual = block.node.expected_type(context)?;
expected_type expected_type.check(&actual).map_err(|conflict| {
.check(&actual) ValidationError::TypeCheck {
.map_err(|conflict| ValidationError::TypeCheck { conflict,
conflict, actual_position: self.if_block.node.last_statement().position(),
actual_position: self.if_block.node.last_statement().position(), expected_position: Some(self.if_expression.position()),
expected_position: Some(self.if_expression.position()), }
})?; })?;
} else { } else {
return Err(ValidationError::ExpectedBoolean { return Err(ValidationError::ExpectedBoolean {
actual: if_expression_type, actual: if_expression_type,
position: self.if_expression.position(), position: self.if_expression.position(),
}); });
}
} }
} }
@ -104,9 +106,11 @@ impl Evaluate for IfElse {
if let ValueInner::Boolean(if_boolean) = value.inner().as_ref() { if let ValueInner::Boolean(if_boolean) = value.inner().as_ref() {
if *if_boolean { if *if_boolean {
self.if_block.node.evaluate(context, _manage_memory) return self.if_block.node.evaluate(context, _manage_memory);
} else { }
for (expression, block) in self.else_ifs {
if let Some(else_ifs) = self.else_ifs {
for (expression, block) in else_ifs {
let expression_position = expression.position(); let expression_position = expression.position();
let action = expression.evaluate(context, _manage_memory)?; let action = expression.evaluate(context, _manage_memory)?;
let value = if let Evaluation::Return(value) = action { let value = if let Evaluation::Return(value) = action {
@ -130,12 +134,12 @@ impl Evaluate for IfElse {
)); ));
} }
} }
}
if let Some(else_statement) = self.else_block { if let Some(else_statement) = self.else_block {
else_statement.node.evaluate(context, _manage_memory) else_statement.node.evaluate(context, _manage_memory)
} else { } else {
Ok(Evaluation::None) Ok(Evaluation::None)
}
} }
} else { } else {
Err(RuntimeError::ValidationFailure( Err(RuntimeError::ValidationFailure(
@ -172,7 +176,7 @@ mod tests {
ValueNode::String("foo".to_string()).with_position((0, 0)) ValueNode::String("foo".to_string()).with_position((0, 0))
))]) ))])
.with_position((0, 0)), .with_position((0, 0)),
Vec::with_capacity(0), Some(Vec::with_capacity(0)),
None None
) )
.evaluate(&mut Context::new(None), true) .evaluate(&mut Context::new(None), true)

View File

@ -15,8 +15,7 @@ pub enum Token<'src> {
Float(f64), Float(f64),
String(&'src str), String(&'src str),
Identifier(&'src str), Identifier(&'src str),
Operator(Operator), Symbol(Symbol),
Control(Control),
Keyword(Keyword), Keyword(Keyword),
} }
@ -29,8 +28,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(operator) => write!(f, "{operator}"), Token::Symbol(control) => write!(f, "{control}"),
Token::Control(control) => write!(f, "{control}"),
Token::Keyword(keyword) => write!(f, "{keyword}"), Token::Keyword(keyword) => write!(f, "{keyword}"),
} }
} }
@ -100,91 +98,80 @@ impl Display for Keyword {
} }
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(Copy, Clone, Debug, PartialEq)]
pub enum Operator { pub enum Symbol {
Add, Plus,
AddAssign, PlusEquals,
And, DoubleAmpersand,
Assign, Colon,
Divide, Comma,
CurlyClose,
CurlyOpen,
Slash,
Dollar,
Dot,
DoubleColon,
DoubleDot,
DoubleEqual,
DoubleUnderscore,
Equal, Equal,
FatArrow,
Greater, Greater,
GreaterOrEqual, GreaterOrEqual,
Less, Less,
LessOrEqual, LessOrEqual,
Modulo, Percent,
Multiply, Asterisk,
Not, Exclamation,
NotEqual, NotEqual,
Or, DoublePipe,
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, "-"),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Control {
CurlyOpen,
CurlyClose,
SquareOpen,
SquareClose,
ParenOpen,
ParenClose, ParenClose,
ParenOpen,
Pipe, Pipe,
Comma,
DoubleColon,
Colon,
Dollar,
Dot,
DoubleDot,
Semicolon, Semicolon,
SkinnyArrow, SkinnyArrow,
FatArrow, SquareClose,
DoubleUnderscore, SquareOpen,
MinusEqual,
Minus,
} }
impl Display for Control { impl Display for Symbol {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self { match self {
Control::CurlyOpen => write!(f, "{{"), Symbol::Asterisk => write!(f, "*"),
Control::CurlyClose => write!(f, "}}"), Symbol::Colon => write!(f, ":"),
Control::Dollar => write!(f, "$"), Symbol::Comma => write!(f, ","),
Control::SquareOpen => write!(f, "["), Symbol::CurlyClose => write!(f, "}}"),
Control::SquareClose => write!(f, "]"), Symbol::CurlyOpen => write!(f, "{{"),
Control::ParenOpen => write!(f, "("), Symbol::Dollar => write!(f, "$"),
Control::ParenClose => write!(f, ")"), Symbol::Dot => write!(f, "."),
Control::Pipe => write!(f, "|"), Symbol::DoubleAmpersand => write!(f, "&&"),
Control::Comma => write!(f, ","), Symbol::DoubleColon => write!(f, "::"),
Control::DoubleColon => write!(f, "::"), Symbol::DoubleDot => write!(f, ".."),
Control::Colon => write!(f, ":"), Symbol::DoubleEqual => write!(f, "=="),
Control::Dot => write!(f, "."), Symbol::DoublePipe => write!(f, "||"),
Control::Semicolon => write!(f, ";"), Symbol::DoubleUnderscore => write!(f, "__"),
Control::DoubleDot => write!(f, ".."), Symbol::Equal => write!(f, "="),
Control::SkinnyArrow => write!(f, "->"), Symbol::Exclamation => write!(f, "!"),
Control::FatArrow => write!(f, "=>"), Symbol::FatArrow => write!(f, "=>"),
Control::DoubleUnderscore => write!(f, "__"), Symbol::Greater => write!(f, ">"),
Symbol::GreaterOrEqual => write!(f, ">="),
Symbol::Less => write!(f, "<"),
Symbol::LessOrEqual => write!(f, "<="),
Symbol::Minus => write!(f, "-"),
Symbol::MinusEqual => write!(f, "-="),
Symbol::NotEqual => write!(f, "!="),
Symbol::ParenClose => write!(f, ")"),
Symbol::ParenOpen => write!(f, "("),
Symbol::Percent => write!(f, "%"),
Symbol::Pipe => write!(f, "|"),
Symbol::Plus => write!(f, "+"),
Symbol::PlusEquals => write!(f, "+="),
Symbol::Semicolon => write!(f, ";"),
Symbol::SkinnyArrow => write!(f, "->"),
Symbol::Slash => write!(f, "/"),
Symbol::SquareClose => write!(f, "]"),
Symbol::SquareOpen => write!(f, "["),
} }
} }
} }
@ -294,51 +281,42 @@ pub fn lexer<'src>() -> impl Parser<
_ => Token::Identifier(text), _ => Token::Identifier(text),
}); });
let operator = choice(( let symbol = choice([
// logic just("!=").to(Token::Symbol(Symbol::NotEqual)),
just("&&").to(Operator::And), just("!").to(Token::Symbol(Symbol::Exclamation)),
just("==").to(Operator::Equal), just("$").to(Token::Symbol(Symbol::Dollar)),
just("!=").to(Operator::NotEqual), just("%").to(Token::Symbol(Symbol::Percent)),
just(">=").to(Operator::GreaterOrEqual), just("&&").to(Token::Symbol(Symbol::DoubleAmpersand)),
just("<=").to(Operator::LessOrEqual), just("(").to(Token::Symbol(Symbol::ParenOpen)),
just(">").to(Operator::Greater), just(")").to(Token::Symbol(Symbol::ParenClose)),
just("<").to(Operator::Less), just("*").to(Token::Symbol(Symbol::Asterisk)),
just("!").to(Operator::Not), just("+=").to(Token::Symbol(Symbol::PlusEquals)),
just("!=").to(Operator::NotEqual), just("+").to(Token::Symbol(Symbol::Plus)),
just("||").to(Operator::Or), just(",").to(Token::Symbol(Symbol::Comma)),
// assignment just("->").to(Token::Symbol(Symbol::SkinnyArrow)),
just("=").to(Operator::Assign), just("-=").to(Token::Symbol(Symbol::MinusEqual)),
just("+=").to(Operator::AddAssign), just("-").to(Token::Symbol(Symbol::Minus)),
just("-=").to(Operator::SubAssign), just("..").to(Token::Symbol(Symbol::DoubleDot)),
// math just(".").to(Token::Symbol(Symbol::Dot)),
just("+").to(Operator::Add), just("/").to(Token::Symbol(Symbol::Slash)),
just("-").to(Operator::Subtract), just("::").to(Token::Symbol(Symbol::DoubleColon)),
just("*").to(Operator::Multiply), just(":").to(Token::Symbol(Symbol::Colon)),
just("/").to(Operator::Divide), just(";").to(Token::Symbol(Symbol::Semicolon)),
just("%").to(Operator::Modulo), just("<=").to(Token::Symbol(Symbol::LessOrEqual)),
)) just("<").to(Token::Symbol(Symbol::Less)),
.map(Token::Operator); just("=>").to(Token::Symbol(Symbol::FatArrow)),
just("==").to(Token::Symbol(Symbol::DoubleEqual)),
let control = choice(( just("=").to(Token::Symbol(Symbol::Equal)),
just("->").to(Control::SkinnyArrow), just(">=").to(Token::Symbol(Symbol::GreaterOrEqual)),
just("=>").to(Control::FatArrow), just(">").to(Token::Symbol(Symbol::Greater)),
just("{").to(Control::CurlyOpen), just("[").to(Token::Symbol(Symbol::SquareOpen)),
just("}").to(Control::CurlyClose), just("]").to(Token::Symbol(Symbol::SquareClose)),
just("[").to(Control::SquareOpen), just("__").to(Token::Symbol(Symbol::DoubleUnderscore)),
just("]").to(Control::SquareClose), just("{").to(Token::Symbol(Symbol::CurlyOpen)),
just("(").to(Control::ParenOpen), just("||").to(Token::Symbol(Symbol::DoublePipe)),
just(")").to(Control::ParenClose), just("|").to(Token::Symbol(Symbol::Pipe)),
just("|").to(Control::Pipe), just("}").to(Token::Symbol(Symbol::CurlyClose)),
just(",").to(Control::Comma), ]);
just(";").to(Control::Semicolon),
just("::").to(Control::DoubleColon),
just(":").to(Control::Colon),
just("..").to(Control::DoubleDot),
just(".").to(Control::Dot),
just("$").to(Control::Dollar),
just("__").to(Control::DoubleUnderscore),
))
.map(Token::Control);
choice(( choice((
line_comment, line_comment,
@ -348,10 +326,9 @@ pub fn lexer<'src>() -> impl Parser<
integer, integer,
string, string,
identifier_and_keyword, identifier_and_keyword,
control, symbol,
operator,
)) ))
.map_with(|token, state| (token, state.span())) .map_with(|token: Token, state| (token, state.span()))
.padded() .padded()
.repeated() .repeated()
.collect() .collect()
@ -427,7 +404,7 @@ mod tests {
lex("1..10").unwrap(), lex("1..10").unwrap(),
vec![ vec![
(Token::Integer(1), (0..1).into()), (Token::Integer(1), (0..1).into()),
(Token::Control(Control::DoubleDot), (1..3).into()), (Token::Symbol(Symbol::DoubleDot), (1..3).into()),
(Token::Integer(10), (3..5).into()) (Token::Integer(10), (3..5).into())
] ]
) )
@ -439,7 +416,7 @@ mod tests {
lex("1 + 1").unwrap(), lex("1 + 1").unwrap(),
vec![ vec![
(Token::Integer(1), (0..1).into()), (Token::Integer(1), (0..1).into()),
(Token::Operator(Operator::Add), (2..3).into()), (Token::Symbol(Symbol::Plus), (2..3).into()),
(Token::Integer(1), (4..5).into()) (Token::Integer(1), (4..5).into())
] ]
) )

View File

@ -9,7 +9,7 @@ use crate::{
abstract_tree::*, abstract_tree::*,
error::DustError, error::DustError,
identifier::Identifier, identifier::Identifier,
lexer::{Control, Keyword, Operator, Token}, lexer::{Keyword, Symbol, Token},
}; };
use self::{ use self::{
@ -96,26 +96,26 @@ pub fn parser<'src>(
.ignore_then( .ignore_then(
positioned_identifier positioned_identifier
.clone() .clone()
.separated_by(just(Token::Control(Control::Comma))) .separated_by(just(Token::Symbol(Symbol::Comma)))
.at_least(1) .at_least(1)
.collect() .collect()
.delimited_by( .delimited_by(
just(Token::Control(Control::Pipe)), just(Token::Symbol(Symbol::Pipe)),
just(Token::Control(Control::Pipe)), just(Token::Symbol(Symbol::Pipe)),
) )
.or_not(), .or_not(),
) )
.then( .then(
type_constructor type_constructor
.clone() .clone()
.separated_by(just(Token::Control(Control::Comma))) .separated_by(just(Token::Symbol(Symbol::Comma)))
.collect() .collect()
.delimited_by( .delimited_by(
just(Token::Control(Control::ParenOpen)), just(Token::Symbol(Symbol::ParenOpen)),
just(Token::Control(Control::ParenClose)), just(Token::Symbol(Symbol::ParenClose)),
), ),
) )
.then_ignore(just(Token::Control(Control::SkinnyArrow))) .then_ignore(just(Token::Symbol(Symbol::SkinnyArrow)))
.then(type_constructor.clone()) .then(type_constructor.clone())
.map_with( .map_with(
|((type_parameters, value_parameters), return_type), state| { |((type_parameters, value_parameters), return_type), state| {
@ -132,11 +132,11 @@ pub fn parser<'src>(
let list_type = type_constructor let list_type = type_constructor
.clone() .clone()
.then_ignore(just(Token::Control(Control::Semicolon))) .then_ignore(just(Token::Symbol(Symbol::Semicolon)))
.then(raw_integer.clone()) .then(raw_integer.clone())
.delimited_by( .delimited_by(
just(Token::Control(Control::SquareOpen)), just(Token::Symbol(Symbol::SquareOpen)),
just(Token::Control(Control::SquareClose)), just(Token::Symbol(Symbol::SquareClose)),
) )
.map_with(|(item_type, length), state| { .map_with(|(item_type, length), state| {
TypeConstructor::List( TypeConstructor::List(
@ -151,8 +151,8 @@ pub fn parser<'src>(
let list_of_type = type_constructor let list_of_type = type_constructor
.clone() .clone()
.delimited_by( .delimited_by(
just(Token::Control(Control::SquareOpen)), just(Token::Symbol(Symbol::SquareOpen)),
just(Token::Control(Control::SquareClose)), just(Token::Symbol(Symbol::SquareClose)),
) )
.map_with(|item_type, state| { .map_with(|item_type, state| {
TypeConstructor::ListOf(Box::new(item_type).with_position(state.span())) TypeConstructor::ListOf(Box::new(item_type).with_position(state.span()))
@ -163,13 +163,13 @@ pub fn parser<'src>(
.then( .then(
type_constructor type_constructor
.clone() .clone()
.separated_by(just(Token::Control(Control::Comma))) .separated_by(just(Token::Symbol(Symbol::Comma)))
.at_least(1) .at_least(1)
.allow_trailing() .allow_trailing()
.collect() .collect()
.delimited_by( .delimited_by(
just(Token::Control(Control::ParenOpen)), just(Token::Symbol(Symbol::ParenOpen)),
just(Token::Control(Control::ParenClose)), just(Token::Symbol(Symbol::ParenClose)),
) )
.or_not(), .or_not(),
) )
@ -190,7 +190,7 @@ pub fn parser<'src>(
}); });
let type_specification = let type_specification =
just(Token::Control(Control::Colon)).ignore_then(type_constructor.clone()); just(Token::Symbol(Symbol::Colon)).ignore_then(type_constructor.clone());
let statement = recursive(|statement| { let statement = recursive(|statement| {
let allow_built_ins = allow_built_ins.clone(); let allow_built_ins = allow_built_ins.clone();
@ -201,8 +201,8 @@ pub fn parser<'src>(
.at_least(1) .at_least(1)
.collect() .collect()
.delimited_by( .delimited_by(
just(Token::Control(Control::CurlyOpen)), just(Token::Symbol(Symbol::CurlyOpen)),
just(Token::Control(Control::CurlyClose)), just(Token::Symbol(Symbol::CurlyClose)),
) )
.map_with(|statements, state| Block::new(statements).with_position(state.span())); .map_with(|statements, state| Block::new(statements).with_position(state.span()));
@ -215,7 +215,7 @@ pub fn parser<'src>(
let range = raw_integer let range = raw_integer
.clone() .clone()
.then_ignore(just(Token::Control(Control::DoubleDot))) .then_ignore(just(Token::Symbol(Symbol::DoubleDot)))
.then(raw_integer) .then(raw_integer)
.map_with(|(start, end), state| { .map_with(|(start, end), state| {
Expression::Value(ValueNode::Range(start..end).with_position(state.span())) Expression::Value(ValueNode::Range(start..end).with_position(state.span()))
@ -223,12 +223,12 @@ pub fn parser<'src>(
let list = expression let list = expression
.clone() .clone()
.separated_by(just(Token::Control(Control::Comma))) .separated_by(just(Token::Symbol(Symbol::Comma)))
.allow_trailing() .allow_trailing()
.collect() .collect()
.delimited_by( .delimited_by(
just(Token::Control(Control::SquareOpen)), just(Token::Symbol(Symbol::SquareOpen)),
just(Token::Control(Control::SquareClose)), just(Token::Symbol(Symbol::SquareClose)),
) )
.map_with(|list, state| { .map_with(|list, state| {
Expression::Value(ValueNode::List(list).with_position(state.span())) Expression::Value(ValueNode::List(list).with_position(state.span()))
@ -237,17 +237,17 @@ pub fn parser<'src>(
let map_fields = identifier let map_fields = identifier
.clone() .clone()
.then(type_specification.clone().or_not()) .then(type_specification.clone().or_not())
.then_ignore(just(Token::Operator(Operator::Assign))) .then_ignore(just(Token::Symbol(Symbol::Equal)))
.then(expression.clone()) .then(expression.clone())
.map(|((identifier, r#type), expression)| (identifier, r#type, expression)); .map(|((identifier, r#type), expression)| (identifier, r#type, expression));
let map = map_fields let map = map_fields
.separated_by(just(Token::Control(Control::Comma)).or_not()) .separated_by(just(Token::Symbol(Symbol::Comma)).or_not())
.allow_trailing() .allow_trailing()
.collect() .collect()
.delimited_by( .delimited_by(
just(Token::Control(Control::CurlyOpen)), just(Token::Symbol(Symbol::CurlyOpen)),
just(Token::Control(Control::CurlyClose)), just(Token::Symbol(Symbol::CurlyClose)),
) )
.map_with(|map_assigment_list, state| { .map_with(|map_assigment_list, state| {
Expression::Value( Expression::Value(
@ -259,30 +259,30 @@ pub fn parser<'src>(
.ignore_then( .ignore_then(
identifier identifier
.clone() .clone()
.separated_by(just(Token::Control(Control::Comma))) .separated_by(just(Token::Symbol(Symbol::Comma)))
.at_least(1) .at_least(1)
.allow_trailing() .allow_trailing()
.collect() .collect()
.delimited_by( .delimited_by(
just(Token::Control(Control::Pipe)), just(Token::Symbol(Symbol::Pipe)),
just(Token::Control(Control::Pipe)), just(Token::Symbol(Symbol::Pipe)),
) )
.or_not(), .or_not(),
) )
.then( .then(
identifier identifier
.clone() .clone()
.then_ignore(just(Token::Control(Control::Colon))) .then_ignore(just(Token::Symbol(Symbol::Colon)))
.then(type_constructor.clone()) .then(type_constructor.clone())
.separated_by(just(Token::Control(Control::Comma))) .separated_by(just(Token::Symbol(Symbol::Comma)))
.allow_trailing() .allow_trailing()
.collect() .collect()
.delimited_by( .delimited_by(
just(Token::Control(Control::ParenOpen)), just(Token::Symbol(Symbol::ParenOpen)),
just(Token::Control(Control::ParenClose)), just(Token::Symbol(Symbol::ParenClose)),
), ),
) )
.then_ignore(just(Token::Control(Control::SkinnyArrow))) .then_ignore(just(Token::Symbol(Symbol::SkinnyArrow)))
.then(type_constructor.clone()) .then(type_constructor.clone())
.then(block.clone()) .then(block.clone())
.map_with( .map_with(
@ -301,16 +301,16 @@ pub fn parser<'src>(
let enum_instance = positioned_identifier let enum_instance = positioned_identifier
.clone() .clone()
.then_ignore(just(Token::Control(Control::DoubleColon))) .then_ignore(just(Token::Symbol(Symbol::DoubleColon)))
.then(positioned_identifier.clone()) .then(positioned_identifier.clone())
.then( .then(
expression expression
.clone() .clone()
.separated_by(just(Token::Control(Control::Comma))) .separated_by(just(Token::Symbol(Symbol::Comma)))
.collect() .collect()
.delimited_by( .delimited_by(
just(Token::Control(Control::ParenOpen)), just(Token::Symbol(Symbol::ParenOpen)),
just(Token::Control(Control::ParenClose)), just(Token::Symbol(Symbol::ParenClose)),
) )
.or_not(), .or_not(),
) )
@ -386,16 +386,16 @@ pub fn parser<'src>(
let turbofish = type_constructor let turbofish = type_constructor
.clone() .clone()
.separated_by(just(Token::Control(Control::Comma))) .separated_by(just(Token::Symbol(Symbol::Comma)))
.at_least(1) .at_least(1)
.collect() .collect()
.delimited_by( .delimited_by(
just(Token::Control(Control::ParenOpen)), just(Token::Symbol(Symbol::ParenOpen)),
just(Token::Control(Control::ParenClose)), just(Token::Symbol(Symbol::ParenClose)),
) )
.delimited_by( .delimited_by(
just(Token::Control(Control::DoubleColon)), just(Token::Symbol(Symbol::DoubleColon)),
just(Token::Control(Control::DoubleColon)), just(Token::Symbol(Symbol::DoubleColon)),
); );
let atom = choice(( let atom = choice((
@ -407,8 +407,8 @@ pub fn parser<'src>(
basic_value.clone(), basic_value.clone(),
identifier_expression.clone(), identifier_expression.clone(),
expression.clone().delimited_by( expression.clone().delimited_by(
just(Token::Control(Control::ParenOpen)), just(Token::Symbol(Symbol::ParenOpen)),
just(Token::Control(Control::ParenClose)), just(Token::Symbol(Symbol::ParenClose)),
), ),
)); ));
@ -416,21 +416,21 @@ pub fn parser<'src>(
// Logic // Logic
prefix( prefix(
2, 2,
just(Token::Operator(Operator::Not)), just(Token::Symbol(Symbol::Exclamation)),
|_, expression, span| { |_, expression, span| {
Expression::Logic(Box::new(Logic::Not(expression)).with_position(span)) Expression::Logic(Box::new(Logic::Not(expression)).with_position(span))
}, },
), ),
infix( infix(
left(1), left(1),
just(Token::Operator(Operator::Equal)), just(Token::Symbol(Symbol::DoubleEqual)),
|left, _, right, span| { |left, _, right, span| {
Expression::Logic(Box::new(Logic::Equal(left, right)).with_position(span)) Expression::Logic(Box::new(Logic::Equal(left, right)).with_position(span))
}, },
), ),
infix( infix(
left(1), left(1),
just(Token::Operator(Operator::NotEqual)), just(Token::Symbol(Symbol::NotEqual)),
|left, _, right, span| { |left, _, right, span| {
Expression::Logic( Expression::Logic(
Box::new(Logic::NotEqual(left, right)).with_position(span), Box::new(Logic::NotEqual(left, right)).with_position(span),
@ -439,21 +439,21 @@ pub fn parser<'src>(
), ),
infix( infix(
left(1), left(1),
just(Token::Operator(Operator::Greater)), just(Token::Symbol(Symbol::Greater)),
|left, _, right, span| { |left, _, right, span| {
Expression::Logic(Box::new(Logic::Greater(left, right)).with_position(span)) Expression::Logic(Box::new(Logic::Greater(left, right)).with_position(span))
}, },
), ),
infix( infix(
left(1), left(1),
just(Token::Operator(Operator::Less)), just(Token::Symbol(Symbol::Less)),
|left, _, right, span| { |left, _, right, span| {
Expression::Logic(Box::new(Logic::Less(left, right)).with_position(span)) Expression::Logic(Box::new(Logic::Less(left, right)).with_position(span))
}, },
), ),
infix( infix(
left(1), left(1),
just(Token::Operator(Operator::GreaterOrEqual)), just(Token::Symbol(Symbol::GreaterOrEqual)),
|left, _, right, span| { |left, _, right, span| {
Expression::Logic( Expression::Logic(
Box::new(Logic::GreaterOrEqual(left, right)).with_position(span), Box::new(Logic::GreaterOrEqual(left, right)).with_position(span),
@ -462,7 +462,7 @@ pub fn parser<'src>(
), ),
infix( infix(
left(1), left(1),
just(Token::Operator(Operator::LessOrEqual)), just(Token::Symbol(Symbol::LessOrEqual)),
|left, _, right, span| { |left, _, right, span| {
Expression::Logic( Expression::Logic(
Box::new(Logic::LessOrEqual(left, right)).with_position(span), Box::new(Logic::LessOrEqual(left, right)).with_position(span),
@ -471,14 +471,14 @@ pub fn parser<'src>(
), ),
infix( infix(
left(1), left(1),
just(Token::Operator(Operator::And)), just(Token::Symbol(Symbol::DoubleAmpersand)),
|left, _, right, span| { |left, _, right, span| {
Expression::Logic(Box::new(Logic::And(left, right)).with_position(span)) Expression::Logic(Box::new(Logic::And(left, right)).with_position(span))
}, },
), ),
infix( infix(
left(1), left(1),
just(Token::Operator(Operator::Or)), just(Token::Symbol(Symbol::DoublePipe)),
|left, _, right, span| { |left, _, right, span| {
Expression::Logic(Box::new(Logic::Or(left, right)).with_position(span)) Expression::Logic(Box::new(Logic::Or(left, right)).with_position(span))
}, },
@ -486,35 +486,35 @@ pub fn parser<'src>(
// Math // Math
infix( infix(
left(1), left(1),
just(Token::Operator(Operator::Add)), just(Token::Symbol(Symbol::Plus)),
|left, _, right, span| { |left, _, right, span| {
Expression::Math(Box::new(Math::Add(left, right)).with_position(span)) Expression::Math(Box::new(Math::Add(left, right)).with_position(span))
}, },
), ),
infix( infix(
left(1), left(1),
just(Token::Operator(Operator::Subtract)), just(Token::Symbol(Symbol::Minus)),
|left, _, right, span| { |left, _, right, span| {
Expression::Math(Box::new(Math::Subtract(left, right)).with_position(span)) Expression::Math(Box::new(Math::Subtract(left, right)).with_position(span))
}, },
), ),
infix( infix(
left(2), left(2),
just(Token::Operator(Operator::Multiply)), just(Token::Symbol(Symbol::Asterisk)),
|left, _, right, span| { |left, _, right, span| {
Expression::Math(Box::new(Math::Multiply(left, right)).with_position(span)) Expression::Math(Box::new(Math::Multiply(left, right)).with_position(span))
}, },
), ),
infix( infix(
left(2), left(2),
just(Token::Operator(Operator::Divide)), just(Token::Symbol(Symbol::Slash)),
|left, _, right, span| { |left, _, right, span| {
Expression::Math(Box::new(Math::Divide(left, right)).with_position(span)) Expression::Math(Box::new(Math::Divide(left, right)).with_position(span))
}, },
), ),
infix( infix(
left(1), left(1),
just(Token::Operator(Operator::Modulo)), just(Token::Symbol(Symbol::Slash)),
|left, _, right, span| { |left, _, right, span| {
Expression::Math(Box::new(Math::Modulo(left, right)).with_position(span)) Expression::Math(Box::new(Math::Modulo(left, right)).with_position(span))
}, },
@ -522,7 +522,7 @@ pub fn parser<'src>(
// Indexes // Indexes
infix( infix(
left(4), left(4),
just(Token::Control(Control::Dot)), just(Token::Symbol(Symbol::Dot)),
|left, _, right, span| { |left, _, right, span| {
Expression::MapIndex( Expression::MapIndex(
Box::new(MapIndex::new(left, right)).with_position(span), Box::new(MapIndex::new(left, right)).with_position(span),
@ -532,8 +532,8 @@ pub fn parser<'src>(
postfix( postfix(
3, 3,
expression.clone().delimited_by( expression.clone().delimited_by(
just(Token::Control(Control::SquareOpen)), just(Token::Symbol(Symbol::SquareOpen)),
just(Token::Control(Control::SquareClose)), just(Token::Symbol(Symbol::SquareClose)),
), ),
|left, right, span| { |left, right, span| {
Expression::ListIndex( Expression::ListIndex(
@ -547,11 +547,11 @@ pub fn parser<'src>(
turbofish.clone().or_not().then( turbofish.clone().or_not().then(
expression expression
.clone() .clone()
.separated_by(just(Token::Control(Control::Comma))) .separated_by(just(Token::Symbol(Symbol::Comma)))
.collect() .collect()
.delimited_by( .delimited_by(
just(Token::Control(Control::ParenOpen)), just(Token::Symbol(Symbol::ParenOpen)),
just(Token::Control(Control::ParenClose)), just(Token::Symbol(Symbol::ParenClose)),
), ),
), ),
|function_expression, (type_parameters, value_parameters), span| { |function_expression, (type_parameters, value_parameters), span| {
@ -596,8 +596,8 @@ pub fn parser<'src>(
let async_block = just(Token::Keyword(Keyword::Async)) let async_block = just(Token::Keyword(Keyword::Async))
.ignore_then(statement.clone().repeated().collect().delimited_by( .ignore_then(statement.clone().repeated().collect().delimited_by(
just(Token::Control(Control::CurlyOpen)), just(Token::Symbol(Symbol::CurlyOpen)),
just(Token::Control(Control::CurlyClose)), just(Token::Symbol(Symbol::CurlyClose)),
)) ))
.map_with(|statements, state| { .map_with(|statements, state| {
Statement::AsyncBlock(AsyncBlock::new(statements).with_position(state.span())) Statement::AsyncBlock(AsyncBlock::new(statements).with_position(state.span()))
@ -610,9 +610,9 @@ pub fn parser<'src>(
.clone() .clone()
.then(type_specification.clone().or_not()) .then(type_specification.clone().or_not())
.then(choice(( .then(choice((
just(Token::Operator(Operator::Assign)).to(AssignmentOperator::Assign), just(Token::Symbol(Symbol::Equal)).to(AssignmentOperator::Assign),
just(Token::Operator(Operator::AddAssign)).to(AssignmentOperator::AddAssign), just(Token::Symbol(Symbol::PlusEquals)).to(AssignmentOperator::AddAssign),
just(Token::Operator(Operator::SubAssign)).to(AssignmentOperator::SubAssign), just(Token::Symbol(Symbol::MinusEqual)).to(AssignmentOperator::SubAssign),
))) )))
.then(statement.clone()) .then(statement.clone())
.map_with(|(((identifier, r#type), operator), statement), state| { .map_with(|(((identifier, r#type), operator), statement), state| {
@ -630,8 +630,8 @@ pub fn parser<'src>(
.at_least(1) .at_least(1)
.collect() .collect()
.delimited_by( .delimited_by(
just(Token::Keyword(Keyword::Loop)).then(just(Token::Control(Control::CurlyOpen))), just(Token::Keyword(Keyword::Loop)).then(just(Token::Symbol(Symbol::CurlyOpen))),
just(Token::Control(Control::CurlyClose)), just(Token::Symbol(Symbol::CurlyClose)),
) )
.map_with(|statements, state| { .map_with(|statements, state| {
Statement::Loop(Loop::new(statements).with_position(state.span())) Statement::Loop(Loop::new(statements).with_position(state.span()))
@ -640,8 +640,8 @@ pub fn parser<'src>(
let r#while = just(Token::Keyword(Keyword::While)) let r#while = just(Token::Keyword(Keyword::While))
.ignore_then(expression.clone()) .ignore_then(expression.clone())
.then(statement.clone().repeated().collect().delimited_by( .then(statement.clone().repeated().collect().delimited_by(
just(Token::Control(Control::CurlyOpen)), just(Token::Symbol(Symbol::CurlyOpen)),
just(Token::Control(Control::CurlyClose)), just(Token::Symbol(Symbol::CurlyClose)),
)) ))
.map_with(|(expression, statements), state| { .map_with(|(expression, statements), state| {
Statement::While(While::new(expression, statements).with_position(state.span())) Statement::While(While::new(expression, statements).with_position(state.span()))
@ -656,7 +656,9 @@ pub fn parser<'src>(
.ignore_then(expression.clone()) .ignore_then(expression.clone())
.then(block.clone()) .then(block.clone())
.repeated() .repeated()
.collect(), .at_least(1)
.collect()
.or_not(),
) )
.then( .then(
just(Token::Keyword(Keyword::Else)) just(Token::Keyword(Keyword::Else))
@ -674,7 +676,7 @@ pub fn parser<'src>(
let type_alias = just(Token::Keyword(Keyword::Type)) let type_alias = just(Token::Keyword(Keyword::Type))
.ignore_then(positioned_identifier.clone()) .ignore_then(positioned_identifier.clone())
.then_ignore(just(Token::Operator(Operator::Assign))) .then_ignore(just(Token::Symbol(Symbol::Equal)))
.then(type_constructor.clone()) .then(type_constructor.clone())
.map_with(|(identifier, constructor), state| { .map_with(|(identifier, constructor), state| {
Statement::TypeAlias( Statement::TypeAlias(
@ -687,11 +689,11 @@ pub fn parser<'src>(
.then( .then(
type_constructor type_constructor
.clone() .clone()
.separated_by(just(Token::Control(Control::Comma))) .separated_by(just(Token::Symbol(Symbol::Comma)))
.collect() .collect()
.delimited_by( .delimited_by(
just(Token::Control(Control::ParenOpen)), just(Token::Symbol(Symbol::ParenOpen)),
just(Token::Control(Control::ParenClose)), just(Token::Symbol(Symbol::ParenClose)),
) )
.or_not(), .or_not(),
) )
@ -705,24 +707,24 @@ pub fn parser<'src>(
.then( .then(
positioned_identifier positioned_identifier
.clone() .clone()
.separated_by(just(Token::Control(Control::Comma))) .separated_by(just(Token::Symbol(Symbol::Comma)))
.allow_trailing() .allow_trailing()
.collect() .collect()
.delimited_by( .delimited_by(
just(Token::Operator(Operator::Less)), just(Token::Symbol(Symbol::Less)),
just(Token::Operator(Operator::Greater)), just(Token::Symbol(Symbol::Greater)),
) )
.or_not(), .or_not(),
) )
.then( .then(
enum_variant enum_variant
.separated_by(just(Token::Control(Control::Comma))) .separated_by(just(Token::Symbol(Symbol::Comma)))
.allow_trailing() .allow_trailing()
.at_least(1) .at_least(1)
.collect() .collect()
.delimited_by( .delimited_by(
just(Token::Control(Control::CurlyOpen)), just(Token::Symbol(Symbol::CurlyOpen)),
just(Token::Control(Control::CurlyClose)), just(Token::Symbol(Symbol::CurlyClose)),
), ),
) )
.map_with(|((name, type_parameters), variants), state| { .map_with(|((name, type_parameters), variants), state| {
@ -751,7 +753,7 @@ pub fn parser<'src>(
type_alias, type_alias,
enum_declaration, enum_declaration,
))) )))
.then_ignore(just(Token::Control(Control::Semicolon)).or_not()) .then_ignore(just(Token::Symbol(Symbol::Semicolon)).or_not())
}); });
statement.repeated().collect() statement.repeated().collect()

View File

@ -587,7 +587,7 @@ fn r#if() {
ValueNode::String("foo".to_string()).with_position((10, 15)) ValueNode::String("foo".to_string()).with_position((10, 15))
))]) ))])
.with_position((8, 17)), .with_position((8, 17)),
Vec::with_capacity(0), None,
None None
) )
.with_position((0, 17)) .with_position((0, 17))
@ -606,7 +606,7 @@ fn if_else() {
ValueNode::String("foo".to_string()).with_position((9, 14)) ValueNode::String("foo".to_string()).with_position((9, 14))
))]) ))])
.with_position((8, 16)), .with_position((8, 16)),
Vec::with_capacity(0), None,
Some( Some(
Block::new(vec![Statement::Expression(Expression::Value( Block::new(vec![Statement::Expression(Expression::Value(
ValueNode::String("bar".to_string()).with_position((24, 29)) ValueNode::String("bar".to_string()).with_position((24, 29))
@ -695,6 +695,10 @@ fn r#loop() {
.with_position((0, 11)) .with_position((0, 11))
) )
); );
}
#[test]
fn complex_loop() {
assert_eq!( assert_eq!(
parse(&lex("loop { if i > 2 { break } else { i += 1 } }").unwrap()).unwrap()[0], parse(&lex("loop { if i > 2 { break } else { i += 1 } }").unwrap()).unwrap()[0],
Statement::Loop( Statement::Loop(
@ -709,7 +713,7 @@ fn r#loop() {
), ),
Block::new(vec![Statement::Break(().with_position((18, 23)))]) Block::new(vec![Statement::Break(().with_position((18, 23)))])
.with_position((16, 25)), .with_position((16, 25)),
Vec::with_capacity(0), None,
Some( Some(
Block::new(vec![Statement::Assignment( Block::new(vec![Statement::Assignment(
Assignment::new( Assignment::new(