Add parser mode to pass tests
This commit is contained in:
parent
44d6a88faa
commit
40b5d15b96
@ -125,6 +125,7 @@ pub struct Parser<'src> {
|
|||||||
lexer: Lexer,
|
lexer: Lexer,
|
||||||
current_token: Token<'src>,
|
current_token: Token<'src>,
|
||||||
current_position: Span,
|
current_position: Span,
|
||||||
|
mode: ParserMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> Parser<'src> {
|
impl<'src> Parser<'src> {
|
||||||
@ -138,6 +139,7 @@ impl<'src> Parser<'src> {
|
|||||||
lexer,
|
lexer,
|
||||||
current_token,
|
current_token,
|
||||||
current_position,
|
current_position,
|
||||||
|
mode: ParserMode::Normal,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,6 +359,53 @@ impl<'src> Parser<'src> {
|
|||||||
|
|
||||||
let identifier = Identifier::new(text);
|
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))
|
Ok(Expression::identifier(identifier, start_position))
|
||||||
}
|
}
|
||||||
Token::Integer(text) => {
|
Token::Integer(text) => {
|
||||||
@ -664,51 +713,6 @@ impl<'src> Parser<'src> {
|
|||||||
Expression::field_access(left, field, position)
|
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 => {
|
Token::LeftParenthesis => {
|
||||||
self.next_token()?;
|
self.next_token()?;
|
||||||
|
|
||||||
@ -773,7 +777,12 @@ 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(10)?;
|
self.mode = ParserMode::Condition;
|
||||||
|
|
||||||
|
let condition = self.parse_expression(0)?;
|
||||||
|
|
||||||
|
self.mode = ParserMode::Normal;
|
||||||
|
|
||||||
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 {
|
||||||
@ -884,6 +893,12 @@ impl<'src> Parser<'src> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum ParserMode {
|
||||||
|
Condition,
|
||||||
|
Normal,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum ParseError {
|
pub enum ParseError {
|
||||||
Boolean {
|
Boolean {
|
||||||
@ -1092,19 +1107,19 @@ mod tests {
|
|||||||
Ok(AbstractSyntaxTree::with_statements([
|
Ok(AbstractSyntaxTree::with_statements([
|
||||||
Statement::Expression(Expression::r#struct(
|
Statement::Expression(Expression::r#struct(
|
||||||
StructExpression::Fields {
|
StructExpression::Fields {
|
||||||
name: Node::new(Identifier::new("Foo"), (0, 0)),
|
name: Node::new(Identifier::new("Foo"), (0, 3)),
|
||||||
fields: vec![
|
fields: vec![
|
||||||
(
|
(
|
||||||
Node::new(Identifier::new("a"), (0, 0)),
|
Node::new(Identifier::new("a"), (6, 7)),
|
||||||
Expression::literal(LiteralExpression::Integer(42), (0, 0)),
|
Expression::literal(LiteralExpression::Integer(42), (9, 11)),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Node::new(Identifier::new("b"), (0, 0)),
|
Node::new(Identifier::new("b"), (13, 14)),
|
||||||
Expression::literal(LiteralExpression::Float(4.0), (0, 0))
|
Expression::literal(LiteralExpression::Float(4.0), (16, 19))
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
(0, 0)
|
(0, 21)
|
||||||
))
|
))
|
||||||
]))
|
]))
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user