pub mod arena;
pub mod ast;
pub mod diagnostics;
pub mod error_recovery;
pub mod lexer;
pub mod parser;
pub use ast::*;
pub use error_recovery::{ParseError, ParseResult, RecoveryParser};
pub use lexer::{Token, TokenStream};
pub use parser::Parser;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parser_creation() {
let mut parser = Parser::new("42");
assert!(parser.parse().is_ok());
}
#[test]
fn test_parse_simple_expression() {
let mut parser = Parser::new("42");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
assert!(matches!(
expr.kind,
ExprKind::Literal(Literal::Integer(42, None))
));
}
#[test]
fn test_parse_binary_operation() {
let mut parser = Parser::new("1 + 2");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
assert!(matches!(
expr.kind,
ExprKind::Binary {
op: BinaryOp::Add,
..
}
));
}
#[test]
fn test_parse_string_literal() {
let mut parser = Parser::new(r#""hello world""#);
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
if let ExprKind::Literal(Literal::String(s)) = expr.kind {
assert_eq!(s, "hello world");
} else {
panic!("Expected string literal");
}
}
#[test]
fn test_parse_boolean_literals() {
let mut parser = Parser::new("true");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
assert!(matches!(expr.kind, ExprKind::Literal(Literal::Bool(true))));
let mut parser = Parser::new("false");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
assert!(matches!(expr.kind, ExprKind::Literal(Literal::Bool(false))));
}
#[test]
fn test_parse_identifier() {
let mut parser = Parser::new("variable_name");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
if let ExprKind::Identifier(name) = expr.kind {
assert_eq!(name, "variable_name");
} else {
panic!("Expected identifier");
}
}
#[test]
fn test_parse_list_literal() {
let mut parser = Parser::new("[1, 2, 3]");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
if let ExprKind::List(items) = expr.kind {
assert_eq!(items.len(), 3);
} else {
panic!("Expected list literal");
}
}
#[test]
fn test_parse_empty_list() {
let mut parser = Parser::new("[]");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
if let ExprKind::List(items) = expr.kind {
assert!(items.is_empty());
} else {
panic!("Expected empty list");
}
}
#[test]
fn test_parse_tuple() {
let mut parser = Parser::new("(1, 2, 3)");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
if let ExprKind::Tuple(items) = expr.kind {
assert_eq!(items.len(), 3);
} else {
panic!("Expected tuple");
}
}
#[test]
fn test_parse_unary_negation() {
let mut parser = Parser::new("-42");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
assert!(matches!(
expr.kind,
ExprKind::Unary {
op: UnaryOp::Negate,
..
}
));
}
#[test]
fn test_parse_unary_not() {
let mut parser = Parser::new("!true");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
assert!(matches!(
expr.kind,
ExprKind::Unary {
op: UnaryOp::Not,
..
}
));
}
#[test]
fn test_parse_comparison_operators() {
let test_cases = vec![
("5 > 3", BinaryOp::Greater),
("3 < 5", BinaryOp::Less),
("5 >= 5", BinaryOp::GreaterEqual),
("3 <= 5", BinaryOp::LessEqual),
("5 == 5", BinaryOp::Equal),
("3 != 5", BinaryOp::NotEqual),
];
for (input, expected_op) in test_cases {
let mut parser = Parser::new(input);
let result = parser.parse();
assert!(result.is_ok(), "Failed to parse: {input}");
let expr = result.expect("operation should succeed in test");
if let ExprKind::Binary { op, .. } = expr.kind {
assert_eq!(op, expected_op, "Wrong operator for: {input}");
} else {
panic!("Expected binary operation for: {input}");
}
}
}
#[test]
fn test_parse_logical_operators() {
let mut parser = Parser::new("true && false");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
assert!(matches!(
expr.kind,
ExprKind::Binary {
op: BinaryOp::And,
..
}
));
let mut parser = Parser::new("true || false");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
assert!(matches!(
expr.kind,
ExprKind::Binary {
op: BinaryOp::Or,
..
}
));
}
#[test]
fn test_parse_arithmetic_operators() {
let test_cases = vec![
("1 + 2", BinaryOp::Add),
("5 - 3", BinaryOp::Subtract),
("2 * 3", BinaryOp::Multiply),
("6 / 2", BinaryOp::Divide),
("7 % 3", BinaryOp::Modulo),
];
for (input, expected_op) in test_cases {
let mut parser = Parser::new(input);
let result = parser.parse();
assert!(result.is_ok(), "Failed to parse: {input}");
let expr = result.expect("operation should succeed in test");
if let ExprKind::Binary { op, .. } = expr.kind {
assert_eq!(op, expected_op, "Wrong operator for: {input}");
} else {
panic!("Expected binary operation for: {input}");
}
}
}
#[test]
fn test_parse_bitwise_operators() {
let test_cases = vec![
("1 & 2", BinaryOp::BitwiseAnd),
("1 | 2", BinaryOp::BitwiseOr),
("1 ^ 2", BinaryOp::BitwiseXor),
];
for (input, expected_op) in test_cases {
let mut parser = Parser::new(input);
let result = parser.parse();
assert!(result.is_ok(), "Failed to parse: {input}");
let expr = result.expect("operation should succeed in test");
if let ExprKind::Binary { op, .. } = expr.kind {
assert_eq!(op, expected_op, "Wrong operator for: {input}");
} else {
panic!("Expected binary operation for: {input}");
}
}
}
#[test]
fn test_parse_parenthesized_expression() {
let mut parser = Parser::new("(42)");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
assert!(matches!(
expr.kind,
ExprKind::Literal(Literal::Integer(42, None))
));
}
#[test]
fn test_parse_precedence() {
let mut parser = Parser::new("1 + 2 * 3");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
if let ExprKind::Binary {
op: BinaryOp::Add,
right,
..
} = expr.kind
{
assert!(matches!(
right.kind,
ExprKind::Binary {
op: BinaryOp::Multiply,
..
}
));
} else {
panic!("Expected addition at top level");
}
}
#[test]
fn test_parse_float_literal() {
let mut parser = Parser::new("3.15");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
if let ExprKind::Literal(Literal::Float(f)) = expr.kind {
assert!((f - 3.15).abs() < 0.001);
} else {
panic!("Expected float literal");
}
}
#[test]
fn test_parse_character_literal() {
let mut parser = Parser::new("'a'");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
if let ExprKind::Literal(Literal::Char(c)) = expr.kind {
assert_eq!(c, 'a');
} else {
panic!("Expected character literal");
}
}
#[test]
fn test_parse_nil_literal() {
let mut parser = Parser::new("nil");
let result = parser.parse();
assert!(result.is_ok());
}
#[test]
fn test_parse_error_recovery() {
let mut parser = Parser::new("let x =");
let result = parser.parse();
assert!(result.is_err());
}
#[test]
fn test_parse_complex_expression() {
let mut parser = Parser::new("(a + b) * (c - d) / 2");
let result = parser.parse();
assert!(result.is_ok());
}
#[test]
fn test_token_stream_iteration() {
let mut tokens = TokenStream::new("let x = 42");
let mut token_count = 0;
while tokens.next().is_some() {
token_count += 1;
}
assert!(token_count > 0);
}
#[test]
fn test_token_stream_peek() {
let mut tokens = TokenStream::new("42 + 3");
let first_peek = tokens.peek().cloned();
let second_peek = tokens.peek().cloned();
assert_eq!(first_peek, second_peek);
let next = tokens.next();
assert!(next.is_some());
let peek_after_next = tokens.peek().cloned();
assert_ne!(first_peek, peek_after_next);
}
#[test]
fn test_parse_range_expression() {
let mut parser = Parser::new("1..10");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
if let ExprKind::Range { inclusive, .. } = expr.kind {
assert!(!inclusive);
} else {
panic!("Expected range expression");
}
}
#[test]
fn test_parse_inclusive_range() {
let mut parser = Parser::new("1..=10");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
if let ExprKind::Range { inclusive, .. } = expr.kind {
assert!(inclusive);
} else {
panic!("Expected inclusive range");
}
}
#[test]
fn test_parse_nested_list() {
let mut parser = Parser::new("[[1, 2], [3, 4]]");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
if let ExprKind::List(outer) = expr.kind {
assert_eq!(outer.len(), 2);
for item in outer {
assert!(matches!(item.kind, ExprKind::List(_)));
}
} else {
panic!("Expected nested list");
}
}
#[test]
fn test_parse_empty_tuple() {
let mut parser = Parser::new("()");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
assert!(
matches!(expr.kind, ExprKind::Tuple(_))
|| matches!(expr.kind, ExprKind::Literal(Literal::Unit))
);
}
#[test]
fn test_parse_single_element_tuple() {
let mut parser = Parser::new("(42,)");
let result = parser.parse();
assert!(result.is_ok());
let expr = result.expect("operation should succeed in test");
if let ExprKind::Tuple(items) = expr.kind {
assert_eq!(items.len(), 1);
} else {
panic!("Expected single-element tuple");
}
}
}