Add test; Attempt to clean up map and block parsing
This commit is contained in:
parent
37e3e1116d
commit
24e21aa0b5
@ -85,11 +85,7 @@ impl Statement {
|
|||||||
pub fn expected_type(&self, context: &Context) -> Option<Type> {
|
pub fn expected_type(&self, context: &Context) -> Option<Type> {
|
||||||
match self {
|
match self {
|
||||||
Statement::Block(nodes) => nodes.last().unwrap().inner.expected_type(context),
|
Statement::Block(nodes) => nodes.last().unwrap().inner.expected_type(context),
|
||||||
Statement::BinaryOperation {
|
Statement::BinaryOperation { left, operator, .. } => match operator.inner {
|
||||||
left,
|
|
||||||
operator,
|
|
||||||
right,
|
|
||||||
} => match operator.inner {
|
|
||||||
BinaryOperator::Add
|
BinaryOperator::Add
|
||||||
| BinaryOperator::Divide
|
| BinaryOperator::Divide
|
||||||
| BinaryOperator::Modulo
|
| BinaryOperator::Modulo
|
||||||
|
@ -247,23 +247,57 @@ impl<'src> Parser<'src> {
|
|||||||
statement.get_or_insert_with(|| Statement::Block(Vec::new()))
|
statement.get_or_insert_with(|| Statement::Block(Vec::new()))
|
||||||
{
|
{
|
||||||
block.push(next_node);
|
block.push(next_node);
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the new statement is already a map, expect the next node to be an
|
||||||
|
// assignment
|
||||||
|
if statement
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|statement| matches!(statement, Statement::Map(_)))
|
||||||
|
{
|
||||||
|
if let Statement::BinaryOperation {
|
||||||
|
left,
|
||||||
|
operator:
|
||||||
|
Node {
|
||||||
|
inner: BinaryOperator::Assign,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
right,
|
||||||
|
} = next_node.inner
|
||||||
|
{
|
||||||
|
if let Statement::Map(map_properties) =
|
||||||
|
statement.get_or_insert_with(|| Statement::Map(Vec::new()))
|
||||||
|
{
|
||||||
|
map_properties.push((*left, *right));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Token::Comma = self.current.0 {
|
||||||
|
self.next_token()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
return Err(ParseError::ExpectedAssignment { actual: next_node });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If the next node is an assignment, this might be a map
|
// If the next node is an assignment, this might be a map
|
||||||
} else if let Statement::BinaryOperation {
|
if let Statement::BinaryOperation {
|
||||||
left,
|
left,
|
||||||
operator:
|
operator:
|
||||||
Node {
|
Node {
|
||||||
inner: BinaryOperator::Assign,
|
inner: BinaryOperator::Assign,
|
||||||
position: operator_position,
|
..
|
||||||
},
|
},
|
||||||
right,
|
right,
|
||||||
} = next_node.inner
|
} = next_node.inner
|
||||||
{
|
{
|
||||||
// If the current token is a comma, or the new statement is already a map
|
// If the current token is a comma or closing brace
|
||||||
if self.current.0 == Token::Comma
|
if self.current.0 == Token::Comma
|
||||||
|| statement
|
|| self.current.0 == Token::RightCurlyBrace
|
||||||
.as_ref()
|
|
||||||
.is_some_and(|statement| matches!(statement, Statement::Map(_)))
|
|
||||||
{
|
{
|
||||||
// The new statement is a map
|
// The new statement is a map
|
||||||
if let Statement::Map(map_properties) =
|
if let Statement::Map(map_properties) =
|
||||||
@ -282,14 +316,11 @@ impl<'src> Parser<'src> {
|
|||||||
if let Statement::Block(statements) =
|
if let Statement::Block(statements) =
|
||||||
statement.get_or_insert_with(|| Statement::Block(Vec::new()))
|
statement.get_or_insert_with(|| Statement::Block(Vec::new()))
|
||||||
{
|
{
|
||||||
// Add the statement to the block
|
// Add the assignment statement to the block
|
||||||
statements.push(Node::new(
|
statements.push(Node::new(
|
||||||
Statement::BinaryOperation {
|
Statement::BinaryOperation {
|
||||||
left,
|
left,
|
||||||
operator: Node::new(
|
operator: Node::new(BinaryOperator::Assign, left_position),
|
||||||
BinaryOperator::Assign,
|
|
||||||
operator_position,
|
|
||||||
),
|
|
||||||
right,
|
right,
|
||||||
},
|
},
|
||||||
next_node.position,
|
next_node.position,
|
||||||
@ -565,6 +596,9 @@ pub enum ParseError {
|
|||||||
position: Span,
|
position: Span,
|
||||||
},
|
},
|
||||||
LexError(LexError),
|
LexError(LexError),
|
||||||
|
ExpectedAssignment {
|
||||||
|
actual: Node<Statement>,
|
||||||
|
},
|
||||||
ExpectedIdentifier {
|
ExpectedIdentifier {
|
||||||
actual: TokenOwned,
|
actual: TokenOwned,
|
||||||
position: Span,
|
position: Span,
|
||||||
@ -598,6 +632,7 @@ impl ParseError {
|
|||||||
pub fn position(&self) -> Span {
|
pub fn position(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
ParseError::BooleanError { position, .. } => *position,
|
ParseError::BooleanError { position, .. } => *position,
|
||||||
|
ParseError::ExpectedAssignment { actual } => actual.position,
|
||||||
ParseError::ExpectedIdentifier { position, .. } => *position,
|
ParseError::ExpectedIdentifier { position, .. } => *position,
|
||||||
ParseError::ExpectedToken { position, .. } => *position,
|
ParseError::ExpectedToken { position, .. } => *position,
|
||||||
ParseError::FloatError { position, .. } => *position,
|
ParseError::FloatError { position, .. } => *position,
|
||||||
@ -621,6 +656,7 @@ impl Display for ParseError {
|
|||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::BooleanError { error, .. } => write!(f, "{}", error),
|
Self::BooleanError { error, .. } => write!(f, "{}", error),
|
||||||
|
Self::ExpectedAssignment { .. } => write!(f, "Expected assignment"),
|
||||||
Self::ExpectedIdentifier { actual, .. } => {
|
Self::ExpectedIdentifier { actual, .. } => {
|
||||||
write!(f, "Expected identifier, found {actual}")
|
write!(f, "Expected identifier, found {actual}")
|
||||||
}
|
}
|
||||||
@ -641,6 +677,34 @@ mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn malformed_map() {
|
||||||
|
let input = "{ x = 1, y = 2, z = 3; }";
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
parse(input),
|
||||||
|
Err(ParseError::ExpectedAssignment {
|
||||||
|
actual: Node::new(
|
||||||
|
Statement::Nil(Box::new(Node::new(
|
||||||
|
Statement::BinaryOperation {
|
||||||
|
left: Box::new(Node::new(
|
||||||
|
Statement::Identifier(Identifier::new("z")),
|
||||||
|
(16, 17)
|
||||||
|
)),
|
||||||
|
operator: Node::new(BinaryOperator::Assign, (18, 19)),
|
||||||
|
right: Box::new(Node::new(
|
||||||
|
Statement::Constant(Value::integer(3)),
|
||||||
|
(20, 21)
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
(16, 21)
|
||||||
|
))),
|
||||||
|
(16, 24)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn while_loop() {
|
fn while_loop() {
|
||||||
let input = "while x < 10 { x += 1 }";
|
let input = "while x < 10 { x += 1 }";
|
||||||
|
Loading…
Reference in New Issue
Block a user