Continue passing tests and tweaking

This commit is contained in:
Jeff 2024-08-15 00:20:36 -04:00
parent 81b7888920
commit 486530610b
3 changed files with 320 additions and 191 deletions

View File

@ -16,27 +16,6 @@ pub enum Expression {
} }
impl Expression { impl Expression {
pub fn range(range: Range, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Range(range)),
position,
))
}
pub fn call(call_expression: CallExpression, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Call(call_expression)),
position,
))
}
pub fn field_access(field_access: FieldAccess, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::FieldAccess(field_access)),
position,
))
}
pub fn operator(operator_expression: OperatorExpression, position: Span) -> Self { pub fn operator(operator_expression: OperatorExpression, position: Span) -> Self {
Expression::WithoutBlock(Node::new( Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Operator(operator_expression)), Box::new(ExpressionWithoutBlock::Operator(operator_expression)),
@ -44,9 +23,175 @@ impl Expression {
)) ))
} }
pub fn r#loop(r#loop: Loop, position: Span) -> Self { pub fn range(start: Expression, end: Expression, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Range(Range { start, end })),
position,
))
}
pub fn call(invoker: Expression, arguments: Vec<Expression>, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Call(CallExpression {
invoker,
arguments,
})),
position,
))
}
pub fn field_access(container: Expression, field: Node<Identifier>, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::FieldAccess(FieldAccess {
container,
field,
})),
position,
))
}
pub fn tuple_access(tuple: Expression, index: Node<usize>, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::TupleAccess(TupleAccess {
tuple,
index,
})),
position,
))
}
pub fn assignment(assignee: Expression, value: Expression, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Operator(
OperatorExpression::Assignment { assignee, value },
)),
position,
))
}
pub fn comparison(
left: Expression,
operator: Node<ComparisonOperator>,
right: Expression,
position: Span,
) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Operator(
OperatorExpression::Comparison {
left,
operator,
right,
},
)),
position,
))
}
pub fn compound_assignment(
assignee: Expression,
operator: Node<MathOperator>,
modifier: Expression,
position: Span,
) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Operator(
OperatorExpression::CompoundAssignment {
assignee,
operator,
modifier,
},
)),
position,
))
}
pub fn math(
left: Expression,
operator: Node<MathOperator>,
right: Expression,
position: Span,
) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Operator(OperatorExpression::Math {
left,
operator,
right,
})),
position,
))
}
pub fn negation(expression: Expression, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Operator(
OperatorExpression::Negation(expression),
)),
position,
))
}
pub fn not(expression: Expression, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Operator(OperatorExpression::Not(
expression,
))),
position,
))
}
pub fn logic(
left: Expression,
operator: Node<LogicOperator>,
right: Expression,
position: Span,
) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Operator(
OperatorExpression::Logic {
left,
operator,
right,
},
)),
position,
))
}
pub fn error_propagation(expression: Expression, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Operator(
OperatorExpression::ErrorPropagation(expression),
)),
position,
))
}
pub fn infinite_loop(block: Node<Block>, position: Span) -> Self {
Expression::WithBlock(Node::new( Expression::WithBlock(Node::new(
Box::new(ExpressionWithBlock::Loop(r#loop)), Box::new(ExpressionWithBlock::Loop(Loop::Infinite { block })),
position,
))
}
pub fn while_loop(condition: Expression, block: Node<Block>, position: Span) -> Self {
Expression::WithBlock(Node::new(
Box::new(ExpressionWithBlock::Loop(Loop::While { condition, block })),
position,
))
}
pub fn for_loop(
identifier: Node<Identifier>,
iterator: Expression,
block: Node<Block>,
position: Span,
) -> Self {
Expression::WithBlock(Node::new(
Box::new(ExpressionWithBlock::Loop(Loop::For {
identifier,
iterator,
block,
})),
position, position,
)) ))
} }
@ -168,6 +313,7 @@ pub enum ExpressionWithoutBlock {
FieldAccess(FieldAccess), FieldAccess(FieldAccess),
ListIndex(ListIndex), ListIndex(ListIndex),
Range(Range), Range(Range),
TupleAccess(TupleAccess),
} }
impl Display for ExpressionWithoutBlock { impl Display for ExpressionWithoutBlock {
@ -183,10 +329,23 @@ impl Display for ExpressionWithoutBlock {
ExpressionWithoutBlock::FieldAccess(field_access) => write!(f, "{}", field_access), ExpressionWithoutBlock::FieldAccess(field_access) => write!(f, "{}", field_access),
ExpressionWithoutBlock::ListIndex(list_index) => write!(f, "{}", list_index), ExpressionWithoutBlock::ListIndex(list_index) => write!(f, "{}", list_index),
ExpressionWithoutBlock::Range(range) => write!(f, "{}", range), ExpressionWithoutBlock::Range(range) => write!(f, "{}", range),
ExpressionWithoutBlock::TupleAccess(tuple_access) => write!(f, "{}", tuple_access),
} }
} }
} }
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct TupleAccess {
pub tuple: Expression,
pub index: Node<usize>,
}
impl Display for TupleAccess {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}.{}", self.tuple, self.index)
}
}
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Range { pub struct Range {
pub start: Expression, pub start: Expression,
@ -213,13 +372,13 @@ impl Display for ListIndex {
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct CallExpression { pub struct CallExpression {
pub function: Expression, pub invoker: Expression,
pub arguments: Vec<Expression>, pub arguments: Vec<Expression>,
} }
impl Display for CallExpression { impl Display for CallExpression {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}(", self.function)?; write!(f, "{}(", self.invoker)?;
for (index, argument) in self.arguments.iter().enumerate() { for (index, argument) in self.arguments.iter().enumerate() {
if index > 0 { if index > 0 {
@ -342,7 +501,7 @@ pub enum OperatorExpression {
CompoundAssignment { CompoundAssignment {
assignee: Expression, assignee: Expression,
operator: Node<MathOperator>, operator: Node<MathOperator>,
value: Expression, modifier: Expression,
}, },
ErrorPropagation(Expression), ErrorPropagation(Expression),
Negation(Expression), Negation(Expression),
@ -375,7 +534,7 @@ impl Display for OperatorExpression {
OperatorExpression::CompoundAssignment { OperatorExpression::CompoundAssignment {
assignee, assignee,
operator, operator,
value, modifier: value,
} => write!(f, "{} {}= {}", assignee, operator, value), } => write!(f, "{} {}= {}", assignee, operator, value),
OperatorExpression::ErrorPropagation(expression) => write!(f, "{}?", expression), OperatorExpression::ErrorPropagation(expression) => write!(f, "{}?", expression),
OperatorExpression::Negation(expression) => write!(f, "-{}", expression), OperatorExpression::Negation(expression) => write!(f, "-{}", expression),
@ -552,7 +711,9 @@ impl Display for Block {
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Loop { pub enum Loop {
Infinite(Block), Infinite {
block: Node<Block>,
},
While { While {
condition: Expression, condition: Expression,
block: Node<Block>, block: Node<Block>,
@ -560,14 +721,14 @@ pub enum Loop {
For { For {
identifier: Node<Identifier>, identifier: Node<Identifier>,
iterator: Expression, iterator: Expression,
block: Block, block: Node<Block>,
}, },
} }
impl Display for Loop { impl Display for Loop {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { match self {
Loop::Infinite(block) => write!(f, "loop {}", block), Loop::Infinite { block } => write!(f, "loop {}", block),
Loop::While { condition, block } => write!(f, "while {} {}", condition, block), Loop::While { condition, block } => write!(f, "while {} {}", condition, block),
Loop::For { Loop::For {
identifier, identifier,

View File

@ -298,10 +298,7 @@ impl<'src> Parser<'src> {
let operand = self.parse_expression(0)?; let operand = self.parse_expression(0)?;
let position = (operator_start, self.current_position.1); let position = (operator_start, self.current_position.1);
Ok(Expression::operator( Ok(Expression::not(operand, position))
OperatorExpression::Not(operand),
position,
))
} }
Token::Minus => { Token::Minus => {
self.next_token()?; self.next_token()?;
@ -309,10 +306,7 @@ impl<'src> Parser<'src> {
let operand = self.parse_expression(0)?; let operand = self.parse_expression(0)?;
let position = (operator_start, self.current_position.1); let position = (operator_start, self.current_position.1);
Ok(Expression::operator( Ok(Expression::negation(operand, position))
OperatorExpression::Negation(operand),
position,
))
} }
_ => Err(ParseError::UnexpectedToken { _ => Err(ParseError::UnexpectedToken {
actual: self.current_token.to_owned(), actual: self.current_token.to_owned(),
@ -494,10 +488,7 @@ impl<'src> Parser<'src> {
let block = self.parse_block()?; let block = self.parse_block()?;
let position = (start_position.0, self.current_position.1); let position = (start_position.0, self.current_position.1);
Ok(Expression::r#loop( Ok(Expression::while_loop(condition, block, position))
Loop::While { condition, block },
position,
))
} }
_ => Err(ParseError::UnexpectedToken { _ => Err(ParseError::UnexpectedToken {
actual: self.current_token.to_owned(), actual: self.current_token.to_owned(),
@ -523,13 +514,7 @@ impl<'src> Parser<'src> {
let value = self.parse_expression(operator_precedence)?; let value = self.parse_expression(operator_precedence)?;
let position = (left_start, value.position().1); let position = (left_start, value.position().1);
return Ok(Expression::operator( return Ok(Expression::assignment(left, value, position));
OperatorExpression::Assignment {
assignee: left,
value,
},
position,
));
} }
if let Token::PlusEqual | Token::MinusEqual = &self.current_token { if let Token::PlusEqual | Token::MinusEqual = &self.current_token {
@ -549,22 +534,7 @@ impl<'src> Parser<'src> {
OperatorExpression::CompoundAssignment { OperatorExpression::CompoundAssignment {
assignee: left, assignee: left,
operator, operator,
value, modifier: value,
},
position,
));
}
if let Token::Dot = &self.current_token {
self.next_token()?;
let field = self.parse_identifier()?;
let position = (left_start, self.current_position.1);
return Ok(Expression::field_access(
FieldAccess {
container: left,
field,
}, },
position, position,
)); ));
@ -576,7 +546,7 @@ impl<'src> Parser<'src> {
let end = self.parse_expression(operator_precedence)?; let end = self.parse_expression(operator_precedence)?;
let position = (left_start, end.position().1); let position = (left_start, end.position().1);
return Ok(Expression::range(Range { start: left, end }, position)); return Ok(Expression::range(left, end, position));
} }
if let Token::Minus | Token::Plus | Token::Star | Token::Slash | Token::Percent = if let Token::Minus | Token::Plus | Token::Star | Token::Slash | Token::Percent =
@ -673,6 +643,27 @@ impl<'src> Parser<'src> {
log::trace!("Parsing {} as postfix operator", self.current_token); log::trace!("Parsing {} as postfix operator", self.current_token);
let expression = match &self.current_token { let expression = match &self.current_token {
Token::Dot => {
self.next_token()?;
if let Token::Integer(text) = &self.current_token {
let index = text.parse::<usize>().map_err(|error| ParseError::Integer {
error,
position: self.current_position,
})?;
let index_node = Node::new(index, self.current_position);
let position = (left.position().0, self.current_position.1);
self.next_token()?;
Expression::tuple_access(left, index_node, position)
} else {
let field = self.parse_identifier()?;
let position = (left.position().0, self.current_position.1);
Expression::field_access(left, field, position)
}
}
Token::LeftCurlyBrace => { Token::LeftCurlyBrace => {
let identifier = if let Some(identifier) = left.as_identifier() { let identifier = if let Some(identifier) = left.as_identifier() {
identifier identifier
@ -681,7 +672,6 @@ impl<'src> Parser<'src> {
}; };
let name = Node::new(identifier.clone(), left.position()); let name = Node::new(identifier.clone(), left.position());
let start_left = self.current_position.0;
self.next_token()?; self.next_token()?;
@ -700,7 +690,7 @@ impl<'src> Parser<'src> {
self.next_token()?; self.next_token()?;
} else { } else {
return Err(ParseError::ExpectedToken { return Err(ParseError::ExpectedToken {
expected: TokenKind::Equal, expected: TokenKind::Colon,
actual: self.current_token.to_owned(), actual: self.current_token.to_owned(),
position: self.current_position, position: self.current_position,
}); });
@ -715,7 +705,7 @@ impl<'src> Parser<'src> {
} }
} }
let position = (start_left, self.current_position.1); let position = (left.position().0, self.current_position.1);
Expression::r#struct(StructExpression::Fields { name, fields }, position) Expression::r#struct(StructExpression::Fields { name, fields }, position)
} }
@ -740,17 +730,9 @@ impl<'src> Parser<'src> {
let position = (left.position().0, self.current_position.1); let position = (left.position().0, self.current_position.1);
Expression::call( Expression::call(left, arguments, position)
CallExpression {
function: left,
arguments,
},
position,
)
} }
Token::LeftSquareBrace => { Token::LeftSquareBrace => {
let operator_start = self.current_position.0;
self.next_token()?; self.next_token()?;
let index = self.parse_expression(0)?; let index = self.parse_expression(0)?;
@ -791,7 +773,7 @@ impl<'src> Parser<'src> {
fn parse_if(&mut self) -> Result<If, ParseError> { fn parse_if(&mut self) -> Result<If, ParseError> {
// Assume that the "if" token has already been consumed // Assume that the "if" token has already been consumed
let condition = self.parse_expression(0)?; let condition = self.parse_expression(10)?;
let if_block = self.parse_block()?; let if_block = self.parse_block()?;
if let Token::Else = self.current_token { if let Token::Else = self.current_token {
@ -1071,24 +1053,20 @@ mod tests {
assert_eq!( assert_eq!(
parse(source), parse(source),
Ok(AbstractSyntaxTree::with_statements([ Ok(AbstractSyntaxTree::with_statements([
Statement::Expression(Expression::field_access( Statement::Expression(Expression::tuple_access(
FieldAccess { Expression::call(
container: Expression::call( Expression::identifier(Identifier::new("Foo"), (0, 3)),
CallExpression { vec![
function: Expression::identifier(Identifier::new("Foo"), (0, 0)), Expression::literal(LiteralExpression::Integer(42), (4, 6)),
arguments: vec![ Expression::literal(
Expression::literal(LiteralExpression::Integer(42), (0, 0)), LiteralExpression::String("bar".to_string()),
Expression::literal( (8, 13)
LiteralExpression::String("bar".to_string()), ),
(0, 0) ],
), (0, 15)
], ),
}, Node::new(0, (15, 16)),
(0, 0) (0, 16)
),
field: Node::new(Identifier::new("0"), (0, 0)),
},
(0, 0)
)) ))
])) ]))
); );
@ -1096,7 +1074,12 @@ mod tests {
#[test] #[test]
fn fields_struct_instantiation() { fn fields_struct_instantiation() {
let source = "Foo { a = 42, b = 4.0 }"; let source = "Foo { a: 42, b: 4.0 }";
let mut tree = AbstractSyntaxTree::new();
if parse_into(source, &mut tree).is_err() {
println!("{:?}", tree);
}
assert_eq!( assert_eq!(
parse(source), parse(source),
@ -1130,19 +1113,19 @@ mod tests {
Ok(AbstractSyntaxTree::with_statements([ Ok(AbstractSyntaxTree::with_statements([
Statement::struct_definition( Statement::struct_definition(
StructDefinition::Fields { StructDefinition::Fields {
name: Node::new(Identifier::new("Foo"), (0, 0)), name: Node::new(Identifier::new("Foo"), (7, 10)),
fields: vec![ fields: vec![
( (
Node::new(Identifier::new("a"), (0, 0)), Node::new(Identifier::new("a"), (13, 14)),
Node::new(Type::Integer, (0, 0)) Node::new(Type::Integer, (16, 19))
), ),
( (
Node::new(Identifier::new("b"), (0, 0)), Node::new(Identifier::new("b"), (21, 22)),
Node::new(Type::Float, (0, 0)) Node::new(Type::Float, (24, 29))
) )
] ]
}, },
(0, 0) (0, 31)
) )
])) ]))
); );
@ -1166,13 +1149,11 @@ mod tests {
(0, 22) (0, 22)
), ),
Statement::Expression(Expression::call( Statement::Expression(Expression::call(
CallExpression { Expression::identifier(Identifier::new("Foo"), (23, 26)),
function: Expression::identifier(Identifier::new("Foo"), (23, 26)), vec![
arguments: vec![ Expression::literal(LiteralExpression::Integer(1), (27, 28)),
Expression::literal(LiteralExpression::Integer(1), (27, 28)), Expression::literal(LiteralExpression::Float(2.0), (30, 33))
Expression::literal(LiteralExpression::Float(2.0), (30, 33)) ],
]
},
(23, 34) (23, 34)
)) ))
])) ]))
@ -1230,25 +1211,25 @@ mod tests {
ListIndex { ListIndex {
list: Expression::list( list: Expression::list(
ListExpression::Ordered(vec![ ListExpression::Ordered(vec![
Expression::literal(LiteralExpression::Integer(1), (0, 0)), Expression::literal(LiteralExpression::Integer(1), (1, 2)),
Expression::list( Expression::list(
ListExpression::Ordered(vec![Expression::literal( ListExpression::Ordered(vec![Expression::literal(
LiteralExpression::Integer(2), LiteralExpression::Integer(2),
(0, 0) (5, 6)
)]), )]),
(0, 0) (4, 7)
), ),
Expression::literal(LiteralExpression::Integer(3), (0, 0)), Expression::literal(LiteralExpression::Integer(3), (9, 10)),
]), ]),
(0, 0) (0, 11)
), ),
index: Expression::literal(LiteralExpression::Integer(1), (0, 0)), index: Expression::literal(LiteralExpression::Integer(1), (12, 13)),
}, },
(0, 0) (0, 14)
), ),
index: Expression::literal(LiteralExpression::Integer(0), (0, 0)), index: Expression::literal(LiteralExpression::Integer(0), (15, 16)),
}, },
(0, 0) (0, 17)
)) ))
])) ]))
); );
@ -1262,10 +1243,8 @@ mod tests {
parse(source), parse(source),
Ok(AbstractSyntaxTree::with_statements([ Ok(AbstractSyntaxTree::with_statements([
Statement::Expression(Expression::range( Statement::Expression(Expression::range(
Range { Expression::literal(LiteralExpression::Integer(0), (0, 1)),
start: Expression::literal(LiteralExpression::Integer(0), (0, 1)), Expression::literal(LiteralExpression::Integer(42), (3, 5)),
end: Expression::literal(LiteralExpression::Integer(42), (3, 5)),
},
(0, 5) (0, 5)
)) ))
])) ]))
@ -1478,37 +1457,29 @@ mod tests {
assert_eq!( assert_eq!(
parse(source), parse(source),
Ok(AbstractSyntaxTree::with_statements([ Ok(AbstractSyntaxTree::with_statements([
Statement::Expression(Expression::r#loop( Statement::Expression(Expression::while_loop(
Loop::While { Expression::operator(
condition: Expression::operator( OperatorExpression::Comparison {
OperatorExpression::Comparison { left: Expression::identifier(Identifier::new("x"), (6, 7)),
left: Expression::identifier(Identifier::new("x"), (6, 7)), operator: Node::new(ComparisonOperator::LessThan, (8, 9)),
operator: Node::new(ComparisonOperator::LessThan, (8, 9)), right: Expression::literal(LiteralExpression::Integer(10), (10, 12)),
right: Expression::literal( },
LiteralExpression::Integer(10), (6, 12)
(10, 12) ),
Node::new(
Block::Sync(vec![Statement::Expression(Expression::operator(
OperatorExpression::CompoundAssignment {
assignee: Expression::identifier(Identifier::new("x"), (15, 16)),
operator: Node::new(MathOperator::Add, (17, 19)),
modifier: Expression::literal(
LiteralExpression::Integer(1),
(20, 21)
), ),
}, },
(6, 12) (15, 21)
), ))]),
block: Node::new( (13, 23)
Block::Sync(vec![Statement::Expression(Expression::operator( ),
OperatorExpression::CompoundAssignment {
assignee: Expression::identifier(
Identifier::new("x"),
(15, 16)
),
operator: Node::new(MathOperator::Add, (17, 19)),
value: Expression::literal(
LiteralExpression::Integer(1),
(20, 21)
),
},
(15, 21)
))]),
(13, 23)
)
},
(0, 23) (0, 23)
)) ))
])) ]))
@ -1523,18 +1494,12 @@ mod tests {
parse(source), parse(source),
Ok(AbstractSyntaxTree::with_statements([ Ok(AbstractSyntaxTree::with_statements([
Statement::Expression(Expression::operator( Statement::Expression(Expression::operator(
OperatorExpression::Assignment { OperatorExpression::CompoundAssignment {
assignee: Expression::identifier(Identifier::new("a"), (0, 0)), assignee: Expression::identifier(Identifier::new("a"), (0, 1)),
value: Expression::operator( operator: Node::new(MathOperator::Add, (2, 4)),
OperatorExpression::Math { modifier: Expression::literal(LiteralExpression::Integer(1), (5, 6)),
left: Expression::identifier(Identifier::new("a"), (0, 0)),
operator: Node::new(MathOperator::Add, (0, 0)),
right: Expression::literal(LiteralExpression::Integer(1), (0, 0)),
},
(0, 0)
),
}, },
(0, 0) (0, 6)
)) ))
])) ]))
) )
@ -1569,13 +1534,13 @@ mod tests {
Statement::Expression(Expression::block( Statement::Expression(Expression::block(
Block::Sync(vec![Statement::Expression(Expression::operator( Block::Sync(vec![Statement::Expression(Expression::operator(
OperatorExpression::Math { OperatorExpression::Math {
left: Expression::literal(LiteralExpression::Integer(40), (0, 0)), left: Expression::literal(LiteralExpression::Integer(40), (2, 4)),
operator: Node::new(MathOperator::Add, (0, 0)), operator: Node::new(MathOperator::Add, (5, 6)),
right: Expression::literal(LiteralExpression::Integer(2), (0, 0)), right: Expression::literal(LiteralExpression::Integer(2), (7, 8)),
}, },
(0, 0) (2, 8)
))]), ))]),
(0, 0) (0, 10)
)) ))
])) ]))
) )
@ -1649,10 +1614,10 @@ mod tests {
Statement::Expression(Expression::operator( Statement::Expression(Expression::operator(
OperatorExpression::Math { OperatorExpression::Math {
left: Expression::literal(LiteralExpression::Integer(42), (0, 2)), left: Expression::literal(LiteralExpression::Integer(42), (0, 2)),
operator: Node::new(MathOperator::Divide, (3, 4)), operator: Node::new(MathOperator::Divide, (3, 5)),
right: Expression::literal(LiteralExpression::Integer(2), (5, 6)), right: Expression::literal(LiteralExpression::Integer(2), (6, 8)),
}, },
(0, 6), (0, 8),
)) ))
])) ]))
); );
@ -1687,10 +1652,10 @@ mod tests {
Statement::Expression(Expression::operator( Statement::Expression(Expression::operator(
OperatorExpression::Comparison { OperatorExpression::Comparison {
left: Expression::literal(LiteralExpression::Integer(1), (0, 1)), left: Expression::literal(LiteralExpression::Integer(1), (0, 1)),
operator: Node::new(ComparisonOperator::LessThanOrEqual, (2, 3)), operator: Node::new(ComparisonOperator::LessThanOrEqual, (2, 4)),
right: Expression::literal(LiteralExpression::Integer(2), (4, 5)), right: Expression::literal(LiteralExpression::Integer(2), (5, 6)),
}, },
(0, 5), (0, 6),
)) ))
])) ]))
); );
@ -1706,10 +1671,10 @@ mod tests {
Statement::Expression(Expression::operator( Statement::Expression(Expression::operator(
OperatorExpression::Comparison { OperatorExpression::Comparison {
left: Expression::literal(LiteralExpression::Integer(1), (0, 1)), left: Expression::literal(LiteralExpression::Integer(1), (0, 1)),
operator: Node::new(ComparisonOperator::GreaterThanOrEqual, (2, 3)), operator: Node::new(ComparisonOperator::GreaterThanOrEqual, (2, 4)),
right: Expression::literal(LiteralExpression::Integer(2), (4, 5)), right: Expression::literal(LiteralExpression::Integer(2), (5, 6)),
}, },
(0, 5), (0, 6),
)) ))
])) ]))
); );
@ -1763,7 +1728,7 @@ mod tests {
Statement::Expression(Expression::operator( Statement::Expression(Expression::operator(
OperatorExpression::Math { OperatorExpression::Math {
left: Expression::literal(LiteralExpression::Integer(42), (0, 2)), left: Expression::literal(LiteralExpression::Integer(42), (0, 2)),
operator: Node::new(MathOperator::Divide, (3, 4)), operator: Node::new(MathOperator::Modulo, (3, 4)),
right: Expression::literal(LiteralExpression::Integer(2), (5, 6)), right: Expression::literal(LiteralExpression::Integer(2), (5, 6)),
}, },
(0, 6), (0, 6),
@ -1879,10 +1844,8 @@ mod tests {
parse(source), parse(source),
Ok(AbstractSyntaxTree::with_statements([ Ok(AbstractSyntaxTree::with_statements([
Statement::Expression(Expression::field_access( Statement::Expression(Expression::field_access(
FieldAccess { Expression::identifier(Identifier::new("a"), (0, 1)),
container: Expression::identifier(Identifier::new("a"), (0, 1)), Node::new(Identifier::new("b"), (2, 3)),
field: Node::new(Identifier::new("b"), (2, 3)),
},
(0, 3) (0, 3)
)) ))
])) ]))

View File

@ -238,9 +238,10 @@ impl<'src> Token<'src> {
pub fn precedence(&self) -> u8 { pub fn precedence(&self) -> u8 {
match self { match self {
Token::Dot => 10, Token::Identifier(_) => 10,
Token::LeftParenthesis | Token::LeftSquareBrace => 9, Token::Dot => 9,
Token::Star | Token::Slash | Token::Percent => 8, Token::LeftCurlyBrace | Token::LeftParenthesis | Token::LeftSquareBrace => 8,
Token::Star | Token::Slash | Token::Percent => 7,
Token::Minus | Token::Plus => 6, Token::Minus | Token::Plus => 6,
Token::DoubleEqual Token::DoubleEqual
| Token::Less | Token::Less
@ -249,8 +250,8 @@ impl<'src> Token<'src> {
| Token::GreaterEqual => 5, | Token::GreaterEqual => 5,
Token::DoubleAmpersand => 4, Token::DoubleAmpersand => 4,
Token::DoublePipe => 3, Token::DoublePipe => 3,
Token::Equal | Token::MinusEqual | Token::PlusEqual => 2, Token::DoubleDot => 2,
Token::DoubleDot => 1, Token::Equal | Token::MinusEqual | Token::PlusEqual => 1,
_ => 0, _ => 0,
} }
} }
@ -258,7 +259,8 @@ impl<'src> Token<'src> {
pub fn is_left_associative(&self) -> bool { pub fn is_left_associative(&self) -> bool {
matches!( matches!(
self, self,
Token::DoubleAmpersand Token::Dot
| Token::DoubleAmpersand
| Token::DoublePipe | Token::DoublePipe
| Token::Plus | Token::Plus
| Token::Minus | Token::Minus
@ -269,7 +271,7 @@ impl<'src> Token<'src> {
} }
pub fn is_right_associative(&self) -> bool { pub fn is_right_associative(&self) -> bool {
matches!(self, Token::Equal | Token::PlusEqual) matches!(self, Token::Equal | Token::MinusEqual | Token::PlusEqual)
} }
pub fn is_prefix(&self) -> bool { pub fn is_prefix(&self) -> bool {
@ -277,7 +279,10 @@ impl<'src> Token<'src> {
} }
pub fn is_postfix(&self) -> bool { pub fn is_postfix(&self) -> bool {
matches!(self, Token::LeftParenthesis | Token::LeftSquareBrace) matches!(
self,
Token::Dot | Token::LeftCurlyBrace | Token::LeftParenthesis | Token::LeftSquareBrace
)
} }
} }