1
0

Add parser mode to pass tests

This commit is contained in:
Jeff 2024-08-15 21:34:47 -04:00
parent 44d6a88faa
commit 40b5d15b96

View File

@ -125,6 +125,7 @@ pub struct Parser<'src> {
lexer: Lexer,
current_token: Token<'src>,
current_position: Span,
mode: ParserMode,
}
impl<'src> Parser<'src> {
@ -138,6 +139,7 @@ impl<'src> Parser<'src> {
lexer,
current_token,
current_position,
mode: ParserMode::Normal,
}
}
@ -357,6 +359,53 @@ impl<'src> Parser<'src> {
let identifier = Identifier::new(text);
if let ParserMode::Condition = self.mode {
return Ok(Expression::identifier(identifier, start_position));
}
if let Token::LeftCurlyBrace = self.current_token {
let name = Node::new(identifier, start_position);
self.next_token()?;
let mut fields = Vec::new();
loop {
if let Token::RightCurlyBrace = self.current_token {
self.next_token()?;
break;
}
let field_name = self.parse_identifier()?;
if let Token::Colon = self.current_token {
self.next_token()?;
} else {
return Err(ParseError::ExpectedToken {
expected: TokenKind::Colon,
actual: self.current_token.to_owned(),
position: self.current_position,
});
}
let field_value = self.parse_expression(0)?;
fields.push((field_name, field_value));
if let Token::Comma = self.current_token {
self.next_token()?;
}
}
let position = (start_position.0, self.current_position.1);
return Ok(Expression::r#struct(
StructExpression::Fields { name, fields },
position,
));
}
Ok(Expression::identifier(identifier, start_position))
}
Token::Integer(text) => {
@ -664,51 +713,6 @@ impl<'src> Parser<'src> {
Expression::field_access(left, field, position)
}
}
Token::LeftCurlyBrace => {
let identifier = if let Some(identifier) = left.as_identifier() {
identifier
} else {
return Err(ParseError::ExpectedIdentifierNode { actual: left });
};
let name = Node::new(identifier.clone(), left.position());
self.next_token()?;
let mut fields = Vec::new();
loop {
if let Token::RightCurlyBrace = self.current_token {
self.next_token()?;
break;
}
let field_name = self.parse_identifier()?;
if let Token::Colon = self.current_token {
self.next_token()?;
} else {
return Err(ParseError::ExpectedToken {
expected: TokenKind::Colon,
actual: self.current_token.to_owned(),
position: self.current_position,
});
}
let field_value = self.parse_expression(0)?;
fields.push((field_name, field_value));
if let Token::Comma = self.current_token {
self.next_token()?;
}
}
let position = (left.position().0, self.current_position.1);
Expression::r#struct(StructExpression::Fields { name, fields }, position)
}
Token::LeftParenthesis => {
self.next_token()?;
@ -773,7 +777,12 @@ impl<'src> Parser<'src> {
fn parse_if(&mut self) -> Result<If, ParseError> {
// Assume that the "if" token has already been consumed
let condition = self.parse_expression(10)?;
self.mode = ParserMode::Condition;
let condition = self.parse_expression(0)?;
self.mode = ParserMode::Normal;
let if_block = self.parse_block()?;
if let Token::Else = self.current_token {
@ -884,6 +893,12 @@ impl<'src> Parser<'src> {
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum ParserMode {
Condition,
Normal,
}
#[derive(Debug, PartialEq, Clone)]
pub enum ParseError {
Boolean {
@ -1092,19 +1107,19 @@ mod tests {
Ok(AbstractSyntaxTree::with_statements([
Statement::Expression(Expression::r#struct(
StructExpression::Fields {
name: Node::new(Identifier::new("Foo"), (0, 0)),
name: Node::new(Identifier::new("Foo"), (0, 3)),
fields: vec![
(
Node::new(Identifier::new("a"), (0, 0)),
Expression::literal(LiteralExpression::Integer(42), (0, 0)),
Node::new(Identifier::new("a"), (6, 7)),
Expression::literal(LiteralExpression::Integer(42), (9, 11)),
),
(
Node::new(Identifier::new("b"), (0, 0)),
Expression::literal(LiteralExpression::Float(4.0), (0, 0))
Node::new(Identifier::new("b"), (13, 14)),
Expression::literal(LiteralExpression::Float(4.0), (16, 19))
)
]
},
(0, 0)
(0, 21)
))
]))
);