use crate::parser::{
parse_expression_list,
parse_function_body,
OptionParsingResult,
ParsingError,
};
use crate::parser::token_utils::{
skip_first_token,
skip_first_token_if_is_keyword,
skip_first_token_if_is_symbol,
LuaKeyword,
LuaSymbol,
};
use crate::parser::node_types::NodeTypes;
use lualexer::{Token, TokenType};
pub fn try_parse_local_assign_or_function<'a, T: NodeTypes>(
tokens: &'a [Token<'a>]
) -> OptionParsingResult<'a, T::Statement> {
if let Some(after_local_tokens) = skip_first_token_if_is_keyword(tokens, LuaKeyword::Local) {
if let Some(after_function_tokens) = skip_first_token_if_is_keyword(after_local_tokens, LuaKeyword::Function) {
let identifier = after_function_tokens.first()
.filter(|token| token.is_type(TokenType::Identifier))
.map(Token::get_content)
.ok_or(ParsingError::IdentifierExpectedAfterForKeyword)?;
let (values, next_tokens) = parse_function_body::<T>(skip_first_token(after_function_tokens))?;
let (parameters, is_variadic, block) = values;
let statement = T::LocalFunctionStatement::from((
identifier.to_owned(),
parameters,
is_variadic,
block,
));
Ok(Some((statement.into(), next_tokens)))
} else {
let first_variable = after_local_tokens.first()
.filter(|token| token.is_type(TokenType::Identifier))
.map(Token::get_content)
.ok_or(ParsingError::IdentifierExpectedForLocalAssign)?;
let mut variables = vec![first_variable.to_owned()];
let mut next_tokens = skip_first_token(after_local_tokens);
while let Some(after_comma_tokens) = skip_first_token_if_is_symbol(next_tokens, LuaSymbol::Comma) {
let identifier = after_comma_tokens.first()
.filter(|token| token.is_type(TokenType::Identifier))
.map(Token::get_content)
.ok_or(ParsingError::IdentifierExpectedForLocalAssign)?;
variables.push(identifier.to_owned());
next_tokens = skip_first_token(after_comma_tokens);
}
let (values, next_tokens) = skip_first_token_if_is_symbol(next_tokens, LuaSymbol::Assign)
.map(|tokens| parse_expression_list::<T>(tokens))
.unwrap_or_else(|| Ok((Vec::new(), next_tokens)))?;
let statement = T::LocalAssignStatement::from((variables, values));
Ok(Some((statement.into(), next_tokens)))
}
} else {
Ok(None)
}
}