use crate::internal::{ast::Argument, errors::ParseError, lexer::Token};
pub fn parse_arg_list<'a>(
tokens: &'a [(Token, &'a str)],
pos: &mut usize,
) -> Result<Vec<Argument>, ParseError> {
let mut args = Vec::new();
if let Some((tok, _)) = crate::internal::peek::peek(tokens, *pos).cloned() {
if matches!(tok, Token::FunctionEnd) {
return Ok(args);
}
}
args.push(crate::internal::parse_arg::parse_arg(tokens, pos)?);
while crate::internal::matches::matches(tokens, pos, |t| matches!(t, Token::Comma)) {
args.push(crate::internal::parse_arg::parse_arg(tokens, pos)?);
}
Ok(args)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::internal::lexer::Token;
#[test]
fn test_parse_arg_list_empty() {
let tokens = vec![(Token::FunctionEnd, ")")];
let mut pos = 0;
let result = parse_arg_list(&tokens, &mut pos);
assert!(result.is_ok());
let args = result.unwrap();
assert_eq!(args.len(), 0);
assert_eq!(pos, 0); }
#[test]
fn test_parse_arg_list_single_argument() {
let tokens = vec![(Token::ColumnName, "x"), (Token::FunctionEnd, ")")];
let mut pos = 0;
let result = parse_arg_list(&tokens, &mut pos);
assert!(result.is_ok());
let args = result.unwrap();
assert_eq!(args.len(), 1);
assert_eq!(pos, 1); }
#[test]
fn test_parse_arg_list_two_arguments() {
let tokens = vec![
(Token::ColumnName, "x"),
(Token::Comma, ","),
(Token::Integer, "2"),
(Token::FunctionEnd, ")"),
];
let mut pos = 0;
let result = parse_arg_list(&tokens, &mut pos);
assert!(result.is_ok());
let args = result.unwrap();
assert_eq!(args.len(), 2);
assert_eq!(pos, 3); }
#[test]
fn test_parse_arg_list_multiple_arguments() {
let tokens = vec![
(Token::ColumnName, "x"),
(Token::Comma, ","),
(Token::ColumnName, "y"),
(Token::Comma, ","),
(Token::Integer, "10"),
(Token::FunctionEnd, ")"),
];
let mut pos = 0;
let result = parse_arg_list(&tokens, &mut pos);
assert!(result.is_ok());
let args = result.unwrap();
assert_eq!(args.len(), 3);
assert_eq!(pos, 5); }
#[test]
fn test_parse_arg_list_with_integer_argument() {
let tokens = vec![(Token::Integer, "42"), (Token::FunctionEnd, ")")];
let mut pos = 0;
let result = parse_arg_list(&tokens, &mut pos);
assert!(result.is_ok());
let args = result.unwrap();
assert_eq!(args.len(), 1);
assert_eq!(pos, 1);
}
#[test]
fn test_parse_arg_list_with_one_argument() {
let tokens = vec![(Token::One, "1"), (Token::FunctionEnd, ")")];
let mut pos = 0;
let result = parse_arg_list(&tokens, &mut pos);
assert!(result.is_ok());
let args = result.unwrap();
assert_eq!(args.len(), 1);
assert_eq!(pos, 1);
}
#[test]
fn test_parse_arg_list_mixed_types() {
let tokens = vec![
(Token::ColumnName, "variable"),
(Token::Comma, ","),
(Token::Integer, "5"),
(Token::Comma, ","),
(Token::One, "1"),
(Token::FunctionEnd, ")"),
];
let mut pos = 0;
let result = parse_arg_list(&tokens, &mut pos);
assert!(result.is_ok());
let args = result.unwrap();
assert_eq!(args.len(), 3);
assert_eq!(pos, 5);
}
#[test]
fn test_parse_arg_list_no_closing_paren() {
let tokens = vec![
(Token::ColumnName, "x"),
(Token::Comma, ","),
(Token::ColumnName, "y"),
];
let mut pos = 0;
let result = parse_arg_list(&tokens, &mut pos);
assert!(result.is_ok()); let args = result.unwrap();
assert_eq!(args.len(), 2);
assert_eq!(pos, 3);
}
#[test]
fn test_parse_arg_list_with_whitespace_equivalent() {
let tokens = vec![
(Token::ColumnName, "x"),
(Token::Comma, ","),
(Token::ColumnName, "y"),
(Token::Comma, ","),
(Token::ColumnName, "z"),
(Token::FunctionEnd, ")"),
];
let mut pos = 0;
let result = parse_arg_list(&tokens, &mut pos);
assert!(result.is_ok());
let args = result.unwrap();
assert_eq!(args.len(), 3);
assert_eq!(pos, 5);
}
}