Clean up block/map parsing code
This commit is contained in:
parent
9338d73621
commit
9a9d9458ae
@ -156,6 +156,20 @@ impl Statement {
|
|||||||
Statement::While { .. } => None,
|
Statement::While { .. } => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn block_statements_mut(&mut self) -> Option<&mut Vec<Node<Statement>>> {
|
||||||
|
match self {
|
||||||
|
Statement::Block(statements) => Some(statements),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn map_properties_mut(&mut self) -> Option<&mut Vec<(Node<Statement>, Node<Statement>)>> {
|
||||||
|
match self {
|
||||||
|
Statement::Map(properties) => Some(properties),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Statement {
|
impl Display for Statement {
|
||||||
|
@ -313,41 +313,66 @@ impl<'src> Parser<'src> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut statement = None;
|
let first_node = self.parse_statement(0)?;
|
||||||
|
|
||||||
|
// Determine whether the new statement is a block or a map
|
||||||
|
//
|
||||||
|
// If the first node is an assignment, this might be a map
|
||||||
|
let mut statement = if let Statement::BinaryOperation {
|
||||||
|
left,
|
||||||
|
operator:
|
||||||
|
Node {
|
||||||
|
inner: BinaryOperator::Assign,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
right,
|
||||||
|
} = first_node.inner
|
||||||
|
{
|
||||||
|
// If the current token is a comma or closing brace
|
||||||
|
if self.current.0 == Token::Comma || self.current.0 == Token::RightCurlyBrace {
|
||||||
|
// Allow commas after properties
|
||||||
|
if let Token::Comma = self.current.0 {
|
||||||
|
self.next_token()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The new statement is a map
|
||||||
|
Statement::Map(vec![(*left, *right)])
|
||||||
|
} else {
|
||||||
|
// Otherwise, the new statement is a block
|
||||||
|
Statement::Block(vec![Node::new(
|
||||||
|
Statement::BinaryOperation {
|
||||||
|
left,
|
||||||
|
operator: Node::new(BinaryOperator::Assign, (0, 0)),
|
||||||
|
right,
|
||||||
|
},
|
||||||
|
first_node.position,
|
||||||
|
)])
|
||||||
|
}
|
||||||
|
// If the next node is not an assignment, the new statement is a block
|
||||||
|
} else {
|
||||||
|
Statement::Block(vec![first_node])
|
||||||
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// If a closing brace is found, return the new statement
|
// If a closing brace is found, return the new statement
|
||||||
if let (Token::RightCurlyBrace, right_position) = self.current {
|
if let (Token::RightCurlyBrace, right_position) = self.current {
|
||||||
self.next_token()?;
|
self.next_token()?;
|
||||||
|
|
||||||
return Ok(Node::new(
|
return Ok(Node::new(statement, (left_position.0, right_position.1)));
|
||||||
statement.unwrap(),
|
|
||||||
(left_position.0, right_position.1),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let next_node = self.parse_statement(0)?;
|
let next_node = self.parse_statement(0)?;
|
||||||
|
|
||||||
// If the new statement is already a block, add the next node to it
|
// If the new statement is already a block, add the next node to it
|
||||||
if statement
|
if let Some(block_statements) = statement.block_statements_mut() {
|
||||||
.as_ref()
|
block_statements.push(next_node);
|
||||||
.is_some_and(|statement| matches!(statement, Statement::Block(_)))
|
|
||||||
{
|
|
||||||
if let Statement::Block(block) =
|
|
||||||
statement.get_or_insert_with(|| Statement::Block(Vec::new()))
|
|
||||||
{
|
|
||||||
block.push(next_node);
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If the new statement is already a map, expect the next node to be an
|
// If the new statement is already a map
|
||||||
// assignment
|
if let Some(map_properties) = statement.map_properties_mut() {
|
||||||
if statement
|
// Expect the next node to be an assignment
|
||||||
.as_ref()
|
|
||||||
.is_some_and(|statement| matches!(statement, Statement::Map(_)))
|
|
||||||
{
|
|
||||||
if let Statement::BinaryOperation {
|
if let Statement::BinaryOperation {
|
||||||
left,
|
left,
|
||||||
operator:
|
operator:
|
||||||
@ -358,12 +383,10 @@ impl<'src> Parser<'src> {
|
|||||||
right,
|
right,
|
||||||
} = next_node.inner
|
} = next_node.inner
|
||||||
{
|
{
|
||||||
if let Statement::Map(map_properties) =
|
// Add the new property to the map
|
||||||
statement.get_or_insert_with(|| Statement::Map(Vec::new()))
|
|
||||||
{
|
|
||||||
map_properties.push((*left, *right));
|
map_properties.push((*left, *right));
|
||||||
}
|
|
||||||
|
|
||||||
|
// Allow commas after properties
|
||||||
if let Token::Comma = self.current.0 {
|
if let Token::Comma = self.current.0 {
|
||||||
self.next_token()?;
|
self.next_token()?;
|
||||||
}
|
}
|
||||||
@ -373,57 +396,6 @@ impl<'src> Parser<'src> {
|
|||||||
return Err(ParseError::ExpectedAssignment { actual: next_node });
|
return Err(ParseError::ExpectedAssignment { actual: next_node });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the next node is an assignment, this might be a map
|
|
||||||
if let Statement::BinaryOperation {
|
|
||||||
left,
|
|
||||||
operator:
|
|
||||||
Node {
|
|
||||||
inner: BinaryOperator::Assign,
|
|
||||||
..
|
|
||||||
},
|
|
||||||
right,
|
|
||||||
} = next_node.inner
|
|
||||||
{
|
|
||||||
// If the current token is a comma or closing brace
|
|
||||||
if self.current.0 == Token::Comma
|
|
||||||
|| self.current.0 == Token::RightCurlyBrace
|
|
||||||
{
|
|
||||||
// The new statement is a map
|
|
||||||
if let Statement::Map(map_properties) =
|
|
||||||
statement.get_or_insert_with(|| Statement::Map(Vec::new()))
|
|
||||||
{
|
|
||||||
// Add the new property to the map
|
|
||||||
map_properties.push((*left, *right));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow commas after properties
|
|
||||||
if let Token::Comma = self.current.0 {
|
|
||||||
self.next_token()?;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Otherwise, the new statement is a block
|
|
||||||
if let Statement::Block(statements) =
|
|
||||||
statement.get_or_insert_with(|| Statement::Block(Vec::new()))
|
|
||||||
{
|
|
||||||
// Add the assignment statement to the block
|
|
||||||
statements.push(Node::new(
|
|
||||||
Statement::BinaryOperation {
|
|
||||||
left,
|
|
||||||
operator: Node::new(BinaryOperator::Assign, left_position),
|
|
||||||
right,
|
|
||||||
},
|
|
||||||
next_node.position,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Otherwise, the new statement is a block
|
|
||||||
} else if let Statement::Block(statements) =
|
|
||||||
statement.get_or_insert_with(|| Statement::Block(Vec::new()))
|
|
||||||
{
|
|
||||||
// Add the statement to the block
|
|
||||||
statements.push(next_node);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Token::LeftParenthesis, left_position) => {
|
(Token::LeftParenthesis, left_position) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user