diff --git a/dust-lang/src/parser.rs b/dust-lang/src/parser.rs index bb589a8..9cbd859 100644 --- a/dust-lang/src/parser.rs +++ b/dust-lang/src/parser.rs @@ -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 { // 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) )) ])) );