2024-08-09 01:59:09 +00:00
|
|
|
//! Parsing tools.
|
|
|
|
//!
|
|
|
|
//! This module provides two parsing options:
|
|
|
|
//! - `parse` convenience function
|
|
|
|
//! - `Parser` struct, which parses the input a statement at a time
|
2024-08-09 00:58:56 +00:00
|
|
|
use std::{
|
2024-08-09 10:32:44 +00:00
|
|
|
collections::VecDeque,
|
2024-08-09 00:58:56 +00:00
|
|
|
error::Error,
|
|
|
|
fmt::{self, Display, Formatter},
|
2024-08-09 18:01:01 +00:00
|
|
|
num::{ParseFloatError, ParseIntError},
|
|
|
|
str::ParseBoolError,
|
2024-08-09 00:58:56 +00:00
|
|
|
};
|
2024-08-05 04:40:51 +00:00
|
|
|
|
2024-08-07 22:24:25 +00:00
|
|
|
use crate::{
|
2024-08-14 19:52:04 +00:00
|
|
|
abstract_tree::*, DustError, Identifier, LexError, Lexer, Span, Token, TokenKind, TokenOwned,
|
|
|
|
Type,
|
2024-08-07 22:24:25 +00:00
|
|
|
};
|
2024-08-04 00:23:52 +00:00
|
|
|
|
2024-08-07 16:32:18 +00:00
|
|
|
/// Parses the input into an abstract syntax tree.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
/// ```
|
|
|
|
/// # use dust_lang::*;
|
2024-08-13 21:34:45 +00:00
|
|
|
/// let tree = parse("x + 42").unwrap();
|
2024-08-07 16:32:18 +00:00
|
|
|
///
|
|
|
|
/// assert_eq!(
|
2024-08-10 08:29:46 +00:00
|
|
|
/// tree,
|
|
|
|
/// AbstractSyntaxTree {
|
2024-08-07 16:32:18 +00:00
|
|
|
/// nodes: [
|
2024-08-10 08:29:46 +00:00
|
|
|
/// Node::new(
|
|
|
|
/// Statement::BinaryOperation {
|
|
|
|
/// left: Box::new(Node::new(
|
|
|
|
/// Statement::Identifier(Identifier::new("x")),
|
|
|
|
/// (0, 1),
|
|
|
|
/// )),
|
|
|
|
/// operator: Node::new(
|
2024-08-13 21:34:45 +00:00
|
|
|
/// BinaryOperator::Add,
|
2024-08-10 08:29:46 +00:00
|
|
|
/// (2, 3)
|
|
|
|
/// ),
|
|
|
|
/// right: Box::new(Node::new(
|
|
|
|
/// Statement::Constant(Value::integer(42)),
|
|
|
|
/// (4, 6),
|
|
|
|
/// ))
|
2024-08-09 09:18:39 +00:00
|
|
|
/// },
|
2024-08-10 08:29:46 +00:00
|
|
|
/// (0, 6),
|
|
|
|
/// )
|
2024-08-07 16:32:18 +00:00
|
|
|
/// ].into(),
|
2024-08-10 08:29:46 +00:00
|
|
|
/// },
|
2024-08-07 16:32:18 +00:00
|
|
|
/// );
|
|
|
|
/// ```
|
2024-08-11 21:59:52 +00:00
|
|
|
pub fn parse(source: &str) -> Result<AbstractSyntaxTree, DustError> {
|
2024-08-08 20:19:14 +00:00
|
|
|
let lexer = Lexer::new();
|
2024-08-14 19:52:04 +00:00
|
|
|
let mut parser = Parser::new(source, lexer);
|
2024-08-05 04:40:51 +00:00
|
|
|
let mut nodes = VecDeque::new();
|
2024-08-04 23:25:44 +00:00
|
|
|
|
2024-08-05 02:15:31 +00:00
|
|
|
loop {
|
2024-08-11 21:59:52 +00:00
|
|
|
let node = parser
|
2024-08-14 19:52:04 +00:00
|
|
|
.parse_statement()
|
2024-08-11 21:59:52 +00:00
|
|
|
.map_err(|parse_error| DustError::ParseError {
|
|
|
|
parse_error,
|
|
|
|
source,
|
|
|
|
})?;
|
2024-08-04 23:25:44 +00:00
|
|
|
|
2024-08-05 04:40:51 +00:00
|
|
|
nodes.push_back(node);
|
2024-08-05 00:08:43 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
if let Token::Eof = parser.current_token {
|
2024-08-05 02:15:31 +00:00
|
|
|
break;
|
|
|
|
}
|
2024-08-05 00:08:43 +00:00
|
|
|
}
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
Ok(AbstractSyntaxTree { statements: nodes })
|
2024-08-04 00:23:52 +00:00
|
|
|
}
|
|
|
|
|
2024-08-14 01:24:56 +00:00
|
|
|
pub fn parse_into<'src>(
|
|
|
|
source: &'src str,
|
|
|
|
tree: &mut AbstractSyntaxTree,
|
|
|
|
) -> Result<(), DustError<'src>> {
|
|
|
|
let lexer = Lexer::new();
|
2024-08-14 19:52:04 +00:00
|
|
|
let mut parser = Parser::new(source, lexer);
|
2024-08-14 01:24:56 +00:00
|
|
|
|
|
|
|
loop {
|
|
|
|
let node = parser
|
2024-08-14 19:52:04 +00:00
|
|
|
.parse_statement()
|
2024-08-14 01:24:56 +00:00
|
|
|
.map_err(|parse_error| DustError::ParseError {
|
|
|
|
parse_error,
|
|
|
|
source,
|
|
|
|
})?;
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
tree.statements.push_back(node);
|
2024-08-14 01:24:56 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
if let Token::Eof = parser.current_token {
|
2024-08-14 01:24:56 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2024-08-07 16:32:18 +00:00
|
|
|
/// Low-level tool for parsing the input a statement at a time.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
/// ```
|
|
|
|
/// # use std::collections::VecDeque;
|
|
|
|
/// # use dust_lang::*;
|
2024-08-14 19:52:04 +00:00
|
|
|
/// let source = "x = 42";
|
2024-08-08 20:19:14 +00:00
|
|
|
/// let lexer = Lexer::new();
|
|
|
|
/// let mut parser = Parser::new(input, lexer);
|
2024-08-07 16:32:18 +00:00
|
|
|
/// let mut nodes = VecDeque::new();
|
|
|
|
///
|
|
|
|
/// loop {
|
|
|
|
/// let node = parser.parse().unwrap();
|
|
|
|
///
|
|
|
|
/// nodes.push_back(node);
|
|
|
|
///
|
|
|
|
/// if let Token::Eof = parser.current().0 {
|
|
|
|
/// break;
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
///
|
2024-08-13 21:34:45 +00:00
|
|
|
/// let tree = AbstractSyntaxTree { nodes };
|
|
|
|
///
|
2024-08-07 16:32:18 +00:00
|
|
|
/// ```
|
2024-08-14 19:52:04 +00:00
|
|
|
pub struct Parser<'src> {
|
2024-08-08 20:19:14 +00:00
|
|
|
source: &'src str,
|
|
|
|
lexer: Lexer,
|
2024-08-14 18:28:39 +00:00
|
|
|
current_token: Token<'src>,
|
|
|
|
current_position: Span,
|
2024-08-04 00:23:52 +00:00
|
|
|
}
|
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
impl<'src> Parser<'src> {
|
2024-08-08 20:19:14 +00:00
|
|
|
pub fn new(source: &'src str, lexer: Lexer) -> Self {
|
2024-08-04 00:23:52 +00:00
|
|
|
let mut lexer = lexer;
|
2024-08-14 18:28:39 +00:00
|
|
|
let (current_token, current_position) =
|
|
|
|
lexer.next_token(source).unwrap_or((Token::Eof, (0, 0)));
|
2024-08-05 00:08:43 +00:00
|
|
|
|
2024-08-08 20:19:14 +00:00
|
|
|
Parser {
|
|
|
|
source,
|
|
|
|
lexer,
|
2024-08-14 18:28:39 +00:00
|
|
|
current_token,
|
|
|
|
current_position,
|
2024-08-08 20:19:14 +00:00
|
|
|
}
|
2024-08-04 00:23:52 +00:00
|
|
|
}
|
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
pub fn parse_statement(&mut self) -> Result<Statement, ParseError> {
|
|
|
|
let start_position = self.current_position;
|
|
|
|
|
|
|
|
if let Token::Struct = self.current_token {
|
|
|
|
self.next_token()?;
|
|
|
|
|
|
|
|
let (name, name_end) = if let Token::Identifier(_) = self.current_token {
|
|
|
|
let end = self.current_position.1;
|
|
|
|
|
|
|
|
(self.parse_identifier()?, end)
|
|
|
|
} else {
|
|
|
|
return Err(ParseError::ExpectedToken {
|
|
|
|
expected: TokenKind::Identifier,
|
|
|
|
actual: self.current_token.to_owned(),
|
|
|
|
position: self.current_position,
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
if let Token::LeftParenthesis = self.current_token {
|
|
|
|
self.next_token()?;
|
|
|
|
|
|
|
|
let mut types = Vec::new();
|
|
|
|
|
|
|
|
loop {
|
|
|
|
if let Token::RightParenthesis = self.current_token {
|
|
|
|
let position = (start_position.0, self.current_position.1);
|
|
|
|
|
|
|
|
self.next_token()?;
|
|
|
|
|
|
|
|
return Ok(Statement::struct_definition(
|
|
|
|
StructDefinition::Tuple { name, items: types },
|
|
|
|
position,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Token::Comma = self.current_token {
|
|
|
|
self.next_token()?;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
let type_node = self.parse_type()?;
|
|
|
|
|
|
|
|
types.push(type_node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Token::LeftCurlyBrace = self.current_token {
|
|
|
|
self.next_token()?;
|
|
|
|
|
|
|
|
let mut fields = Vec::new();
|
|
|
|
|
|
|
|
loop {
|
|
|
|
if let Token::RightCurlyBrace = self.current_token {
|
|
|
|
let position = (start_position.0, self.current_position.1);
|
|
|
|
|
|
|
|
self.next_token()?;
|
|
|
|
|
|
|
|
return Ok(Statement::struct_definition(
|
|
|
|
StructDefinition::Fields { name, fields },
|
|
|
|
position,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Token::Comma = self.current_token {
|
|
|
|
self.next_token()?;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
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_type = self.parse_type()?;
|
|
|
|
|
|
|
|
fields.push((field_name, field_type));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Ok(Statement::struct_definition(
|
|
|
|
StructDefinition::Unit { name },
|
|
|
|
(start_position.0, name_end),
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
let expression = self.parse_expression(0)?;
|
|
|
|
|
|
|
|
Ok(Statement::Expression(expression))
|
2024-08-10 04:01:50 +00:00
|
|
|
}
|
2024-08-09 05:43:58 +00:00
|
|
|
|
2024-08-10 04:01:50 +00:00
|
|
|
fn next_token(&mut self) -> Result<(), ParseError> {
|
2024-08-14 18:28:39 +00:00
|
|
|
let (token, position) = self.lexer.next_token(self.source)?;
|
|
|
|
|
|
|
|
self.current_token = token;
|
|
|
|
self.current_position = position;
|
2024-08-04 00:23:52 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
fn parse_expression(&mut self, mut precedence: u8) -> Result<Expression, ParseError> {
|
2024-08-12 12:35:08 +00:00
|
|
|
// Parse a statement starting from the current node.
|
2024-08-14 18:28:39 +00:00
|
|
|
let mut left = if self.current_token.is_prefix() {
|
2024-08-12 23:06:57 +00:00
|
|
|
self.parse_prefix()?
|
|
|
|
} else {
|
|
|
|
self.parse_primary()?
|
|
|
|
};
|
2024-08-04 00:23:52 +00:00
|
|
|
|
2024-08-12 12:35:08 +00:00
|
|
|
// While the current token has a higher precedence than the given precedence
|
2024-08-14 18:28:39 +00:00
|
|
|
while precedence < self.current_token.precedence() {
|
2024-08-12 12:35:08 +00:00
|
|
|
// Give precedence to postfix operations
|
2024-08-14 18:28:39 +00:00
|
|
|
left = if self.current_token.is_postfix() {
|
2024-08-12 23:06:57 +00:00
|
|
|
let statement = self.parse_postfix(left)?;
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
precedence = self.current_token.precedence();
|
2024-08-12 23:06:57 +00:00
|
|
|
|
2024-08-14 07:53:15 +00:00
|
|
|
// Replace the left-hand side with the postfix operation
|
2024-08-12 23:06:57 +00:00
|
|
|
statement
|
2024-08-10 04:01:50 +00:00
|
|
|
} else {
|
2024-08-12 12:35:08 +00:00
|
|
|
// Replace the left-hand side with the infix operation
|
2024-08-12 23:06:57 +00:00
|
|
|
self.parse_infix(left)?
|
|
|
|
};
|
2024-08-04 00:23:52 +00:00
|
|
|
}
|
2024-08-10 04:01:50 +00:00
|
|
|
|
|
|
|
Ok(left)
|
2024-08-04 00:23:52 +00:00
|
|
|
}
|
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
fn parse_prefix(&mut self) -> Result<Expression, ParseError> {
|
2024-08-14 18:28:39 +00:00
|
|
|
log::trace!("Parsing {} as prefix operator", self.current_token);
|
2024-08-14 07:53:15 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let operator_start = self.current_position.0;
|
2024-08-14 07:53:15 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
match self.current_token {
|
|
|
|
Token::Bang => {
|
2024-08-12 09:44:05 +00:00
|
|
|
self.next_token()?;
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let operand = self.parse_expression(0)?;
|
|
|
|
let position = (operator_start, self.current_position.1);
|
2024-08-12 09:44:05 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
Ok(Expression::operator(
|
2024-08-14 18:28:39 +00:00
|
|
|
OperatorExpression::Not(operand),
|
|
|
|
position,
|
2024-08-14 19:52:04 +00:00
|
|
|
))
|
2024-08-12 09:44:05 +00:00
|
|
|
}
|
2024-08-14 18:28:39 +00:00
|
|
|
Token::Minus => {
|
2024-08-12 09:44:05 +00:00
|
|
|
self.next_token()?;
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let operand = self.parse_expression(0)?;
|
|
|
|
let position = (operator_start, self.current_position.1);
|
2024-08-12 09:44:05 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
Ok(Expression::operator(
|
2024-08-14 18:28:39 +00:00
|
|
|
OperatorExpression::Negation(operand),
|
|
|
|
position,
|
2024-08-14 19:52:04 +00:00
|
|
|
))
|
2024-08-12 09:44:05 +00:00
|
|
|
}
|
2024-08-12 23:06:57 +00:00
|
|
|
_ => Err(ParseError::UnexpectedToken {
|
2024-08-14 18:28:39 +00:00
|
|
|
actual: self.current_token.to_owned(),
|
|
|
|
position: self.current_position,
|
2024-08-12 23:06:57 +00:00
|
|
|
}),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
fn parse_primary(&mut self) -> Result<Expression, ParseError> {
|
2024-08-14 18:28:39 +00:00
|
|
|
log::trace!("Parsing {} as primary", self.current_token);
|
2024-08-14 07:53:15 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let start_position = self.current_position;
|
2024-08-14 03:45:17 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
match self.current_token {
|
|
|
|
Token::Async => {
|
|
|
|
let block = self.parse_block()?;
|
|
|
|
let position = (start_position.0, self.current_position.1);
|
2024-08-14 03:45:17 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
return Ok(Expression::block(block.inner, position));
|
2024-08-14 03:45:17 +00:00
|
|
|
}
|
2024-08-14 18:28:39 +00:00
|
|
|
Token::Boolean(text) => {
|
2024-08-07 14:50:19 +00:00
|
|
|
self.next_token()?;
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let boolean = text.parse().map_err(|error| ParseError::Boolean {
|
|
|
|
error,
|
|
|
|
position: start_position,
|
|
|
|
})?;
|
|
|
|
let right_end = self.current_position.1;
|
2024-08-14 19:52:04 +00:00
|
|
|
let statement = Expression::literal(
|
2024-08-14 18:28:39 +00:00
|
|
|
LiteralExpression::Boolean(boolean),
|
|
|
|
(start_position.0, right_end),
|
|
|
|
);
|
|
|
|
|
|
|
|
return Ok(statement);
|
2024-08-07 14:50:19 +00:00
|
|
|
}
|
2024-08-14 18:28:39 +00:00
|
|
|
Token::Float(text) => {
|
2024-08-04 00:23:52 +00:00
|
|
|
self.next_token()?;
|
2024-08-05 00:08:43 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let float = text.parse().map_err(|error| ParseError::Float {
|
|
|
|
error,
|
|
|
|
position: start_position,
|
|
|
|
})?;
|
|
|
|
let position = (start_position.0, self.current_position.1);
|
2024-08-09 18:01:01 +00:00
|
|
|
|
2024-08-14 20:07:32 +00:00
|
|
|
Ok(Expression::literal(
|
2024-08-14 18:28:39 +00:00
|
|
|
LiteralExpression::Float(float),
|
2024-08-09 18:01:01 +00:00
|
|
|
position,
|
2024-08-14 20:07:32 +00:00
|
|
|
))
|
2024-08-05 00:08:43 +00:00
|
|
|
}
|
2024-08-14 18:28:39 +00:00
|
|
|
Token::Identifier(text) => {
|
|
|
|
let identifier = Identifier::new(text);
|
|
|
|
let identifier_position = self.current_position;
|
2024-08-13 23:41:36 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
self.next_token()?;
|
2024-08-13 23:41:36 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
if let Token::LeftCurlyBrace = self.current_token {
|
2024-08-13 23:41:36 +00:00
|
|
|
self.next_token()?;
|
|
|
|
|
|
|
|
let mut fields = Vec::new();
|
|
|
|
|
|
|
|
loop {
|
2024-08-14 18:28:39 +00:00
|
|
|
if let Token::RightCurlyBrace = self.current_token {
|
|
|
|
let position = (start_position.0, self.current_position.1);
|
2024-08-13 23:41:36 +00:00
|
|
|
|
|
|
|
self.next_token()?;
|
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
return Ok(Expression::r#struct(
|
2024-08-14 18:28:39 +00:00
|
|
|
StructExpression::Fields {
|
|
|
|
name: Node::new(identifier, identifier_position),
|
2024-08-13 23:41:36 +00:00
|
|
|
fields,
|
|
|
|
},
|
2024-08-14 18:28:39 +00:00
|
|
|
position,
|
2024-08-13 23:41:36 +00:00
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
let field_name = self.parse_identifier()?;
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
if let Token::Colon = self.current_token {
|
2024-08-13 23:41:36 +00:00
|
|
|
self.next_token()?;
|
|
|
|
} else {
|
|
|
|
return Err(ParseError::ExpectedToken {
|
|
|
|
expected: TokenKind::Equal,
|
2024-08-14 18:28:39 +00:00
|
|
|
actual: self.current_token.to_owned(),
|
|
|
|
position: self.current_position,
|
2024-08-13 23:41:36 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let field_value = self.parse_expression(0)?;
|
2024-08-13 23:41:36 +00:00
|
|
|
|
|
|
|
fields.push((field_name, field_value));
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
if let Token::Comma = self.current_token {
|
2024-08-13 23:41:36 +00:00
|
|
|
self.next_token()?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
Ok(Expression::identifier(identifier, identifier_position))
|
2024-08-13 23:41:36 +00:00
|
|
|
}
|
2024-08-14 18:28:39 +00:00
|
|
|
Token::Integer(text) => {
|
2024-08-05 00:08:43 +00:00
|
|
|
self.next_token()?;
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let integer = text.parse::<i64>().map_err(|error| ParseError::Integer {
|
|
|
|
error,
|
|
|
|
position: start_position,
|
|
|
|
})?;
|
2024-08-09 18:01:01 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
if let Token::DoubleDot = self.current_token {
|
2024-08-12 14:08:34 +00:00
|
|
|
self.next_token()?;
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
if let Token::Integer(range_end) = self.current_token {
|
|
|
|
let end_position = self.current_position;
|
2024-08-12 14:08:34 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
self.next_token()?;
|
2024-08-12 14:08:34 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let range_end =
|
|
|
|
range_end
|
|
|
|
.parse::<i64>()
|
|
|
|
.map_err(|error| ParseError::Integer {
|
|
|
|
error,
|
|
|
|
position: end_position,
|
|
|
|
})?;
|
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
Ok(Expression::literal(
|
2024-08-14 18:28:39 +00:00
|
|
|
LiteralExpression::Range(integer, range_end),
|
|
|
|
(start_position.0, end_position.1),
|
2024-08-12 14:08:34 +00:00
|
|
|
))
|
|
|
|
} else {
|
|
|
|
Err(ParseError::ExpectedToken {
|
|
|
|
expected: TokenKind::Integer,
|
2024-08-14 18:28:39 +00:00
|
|
|
actual: self.current_token.to_owned(),
|
|
|
|
position: (start_position.0, self.current_position.1),
|
2024-08-12 14:08:34 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
} else {
|
2024-08-14 19:52:04 +00:00
|
|
|
Ok(Expression::literal(
|
2024-08-14 18:28:39 +00:00
|
|
|
LiteralExpression::Integer(integer),
|
|
|
|
start_position,
|
2024-08-12 14:08:34 +00:00
|
|
|
))
|
|
|
|
}
|
2024-08-04 00:23:52 +00:00
|
|
|
}
|
2024-08-14 18:28:39 +00:00
|
|
|
Token::If => {
|
2024-08-11 18:35:33 +00:00
|
|
|
self.next_token()?;
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let condition = self.parse_expression(0)?;
|
|
|
|
let if_block = self.parse_block()?;
|
|
|
|
let else_block = if let Token::Else = self.current_token {
|
2024-08-11 18:35:33 +00:00
|
|
|
self.next_token()?;
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
Some(self.parse_block()?)
|
2024-08-11 18:35:33 +00:00
|
|
|
} else {
|
2024-08-14 18:28:39 +00:00
|
|
|
None
|
|
|
|
};
|
|
|
|
let position = (start_position.0, self.current_position.1);
|
2024-08-13 23:41:36 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
Ok(Expression::r#if(
|
2024-08-14 18:28:39 +00:00
|
|
|
If {
|
|
|
|
condition,
|
|
|
|
if_block,
|
|
|
|
else_block,
|
|
|
|
},
|
|
|
|
position,
|
|
|
|
))
|
2024-08-11 18:35:33 +00:00
|
|
|
}
|
2024-08-14 18:28:39 +00:00
|
|
|
Token::String(text) => {
|
2024-08-08 17:11:32 +00:00
|
|
|
self.next_token()?;
|
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
Ok(Expression::literal(
|
2024-08-14 18:28:39 +00:00
|
|
|
LiteralExpression::String(text.to_string()),
|
|
|
|
start_position,
|
|
|
|
))
|
2024-08-08 17:11:32 +00:00
|
|
|
}
|
2024-08-14 18:28:39 +00:00
|
|
|
Token::LeftCurlyBrace => {
|
|
|
|
let block_node = self.parse_block()?;
|
2024-08-11 17:16:16 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
Ok(Expression::block(block_node.inner, block_node.position))
|
2024-08-09 10:09:59 +00:00
|
|
|
}
|
2024-08-14 18:28:39 +00:00
|
|
|
Token::LeftParenthesis => {
|
2024-08-04 00:23:52 +00:00
|
|
|
self.next_token()?;
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let node = self.parse_expression(0)?;
|
|
|
|
|
|
|
|
if let Token::RightParenthesis = self.current_token {
|
|
|
|
let position = (start_position.0, self.current_position.1);
|
2024-08-04 00:23:52 +00:00
|
|
|
|
|
|
|
self.next_token()?;
|
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
Ok(Expression::grouped(node, position))
|
2024-08-04 00:23:52 +00:00
|
|
|
} else {
|
2024-08-09 10:09:59 +00:00
|
|
|
Err(ParseError::ExpectedToken {
|
2024-08-12 14:08:34 +00:00
|
|
|
expected: TokenKind::RightParenthesis,
|
2024-08-14 18:28:39 +00:00
|
|
|
actual: self.current_token.to_owned(),
|
|
|
|
position: self.current_position,
|
2024-08-05 01:31:18 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2024-08-14 18:28:39 +00:00
|
|
|
Token::LeftSquareBrace => {
|
2024-08-05 01:31:18 +00:00
|
|
|
self.next_token()?;
|
|
|
|
|
2024-08-14 20:07:32 +00:00
|
|
|
if let Token::RightSquareBrace = self.current_token {
|
|
|
|
let position = (start_position.0, self.current_position.1);
|
|
|
|
|
|
|
|
self.next_token()?;
|
|
|
|
|
|
|
|
return Ok(Expression::list(
|
|
|
|
ListExpression::Ordered(Vec::new()),
|
|
|
|
position,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let first_expression = self.parse_expression(0)?;
|
2024-08-05 01:31:18 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
if let Token::Semicolon = self.current_token {
|
|
|
|
self.next_token()?;
|
2024-08-05 01:31:18 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let repeat_operand = self.parse_expression(0)?;
|
|
|
|
|
|
|
|
if let Token::RightSquareBrace = self.current_token {
|
|
|
|
let position = (start_position.0, self.current_position.1);
|
2024-08-05 01:31:18 +00:00
|
|
|
|
|
|
|
self.next_token()?;
|
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
return Ok(Expression::list(
|
2024-08-14 18:28:39 +00:00
|
|
|
ListExpression::AutoFill {
|
|
|
|
length_operand: first_expression,
|
|
|
|
repeat_operand,
|
|
|
|
},
|
|
|
|
position,
|
|
|
|
));
|
|
|
|
} else {
|
|
|
|
return Err(ParseError::ExpectedToken {
|
|
|
|
expected: TokenKind::RightSquareBrace,
|
|
|
|
actual: self.current_token.to_owned(),
|
|
|
|
position: self.current_position,
|
|
|
|
});
|
2024-08-05 01:31:18 +00:00
|
|
|
}
|
2024-08-07 22:43:24 +00:00
|
|
|
}
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let mut expressions = vec![first_expression];
|
2024-08-07 22:43:24 +00:00
|
|
|
|
2024-08-08 17:49:40 +00:00
|
|
|
loop {
|
2024-08-14 18:28:39 +00:00
|
|
|
if let Token::RightSquareBrace = self.current_token {
|
|
|
|
let position = (start_position.0, self.current_position.1);
|
|
|
|
|
2024-08-08 17:49:40 +00:00
|
|
|
self.next_token()?;
|
2024-08-14 18:28:39 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
return Ok(Expression::list(
|
2024-08-14 18:28:39 +00:00
|
|
|
ListExpression::Ordered(expressions),
|
|
|
|
position,
|
|
|
|
));
|
2024-08-08 17:49:40 +00:00
|
|
|
}
|
2024-08-07 22:43:24 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
if let Token::Comma = self.current_token {
|
2024-08-08 17:49:40 +00:00
|
|
|
self.next_token()?;
|
2024-08-14 18:28:39 +00:00
|
|
|
|
2024-08-08 17:49:40 +00:00
|
|
|
continue;
|
|
|
|
}
|
2024-08-07 22:43:24 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let expression = self.parse_expression(0)?;
|
2024-08-07 22:43:24 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
expressions.push(expression);
|
2024-08-14 07:53:15 +00:00
|
|
|
}
|
|
|
|
}
|
2024-08-14 18:28:39 +00:00
|
|
|
Token::While => {
|
2024-08-13 17:54:16 +00:00
|
|
|
self.next_token()?;
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let condition = self.parse_expression(0)?;
|
|
|
|
let block = self.parse_block()?;
|
|
|
|
let position = (start_position.0, self.current_position.1);
|
2024-08-10 09:23:43 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
Ok(Expression::r#loop(
|
2024-08-14 18:28:39 +00:00
|
|
|
Loop::While { condition, block },
|
|
|
|
position,
|
2024-08-10 09:23:43 +00:00
|
|
|
))
|
|
|
|
}
|
2024-08-09 04:49:17 +00:00
|
|
|
_ => Err(ParseError::UnexpectedToken {
|
2024-08-14 18:28:39 +00:00
|
|
|
actual: self.current_token.to_owned(),
|
|
|
|
position: self.current_position,
|
2024-08-09 04:49:17 +00:00
|
|
|
}),
|
2024-08-04 00:23:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
fn parse_infix(&mut self, left: Expression) -> Result<Expression, ParseError> {
|
2024-08-14 18:28:39 +00:00
|
|
|
log::trace!("Parsing {} as infix operator", self.current_token);
|
2024-08-14 07:53:15 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let operator_precedence = self.current_token.precedence()
|
|
|
|
- if self.current_token.is_right_associative() {
|
2024-08-12 15:24:24 +00:00
|
|
|
1
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
};
|
2024-08-14 18:28:39 +00:00
|
|
|
let left_start = left.position().0;
|
2024-08-13 21:34:45 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
if let Token::Equal = &self.current_token {
|
2024-08-13 21:34:45 +00:00
|
|
|
self.next_token()?;
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let value = self.parse_expression(operator_precedence)?;
|
|
|
|
let position = (left_start, value.position().1);
|
2024-08-13 21:34:45 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
return Ok(Expression::operator(
|
2024-08-14 18:28:39 +00:00
|
|
|
OperatorExpression::Assignment {
|
|
|
|
assignee: left,
|
|
|
|
value,
|
2024-08-13 21:34:45 +00:00
|
|
|
},
|
2024-08-14 18:28:39 +00:00
|
|
|
position,
|
2024-08-13 21:34:45 +00:00
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
if let Token::PlusEqual | Token::MinusEqual = &self.current_token {
|
|
|
|
let math_operator = match self.current_token {
|
|
|
|
Token::PlusEqual => MathOperator::Add,
|
|
|
|
Token::MinusEqual => MathOperator::Subtract,
|
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
|
|
|
let operator = Node::new(math_operator, self.current_position);
|
2024-08-12 19:02:04 +00:00
|
|
|
|
2024-08-09 22:14:46 +00:00
|
|
|
self.next_token()?;
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let value = self.parse_expression(operator_precedence)?;
|
|
|
|
let position = (left_start, value.position().1);
|
2024-08-12 01:37:44 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
return Ok(Expression::operator(
|
2024-08-14 18:28:39 +00:00
|
|
|
OperatorExpression::CompoundAssignment {
|
|
|
|
assignee: left,
|
|
|
|
operator,
|
|
|
|
value,
|
|
|
|
},
|
|
|
|
position,
|
|
|
|
));
|
|
|
|
}
|
2024-08-12 01:37:44 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
if let Token::Dot = &self.current_token {
|
|
|
|
self.next_token()?;
|
2024-08-12 01:37:44 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let field = self.parse_identifier()?;
|
|
|
|
let position = (left_start, self.current_position.1);
|
2024-08-12 01:37:44 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
return Ok(Expression::field_access(
|
2024-08-14 18:28:39 +00:00
|
|
|
FieldAccess {
|
|
|
|
container: left,
|
|
|
|
field,
|
2024-08-12 19:02:04 +00:00
|
|
|
},
|
2024-08-14 18:28:39 +00:00
|
|
|
position,
|
2024-08-09 22:14:46 +00:00
|
|
|
));
|
2024-08-10 04:01:50 +00:00
|
|
|
}
|
2024-08-09 18:01:01 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let math_operator = match &self.current_token {
|
|
|
|
Token::Minus => Node::new(MathOperator::Subtract, self.current_position),
|
|
|
|
Token::Plus => Node::new(MathOperator::Add, self.current_position),
|
|
|
|
Token::Star => Node::new(MathOperator::Multiply, self.current_position),
|
|
|
|
Token::Slash => Node::new(MathOperator::Divide, self.current_position),
|
|
|
|
Token::Percent => Node::new(MathOperator::Modulo, self.current_position),
|
2024-08-09 18:01:01 +00:00
|
|
|
_ => {
|
|
|
|
return Err(ParseError::UnexpectedToken {
|
2024-08-14 18:28:39 +00:00
|
|
|
actual: self.current_token.to_owned(),
|
|
|
|
position: self.current_position,
|
2024-08-09 18:01:01 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
self.next_token()?;
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let right = self.parse_expression(operator_precedence)?;
|
|
|
|
let position = (left_start, right.position().1);
|
2024-08-09 18:01:01 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
Ok(Expression::operator(
|
2024-08-14 18:28:39 +00:00
|
|
|
OperatorExpression::Math {
|
|
|
|
left,
|
|
|
|
operator: math_operator,
|
|
|
|
right,
|
2024-08-09 18:01:01 +00:00
|
|
|
},
|
2024-08-14 18:28:39 +00:00
|
|
|
position,
|
2024-08-09 18:01:01 +00:00
|
|
|
))
|
|
|
|
}
|
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
fn parse_postfix(&mut self, left: Expression) -> Result<Expression, ParseError> {
|
2024-08-14 18:28:39 +00:00
|
|
|
log::trace!("Parsing {} as postfix operator", self.current_token);
|
2024-08-14 07:53:15 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let statement = match &self.current_token {
|
2024-08-13 20:21:44 +00:00
|
|
|
Token::LeftParenthesis => {
|
|
|
|
self.next_token()?;
|
2024-08-09 22:14:46 +00:00
|
|
|
|
2024-08-13 20:21:44 +00:00
|
|
|
let mut arguments = Vec::new();
|
2024-08-12 20:57:10 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
while self.current_token != Token::RightParenthesis {
|
|
|
|
let argument = self.parse_expression(0)?;
|
2024-08-12 20:57:10 +00:00
|
|
|
|
2024-08-13 20:21:44 +00:00
|
|
|
arguments.push(argument);
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
if let Token::Comma = self.current_token {
|
2024-08-13 20:21:44 +00:00
|
|
|
self.next_token()?;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-12 20:57:10 +00:00
|
|
|
self.next_token()?;
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let position = (left.position().0, self.current_position.1);
|
2024-08-14 01:24:56 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
Expression::call(
|
2024-08-14 18:28:39 +00:00
|
|
|
CallExpression {
|
|
|
|
function: left,
|
|
|
|
arguments,
|
2024-08-13 20:21:44 +00:00
|
|
|
},
|
2024-08-14 18:28:39 +00:00
|
|
|
position,
|
2024-08-13 20:21:44 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
Token::LeftSquareBrace => {
|
2024-08-14 18:28:39 +00:00
|
|
|
let operator_start = self.current_position.0;
|
2024-08-12 23:06:57 +00:00
|
|
|
|
2024-08-13 20:21:44 +00:00
|
|
|
self.next_token()?;
|
2024-08-12 23:06:57 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let index = self.parse_expression(0)?;
|
2024-08-12 23:06:57 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let operator_end = if let Token::RightSquareBrace = self.current_token {
|
|
|
|
let end = self.current_position.1;
|
2024-08-12 23:06:57 +00:00
|
|
|
|
2024-08-13 20:21:44 +00:00
|
|
|
self.next_token()?;
|
|
|
|
|
|
|
|
end
|
|
|
|
} else {
|
|
|
|
return Err(ParseError::ExpectedToken {
|
|
|
|
expected: TokenKind::RightSquareBrace,
|
2024-08-14 18:28:39 +00:00
|
|
|
actual: self.current_token.to_owned(),
|
|
|
|
position: self.current_position,
|
2024-08-13 20:21:44 +00:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
let position = (left.position().0, operator_end);
|
2024-08-13 20:21:44 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
Expression::list_index(ListIndex { list: left, index }, position)
|
2024-08-13 20:21:44 +00:00
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
return Err(ParseError::UnexpectedToken {
|
2024-08-14 18:28:39 +00:00
|
|
|
actual: self.current_token.to_owned(),
|
|
|
|
position: self.current_position,
|
2024-08-13 20:21:44 +00:00
|
|
|
});
|
|
|
|
}
|
2024-08-12 13:06:42 +00:00
|
|
|
};
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
if self.current_token.is_postfix() {
|
2024-08-12 23:06:57 +00:00
|
|
|
self.parse_postfix(statement)
|
|
|
|
} else {
|
|
|
|
Ok(statement)
|
|
|
|
}
|
2024-08-09 22:14:46 +00:00
|
|
|
}
|
2024-08-10 09:23:43 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
fn parse_identifier(&mut self) -> Result<Node<Identifier>, ParseError> {
|
|
|
|
if let Token::Identifier(text) = self.current_token {
|
|
|
|
self.next_token()?;
|
2024-08-13 17:54:16 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
Ok(Node::new(Identifier::new(text), self.current_position))
|
|
|
|
} else {
|
|
|
|
Err(ParseError::ExpectedToken {
|
|
|
|
expected: TokenKind::Identifier,
|
|
|
|
actual: self.current_token.to_owned(),
|
|
|
|
position: self.current_position,
|
|
|
|
})
|
|
|
|
}
|
2024-08-13 17:54:16 +00:00
|
|
|
}
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
fn parse_block(&mut self) -> Result<Node<Block>, ParseError> {
|
|
|
|
let left_start = self.current_position.0;
|
|
|
|
let is_async = if let Token::Async = self.current_token {
|
|
|
|
self.next_token()?;
|
|
|
|
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
};
|
2024-08-10 09:23:43 +00:00
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
if let Token::LeftCurlyBrace = self.current_token {
|
2024-08-10 09:23:43 +00:00
|
|
|
self.next_token()?;
|
|
|
|
} else {
|
|
|
|
return Err(ParseError::ExpectedToken {
|
2024-08-12 14:08:34 +00:00
|
|
|
expected: TokenKind::LeftCurlyBrace,
|
2024-08-14 18:28:39 +00:00
|
|
|
actual: self.current_token.to_owned(),
|
|
|
|
position: self.current_position,
|
2024-08-10 09:23:43 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut statements = Vec::new();
|
|
|
|
|
|
|
|
loop {
|
2024-08-14 18:28:39 +00:00
|
|
|
if let Token::RightCurlyBrace = self.current_token {
|
|
|
|
let position = (left_start, self.current_position.1);
|
2024-08-10 09:23:43 +00:00
|
|
|
|
|
|
|
self.next_token()?;
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
return if is_async {
|
|
|
|
Ok(Node::new(Block::Async(statements), position))
|
|
|
|
} else {
|
|
|
|
Ok(Node::new(Block::Sync(statements), position))
|
|
|
|
};
|
2024-08-10 09:23:43 +00:00
|
|
|
}
|
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
let statement = self.parse_statement()?;
|
2024-08-10 09:23:43 +00:00
|
|
|
|
|
|
|
statements.push(statement);
|
|
|
|
}
|
|
|
|
}
|
2024-08-13 19:12:32 +00:00
|
|
|
|
|
|
|
fn parse_type(&mut self) -> Result<Node<Type>, ParseError> {
|
2024-08-14 18:28:39 +00:00
|
|
|
let r#type = match self.current_token {
|
2024-08-13 19:12:32 +00:00
|
|
|
Token::Bool => Type::Boolean,
|
|
|
|
Token::FloatKeyword => Type::Float,
|
|
|
|
Token::Int => Type::Integer,
|
|
|
|
_ => {
|
|
|
|
return Err(ParseError::ExpectedTokenMultiple {
|
|
|
|
expected: vec![TokenKind::Bool, TokenKind::FloatKeyword, TokenKind::Int],
|
2024-08-14 18:28:39 +00:00
|
|
|
actual: self.current_token.to_owned(),
|
|
|
|
position: self.current_position,
|
2024-08-13 19:12:32 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
2024-08-14 18:28:39 +00:00
|
|
|
let position = self.current_position;
|
2024-08-13 19:12:32 +00:00
|
|
|
|
|
|
|
self.next_token()?;
|
|
|
|
|
|
|
|
Ok(Node::new(r#type, position))
|
|
|
|
}
|
2024-08-04 00:23:52 +00:00
|
|
|
}
|
|
|
|
|
2024-08-04 23:25:44 +00:00
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
|
|
|
pub enum ParseError {
|
2024-08-14 18:28:39 +00:00
|
|
|
Boolean {
|
2024-08-09 18:01:01 +00:00
|
|
|
error: ParseBoolError,
|
|
|
|
position: Span,
|
|
|
|
},
|
2024-08-14 18:28:39 +00:00
|
|
|
Lex(LexError),
|
2024-08-11 17:16:16 +00:00
|
|
|
ExpectedAssignment {
|
2024-08-14 18:28:39 +00:00
|
|
|
actual: Statement,
|
|
|
|
},
|
|
|
|
ExpectedExpression {
|
|
|
|
actual: Statement,
|
2024-08-11 17:16:16 +00:00
|
|
|
},
|
2024-08-09 08:23:02 +00:00
|
|
|
ExpectedIdentifier {
|
2024-08-09 10:09:59 +00:00
|
|
|
actual: TokenOwned,
|
2024-08-09 15:41:23 +00:00
|
|
|
position: Span,
|
2024-08-09 08:23:02 +00:00
|
|
|
},
|
2024-08-09 10:09:59 +00:00
|
|
|
ExpectedToken {
|
2024-08-12 14:08:34 +00:00
|
|
|
expected: TokenKind,
|
2024-08-09 08:23:02 +00:00
|
|
|
actual: TokenOwned,
|
|
|
|
position: Span,
|
|
|
|
},
|
2024-08-13 19:12:32 +00:00
|
|
|
ExpectedTokenMultiple {
|
|
|
|
expected: Vec<TokenKind>,
|
|
|
|
actual: TokenOwned,
|
|
|
|
position: Span,
|
|
|
|
},
|
2024-08-09 08:23:02 +00:00
|
|
|
UnexpectedToken {
|
|
|
|
actual: TokenOwned,
|
|
|
|
position: Span,
|
|
|
|
},
|
2024-08-14 18:28:39 +00:00
|
|
|
Float {
|
2024-08-09 18:01:01 +00:00
|
|
|
error: ParseFloatError,
|
|
|
|
position: Span,
|
|
|
|
},
|
2024-08-14 18:28:39 +00:00
|
|
|
Integer {
|
2024-08-09 18:01:01 +00:00
|
|
|
error: ParseIntError,
|
|
|
|
position: Span,
|
|
|
|
},
|
2024-08-09 04:49:17 +00:00
|
|
|
}
|
|
|
|
|
2024-08-10 04:01:50 +00:00
|
|
|
impl From<LexError> for ParseError {
|
|
|
|
fn from(v: LexError) -> Self {
|
2024-08-14 18:28:39 +00:00
|
|
|
Self::Lex(v)
|
2024-08-10 04:01:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-09 04:49:17 +00:00
|
|
|
impl ParseError {
|
|
|
|
pub fn position(&self) -> Span {
|
|
|
|
match self {
|
2024-08-14 18:28:39 +00:00
|
|
|
ParseError::Boolean { position, .. } => *position,
|
|
|
|
ParseError::ExpectedAssignment { actual } => actual.position(),
|
|
|
|
ParseError::ExpectedExpression { actual } => actual.position(),
|
2024-08-09 18:01:01 +00:00
|
|
|
ParseError::ExpectedIdentifier { position, .. } => *position,
|
|
|
|
ParseError::ExpectedToken { position, .. } => *position,
|
2024-08-13 19:12:32 +00:00
|
|
|
ParseError::ExpectedTokenMultiple { position, .. } => *position,
|
2024-08-14 18:28:39 +00:00
|
|
|
ParseError::Float { position, .. } => *position,
|
|
|
|
ParseError::Integer { position, .. } => *position,
|
|
|
|
ParseError::Lex(error) => error.position(),
|
2024-08-09 18:01:01 +00:00
|
|
|
ParseError::UnexpectedToken { position, .. } => *position,
|
2024-08-09 04:49:17 +00:00
|
|
|
}
|
|
|
|
}
|
2024-08-04 23:25:44 +00:00
|
|
|
}
|
|
|
|
|
2024-08-09 00:58:56 +00:00
|
|
|
impl Error for ParseError {
|
|
|
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
|
|
|
match self {
|
2024-08-14 18:28:39 +00:00
|
|
|
Self::Lex(error) => Some(error),
|
2024-08-09 00:58:56 +00:00
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Display for ParseError {
|
|
|
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
|
|
match self {
|
2024-08-14 18:28:39 +00:00
|
|
|
Self::Boolean { error, .. } => write!(f, "{}", error),
|
2024-08-11 17:16:16 +00:00
|
|
|
Self::ExpectedAssignment { .. } => write!(f, "Expected assignment"),
|
2024-08-14 18:28:39 +00:00
|
|
|
Self::ExpectedExpression { .. } => write!(f, "Expected expression"),
|
2024-08-09 08:23:02 +00:00
|
|
|
Self::ExpectedIdentifier { actual, .. } => {
|
|
|
|
write!(f, "Expected identifier, found {actual}")
|
|
|
|
}
|
2024-08-09 10:09:59 +00:00
|
|
|
Self::ExpectedToken {
|
|
|
|
expected, actual, ..
|
|
|
|
} => write!(f, "Expected token {expected}, found {actual}"),
|
2024-08-13 19:12:32 +00:00
|
|
|
Self::ExpectedTokenMultiple {
|
|
|
|
expected, actual, ..
|
|
|
|
} => {
|
|
|
|
write!(f, "Expected one of")?;
|
|
|
|
|
|
|
|
for (i, token_kind) in expected.iter().enumerate() {
|
|
|
|
if i == 0 {
|
|
|
|
write!(f, " {token_kind}")?;
|
|
|
|
} else if i == expected.len() - 1 {
|
|
|
|
write!(f, " or {token_kind}")?;
|
|
|
|
} else {
|
|
|
|
write!(f, ", {token_kind}")?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, ", found {actual}")
|
|
|
|
}
|
2024-08-14 18:28:39 +00:00
|
|
|
Self::Float { error, .. } => write!(f, "{}", error),
|
|
|
|
Self::Integer { error, .. } => write!(f, "{}", error),
|
|
|
|
Self::Lex(error) => write!(f, "{}", error),
|
2024-08-09 04:49:17 +00:00
|
|
|
Self::UnexpectedToken { actual, .. } => write!(f, "Unexpected token {actual}"),
|
2024-08-09 00:58:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-04 00:23:52 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2024-08-14 19:52:04 +00:00
|
|
|
use fmt::Write;
|
|
|
|
|
|
|
|
use crate::{Identifier, Type};
|
2024-08-04 00:23:52 +00:00
|
|
|
|
2024-08-04 23:25:44 +00:00
|
|
|
use super::*;
|
2024-08-04 00:23:52 +00:00
|
|
|
|
2024-08-14 05:13:43 +00:00
|
|
|
#[test]
|
|
|
|
fn mutable_variable() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "mut x = false";
|
2024-08-14 05:13:43 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-14 05:13:43 +00:00
|
|
|
}
|
|
|
|
|
2024-08-14 03:45:17 +00:00
|
|
|
#[test]
|
|
|
|
fn async_block() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "async { x = 42; y = 4.0 }";
|
2024-08-14 03:45:17 +00:00
|
|
|
|
|
|
|
assert_eq!(
|
2024-08-14 19:52:04 +00:00
|
|
|
parse(source),
|
2024-08-14 03:45:17 +00:00
|
|
|
Ok(AbstractSyntaxTree {
|
2024-08-14 19:52:04 +00:00
|
|
|
statements: [Statement::Expression(Expression::block(
|
|
|
|
Block::Async(vec![
|
|
|
|
Statement::Expression(Expression::operator(
|
|
|
|
OperatorExpression::Assignment {
|
|
|
|
assignee: Expression::identifier(Identifier::new("x"), (0, 0)),
|
|
|
|
value: Expression::literal(LiteralExpression::Integer(42), (0, 0)),
|
|
|
|
},
|
|
|
|
(0, 0)
|
|
|
|
)),
|
|
|
|
Statement::Expression(Expression::operator(
|
|
|
|
OperatorExpression::Assignment {
|
|
|
|
assignee: Expression::identifier(Identifier::new("y"), (0, 0)),
|
|
|
|
value: Expression::literal(LiteralExpression::Float(4.0), (0, 0)),
|
|
|
|
},
|
|
|
|
(0, 0)
|
|
|
|
))
|
|
|
|
]),
|
|
|
|
(0, 0)
|
|
|
|
),)]
|
2024-08-14 03:45:17 +00:00
|
|
|
.into()
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-08-14 01:24:56 +00:00
|
|
|
#[test]
|
|
|
|
fn tuple_struct_access() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "(Foo(42, 'bar')).0";
|
2024-08-14 07:53:15 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-14 01:24:56 +00:00
|
|
|
}
|
|
|
|
|
2024-08-13 23:41:36 +00:00
|
|
|
#[test]
|
|
|
|
fn fields_struct_instantiation() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "Foo { a = 42, b = 4.0 }";
|
2024-08-13 23:41:36 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-13 23:41:36 +00:00
|
|
|
}
|
|
|
|
|
2024-08-13 22:48:02 +00:00
|
|
|
#[test]
|
|
|
|
fn fields_struct() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "struct Foo { a: int, b: float }";
|
2024-08-13 22:48:02 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-13 22:48:02 +00:00
|
|
|
}
|
|
|
|
|
2024-08-13 20:21:44 +00:00
|
|
|
#[test]
|
|
|
|
fn tuple_struct_instantiation() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "struct Foo(int, float) Foo(1, 2.0)";
|
2024-08-13 20:21:44 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-13 20:21:44 +00:00
|
|
|
}
|
|
|
|
|
2024-08-13 19:12:32 +00:00
|
|
|
#[test]
|
|
|
|
fn tuple_struct() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "struct Foo(int, float)";
|
2024-08-13 19:12:32 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-13 19:12:32 +00:00
|
|
|
}
|
|
|
|
|
2024-08-13 17:54:16 +00:00
|
|
|
#[test]
|
|
|
|
fn unit_struct() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "struct Foo";
|
2024-08-13 17:54:16 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-13 17:54:16 +00:00
|
|
|
}
|
|
|
|
|
2024-08-12 20:57:10 +00:00
|
|
|
#[test]
|
|
|
|
fn list_index_nested() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "[1, [2], 3][1][0]";
|
2024-08-12 20:57:10 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-12 20:57:10 +00:00
|
|
|
}
|
|
|
|
|
2024-08-12 15:24:24 +00:00
|
|
|
#[test]
|
|
|
|
fn map_property_nested() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "{ x = { y = 42 } }.x.y";
|
2024-08-12 15:24:24 +00:00
|
|
|
}
|
|
|
|
|
2024-08-12 14:08:34 +00:00
|
|
|
#[test]
|
|
|
|
fn range() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "0..42";
|
2024-08-12 14:08:34 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-12 14:08:34 +00:00
|
|
|
}
|
|
|
|
|
2024-08-12 09:44:05 +00:00
|
|
|
#[test]
|
|
|
|
fn negate_variable() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "a = 1; -a";
|
2024-08-12 09:44:05 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-12 09:44:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn negate_expression() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "-(1 + 1)";
|
2024-08-12 09:44:05 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-12 09:44:05 +00:00
|
|
|
}
|
|
|
|
|
2024-08-12 10:00:14 +00:00
|
|
|
#[test]
|
|
|
|
fn not_expression() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "!(1 > 42)";
|
2024-08-12 10:00:14 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-12 10:00:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn not_variable() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "a = false; !a";
|
2024-08-12 10:00:14 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-12 10:00:14 +00:00
|
|
|
}
|
|
|
|
|
2024-08-11 18:35:33 +00:00
|
|
|
#[test]
|
|
|
|
fn r#if() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "if x { y }";
|
2024-08-11 18:35:33 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-11 18:35:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn if_else() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "if x { y } else { z }";
|
2024-08-11 18:35:33 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!())
|
2024-08-11 18:35:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn if_else_if_else() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "if x { y } else if z { a } else { b }";
|
2024-08-11 18:35:33 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!())
|
2024-08-11 18:35:33 +00:00
|
|
|
}
|
|
|
|
|
2024-08-11 17:16:16 +00:00
|
|
|
#[test]
|
|
|
|
fn malformed_map() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "{ x = 1, y = 2, z = 3; }";
|
2024-08-11 17:16:16 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!())
|
2024-08-11 17:16:16 +00:00
|
|
|
}
|
|
|
|
|
2024-08-10 09:23:43 +00:00
|
|
|
#[test]
|
|
|
|
fn while_loop() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "while x < 10 { x += 1 }";
|
2024-08-10 09:23:43 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!())
|
2024-08-10 09:23:43 +00:00
|
|
|
}
|
|
|
|
|
2024-08-09 22:14:46 +00:00
|
|
|
#[test]
|
|
|
|
fn add_assign() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "a += 1";
|
2024-08-09 22:14:46 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!())
|
2024-08-09 22:14:46 +00:00
|
|
|
}
|
|
|
|
|
2024-08-09 18:01:01 +00:00
|
|
|
#[test]
|
|
|
|
fn or() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "true || false";
|
2024-08-09 18:01:01 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!())
|
2024-08-09 18:01:01 +00:00
|
|
|
}
|
|
|
|
|
2024-08-09 15:41:23 +00:00
|
|
|
#[test]
|
|
|
|
fn misplaced_semicolon() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = ";";
|
2024-08-09 15:41:23 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!())
|
2024-08-09 15:41:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn block_with_one_statement() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "{ 40 + 2 }";
|
2024-08-09 15:41:23 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!())
|
2024-08-09 15:41:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn block_with_assignment() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "{ foo = 42; bar = 42; baz = '42' }";
|
2024-08-09 15:41:23 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!())
|
2024-08-09 15:41:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn empty_map() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "{}";
|
2024-08-09 15:41:23 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-09 15:41:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn map_with_trailing_comma() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "{ foo = 42, bar = 42, baz = '42', }";
|
2024-08-09 15:41:23 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-09 15:41:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2024-08-12 19:02:04 +00:00
|
|
|
fn map_with_two_fields() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "{ x = 42, y = 'foobar' }";
|
2024-08-09 15:41:23 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-09 15:41:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2024-08-12 19:02:04 +00:00
|
|
|
fn map_with_one_field() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "{ x = 42 }";
|
2024-08-09 15:41:23 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-09 15:41:23 +00:00
|
|
|
}
|
|
|
|
|
2024-08-09 11:15:09 +00:00
|
|
|
#[test]
|
|
|
|
fn equal() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "42 == 42";
|
2024-08-09 11:15:09 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-09 11:15:09 +00:00
|
|
|
}
|
|
|
|
|
2024-08-09 11:02:55 +00:00
|
|
|
#[test]
|
|
|
|
fn modulo() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "42 % 2";
|
2024-08-09 11:02:55 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-09 11:02:55 +00:00
|
|
|
}
|
|
|
|
|
2024-08-09 10:46:24 +00:00
|
|
|
#[test]
|
|
|
|
fn divide() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "42 / 2";
|
2024-08-09 10:46:24 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-09 10:46:24 +00:00
|
|
|
}
|
|
|
|
|
2024-08-09 07:00:48 +00:00
|
|
|
#[test]
|
|
|
|
fn less_than() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "1 < 2";
|
2024-08-09 07:00:48 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-09 07:00:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn less_than_or_equal() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "1 <= 2";
|
2024-08-09 07:00:48 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-09 07:00:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn greater_than_or_equal() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "1 >= 2";
|
2024-08-09 07:00:48 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-09 07:00:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn greater_than() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "1 > 2";
|
2024-08-09 07:00:48 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-09 07:00:48 +00:00
|
|
|
}
|
|
|
|
|
2024-08-08 17:11:32 +00:00
|
|
|
#[test]
|
2024-08-09 03:28:47 +00:00
|
|
|
fn subtract_negative_integers() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "-1 - -2";
|
2024-08-09 03:28:47 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-09 03:28:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2024-08-08 17:11:32 +00:00
|
|
|
fn string_concatenation() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "\"Hello, \" + \"World!\"";
|
2024-08-08 17:11:32 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-08 17:11:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn string() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "\"Hello, World!\"";
|
2024-08-08 17:11:32 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-08 17:11:32 +00:00
|
|
|
}
|
|
|
|
|
2024-08-07 14:50:19 +00:00
|
|
|
#[test]
|
|
|
|
fn boolean() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "true";
|
2024-08-07 14:50:19 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-07 14:50:19 +00:00
|
|
|
}
|
|
|
|
|
2024-08-07 22:24:25 +00:00
|
|
|
#[test]
|
|
|
|
fn property_access_function_call() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "42.is_even()";
|
2024-08-07 22:24:25 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-07 22:24:25 +00:00
|
|
|
}
|
|
|
|
|
2024-08-05 18:58:58 +00:00
|
|
|
#[test]
|
2024-08-12 20:57:10 +00:00
|
|
|
fn list_index() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "[1, 2, 3][0]";
|
2024-08-05 18:58:58 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-05 18:58:58 +00:00
|
|
|
}
|
|
|
|
|
2024-08-05 18:31:08 +00:00
|
|
|
#[test]
|
|
|
|
fn property_access() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "a.b";
|
2024-08-05 18:31:08 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-05 18:31:08 +00:00
|
|
|
}
|
|
|
|
|
2024-08-05 01:39:57 +00:00
|
|
|
#[test]
|
|
|
|
fn complex_list() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "[1, 1 + 1, 2 + (4 * 10)]";
|
2024-08-05 01:39:57 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-05 01:39:57 +00:00
|
|
|
}
|
|
|
|
|
2024-08-05 01:31:18 +00:00
|
|
|
#[test]
|
|
|
|
fn list() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "[1, 2]";
|
2024-08-05 01:31:18 +00:00
|
|
|
|
2024-08-14 19:52:04 +00:00
|
|
|
assert_eq!(parse(source), todo!());
|
2024-08-05 01:31:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn empty_list() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "[]";
|
2024-08-05 01:31:18 +00:00
|
|
|
|
2024-08-14 20:07:32 +00:00
|
|
|
assert_eq!(
|
|
|
|
parse(source),
|
|
|
|
Ok(AbstractSyntaxTree::with_statements([
|
|
|
|
Statement::Expression(Expression::list(ListExpression::Ordered(vec![]), (0, 2)))
|
|
|
|
]))
|
|
|
|
);
|
2024-08-05 01:31:18 +00:00
|
|
|
}
|
|
|
|
|
2024-08-05 00:08:43 +00:00
|
|
|
#[test]
|
|
|
|
fn float() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "42.0";
|
2024-08-05 00:08:43 +00:00
|
|
|
|
2024-08-14 20:07:32 +00:00
|
|
|
assert_eq!(
|
|
|
|
parse(source),
|
|
|
|
Ok(AbstractSyntaxTree::with_statements([
|
|
|
|
Statement::Expression(Expression::literal(LiteralExpression::Float(42.0), (0, 4)))
|
|
|
|
]))
|
|
|
|
);
|
2024-08-05 00:08:43 +00:00
|
|
|
}
|
|
|
|
|
2024-08-04 00:23:52 +00:00
|
|
|
#[test]
|
|
|
|
fn add() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "1 + 2";
|
2024-08-04 00:23:52 +00:00
|
|
|
|
2024-08-14 20:07:32 +00:00
|
|
|
assert_eq!(
|
|
|
|
parse(source),
|
|
|
|
Ok(AbstractSyntaxTree::with_statements([
|
|
|
|
Statement::Expression(Expression::operator(
|
|
|
|
OperatorExpression::Math {
|
|
|
|
left: Expression::literal(LiteralExpression::Integer(1), (0, 1)),
|
|
|
|
operator: Node::new(MathOperator::Add, (2, 3)),
|
|
|
|
right: Expression::literal(LiteralExpression::Integer(2), (4, 5))
|
|
|
|
},
|
|
|
|
(0, 5)
|
|
|
|
))
|
|
|
|
]))
|
|
|
|
);
|
2024-08-04 00:23:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn multiply() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "1 * 2";
|
2024-08-04 00:23:52 +00:00
|
|
|
|
2024-08-14 20:07:32 +00:00
|
|
|
assert_eq!(
|
|
|
|
parse(source),
|
|
|
|
Ok(AbstractSyntaxTree::with_statements([
|
|
|
|
Statement::Expression(Expression::operator(
|
|
|
|
OperatorExpression::Math {
|
|
|
|
left: Expression::literal(LiteralExpression::Integer(1), (0, 1)),
|
|
|
|
operator: Node::new(MathOperator::Multiply, (2, 3)),
|
|
|
|
right: Expression::literal(LiteralExpression::Integer(2), (4, 5))
|
|
|
|
},
|
|
|
|
(0, 5)
|
|
|
|
))
|
|
|
|
]))
|
|
|
|
);
|
2024-08-04 00:23:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn add_and_multiply() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "1 + 2 * 3";
|
2024-08-04 00:23:52 +00:00
|
|
|
|
2024-08-14 20:07:32 +00:00
|
|
|
assert_eq!(
|
|
|
|
parse(source),
|
|
|
|
Ok(AbstractSyntaxTree::with_statements([
|
|
|
|
Statement::Expression(Expression::operator(
|
|
|
|
OperatorExpression::Math {
|
|
|
|
left: Expression::literal(LiteralExpression::Integer(1), (0, 1)),
|
|
|
|
operator: Node::new(MathOperator::Add, (2, 3)),
|
|
|
|
right: Expression::operator(
|
|
|
|
OperatorExpression::Math {
|
|
|
|
left: Expression::literal(LiteralExpression::Integer(2), (4, 5)),
|
|
|
|
operator: Node::new(MathOperator::Multiply, (6, 7)),
|
|
|
|
right: Expression::literal(LiteralExpression::Integer(3), (8, 9))
|
|
|
|
},
|
|
|
|
(4, 9)
|
|
|
|
)
|
|
|
|
},
|
|
|
|
(0, 5)
|
|
|
|
))
|
|
|
|
]))
|
|
|
|
);
|
2024-08-04 00:23:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn assignment() {
|
2024-08-14 19:52:04 +00:00
|
|
|
let source = "a = 1 + 2 * 3";
|
2024-08-04 00:23:52 +00:00
|
|
|
|
2024-08-14 20:07:32 +00:00
|
|
|
assert_eq!(
|
|
|
|
parse(source),
|
|
|
|
Ok(AbstractSyntaxTree::with_statements([
|
|
|
|
Statement::Expression(Expression::operator(
|
|
|
|
OperatorExpression::Assignment {
|
|
|
|
assignee: Expression::identifier(Identifier::new("a"), (0, 1)),
|
|
|
|
value: Expression::operator(
|
|
|
|
OperatorExpression::Math {
|
|
|
|
left: Expression::literal(LiteralExpression::Integer(1), (4, 5)),
|
|
|
|
operator: Node::new(MathOperator::Add, (6, 7)),
|
|
|
|
right: Expression::operator(
|
|
|
|
OperatorExpression::Math {
|
|
|
|
left: Expression::literal(
|
|
|
|
LiteralExpression::Integer(2),
|
|
|
|
(8, 9)
|
|
|
|
),
|
|
|
|
operator: Node::new(MathOperator::Multiply, (10, 11)),
|
|
|
|
right: Expression::literal(
|
|
|
|
LiteralExpression::Integer(3),
|
|
|
|
(12, 13)
|
|
|
|
)
|
|
|
|
},
|
|
|
|
(8, 13)
|
|
|
|
)
|
|
|
|
},
|
|
|
|
(4, 13)
|
|
|
|
)
|
|
|
|
},
|
|
|
|
(0, 13)
|
|
|
|
))
|
|
|
|
]))
|
|
|
|
);
|
2024-08-04 00:23:52 +00:00
|
|
|
}
|
|
|
|
}
|