use crate::T;
use crate::ast::ast::*;
use crate::error::ParseError;
use crate::parser::internal::argument::parse_argument;
use crate::parser::internal::argument::parse_remaining_argument_list;
use crate::parser::internal::expression::parse_expression_with_precedence;
use crate::parser::internal::token_stream::TokenStream;
use crate::parser::internal::utils;
use crate::token::Precedence;
use crate::token::TokenKind;
pub fn parse_ambiguous_clone_expression(stream: &mut TokenStream<'_, '_>) -> Result<Expression, ParseError> {
let clone = utils::expect_keyword(stream, T!["clone"])?;
if utils::peek(stream)?.kind != TokenKind::LeftParenthesis {
return Ok(Expression::Clone(Clone {
clone,
object: Box::new(parse_expression_with_precedence(stream, Precedence::Clone)?),
}));
}
let left_parenthesis = utils::expect_span(stream, T!["("])?;
if let TokenKind::DotDotDot = utils::peek(stream)?.kind {
let ellipsis = utils::expect_any(stream)?.span;
let right_parenthesis = utils::expect_span(stream, T![")"])?;
return Ok(Expression::ClosureCreation(ClosureCreation::Function(FunctionClosureCreation {
function: Box::new(Expression::Identifier(Identifier::Local(LocalIdentifier {
span: clone.span,
value: clone.value,
}))),
left_parenthesis,
ellipsis,
right_parenthesis,
})));
}
let argument = parse_argument(stream)?;
let is_next_comma = utils::peek(stream)?.kind.is_comma();
let cloned_expression = match argument {
Argument::Positional(argument) if !is_next_comma && argument.ellipsis.is_none() => argument.value,
_ => {
let argument_list = parse_remaining_argument_list(stream, left_parenthesis, argument)?;
return Ok(Expression::Call(Call::Function(FunctionCall {
function: Box::new(Expression::Identifier(Identifier::Local(LocalIdentifier {
span: clone.span,
value: clone.value,
}))),
argument_list,
})));
}
};
Ok(Expression::Clone(Clone {
clone,
object: Box::new(Expression::Parenthesized(Parenthesized {
left_parenthesis,
expression: Box::new(cloned_expression),
right_parenthesis: utils::expect_span(stream, T![")"])?,
})),
}))
}