luaparser 0.1.1

Read Lua 5.1 code and produce an abstract syntax tree
Documentation
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)
    }
}