use crate::parser::{
try_parse_expression,
OptionParsingResult,
ParsingError,
};
use crate::parser::token_utils::{
is_symbol,
skip_first_token,
skip_first_token_if_is_symbol,
LuaSymbol,
};
use crate::parser::node_types::NodeTypes;
use crate::parser::node_types::builders::TableEntry;
use lualexer::{Token, TokenType};
pub fn try_parse_table_expression<'a, T: NodeTypes>(
tokens: &'a [Token<'a>]
) -> OptionParsingResult<'a, T::TableExpression> {
if let Some(mut next_tokens) = tokens.first()
.filter(|token| is_symbol(token, LuaSymbol::OpenBrace))
.map(|_| skip_first_token(tokens))
{
let mut entries = Vec::new();
while let Some((entry, after_entry_tokens)) = try_parse_table_entry::<T>(next_tokens)? {
entries.push(entry);
if let Some(_) = after_entry_tokens.first()
.filter(|token| is_symbol(token, LuaSymbol::Comma) || is_symbol(token, LuaSymbol::SemiColon))
{
next_tokens = skip_first_token(after_entry_tokens);
} else {
next_tokens = after_entry_tokens;
break
}
}
next_tokens.first()
.filter(|token| is_symbol(token, LuaSymbol::CloseBrace))
.ok_or(ParsingError::ClosingBraceExpected)
.map(|_| Some((T::TableExpression::from(entries), skip_first_token(next_tokens))))
} else {
Ok(None)
}
}
fn try_parse_table_entry<'a, T: NodeTypes>(
tokens: &'a [Token<'a>],
) -> OptionParsingResult<'a, T::TableEntry> {
if let Some(token) = tokens.first() {
if token.is_type(TokenType::Identifier) {
let after_first_tokens = skip_first_token(tokens);
if let Some(next_tokens) = skip_first_token_if_is_symbol(after_first_tokens, LuaSymbol::Assign) {
let (value, next_tokens) = try_parse_expression::<T>(next_tokens)?
.ok_or(ParsingError::ExpressionExpectedForTableEntry)?;
let entry = T::TableEntry::from_field(token.get_content().to_owned(), value);
Ok(Some((entry, next_tokens)))
} else {
let (value, next_tokens) = try_parse_expression::<T>(tokens)?.unwrap();
Ok(Some((T::TableEntry::from_value(value), next_tokens)))
}
} else if is_symbol(token, LuaSymbol::OpenBracket) {
let (index, next_tokens) = try_parse_expression::<T>(skip_first_token(tokens))?
.ok_or(ParsingError::ExpressionExpectedForTableKey)?;
let after_bracket_tokens = next_tokens.first()
.filter(|token| is_symbol(token, LuaSymbol::CloseBracket))
.map(|_| skip_first_token(next_tokens))
.ok_or(ParsingError::ClosingBracketExpectedForTableKey)?;
let after_assign_tokens = after_bracket_tokens.first()
.filter(|token| is_symbol(token, LuaSymbol::Assign))
.map(|_| skip_first_token(after_bracket_tokens))
.ok_or(ParsingError::AssignSymbolExpectedAfterTableKey)?;
let (expression, after_expression_tokens) = try_parse_expression::<T>(after_assign_tokens)?
.ok_or(ParsingError::ExpressionExpectedForTableEntry)?;
Ok(Some((T::TableEntry::from_index(index, expression), after_expression_tokens)))
} else {
if let Some((expression, next_tokens)) = try_parse_expression::<T>(tokens)? {
Ok(Some((T::TableEntry::from_value(expression), next_tokens)))
} else {
Ok(None)
}
}
} else {
Ok(None)
}
}