luaparser 0.1.1

Read Lua 5.1 code and produce an abstract syntax tree
Documentation
use crate::parser::{
    parse_block,
    parse_block_with_end,
    try_parse_expression,
    OptionParsingResult,
    ParsingError,
};
use crate::parser::token_utils::{
    is_one_of_keywords,
    skip_first_token_if_is_keyword,
    LuaKeyword,
};
use crate::parser::node_types::NodeTypes;

use lualexer::Token;
use std::marker::PhantomData;

pub fn try_parse_if_statement<'a, T: NodeTypes>(
    tokens: &'a [Token<'a>]
) -> OptionParsingResult<'a, T::Statement> {
    if let Some(after_if_tokens) = skip_first_token_if_is_keyword(tokens, LuaKeyword::If) {
        let (condition, after_condition_tokens) = try_parse_expression::<T>(after_if_tokens)?
            .ok_or(ParsingError::ConditionExpectedForIfStatement)?;

        let after_then_tokens = skip_first_token_if_is_keyword(after_condition_tokens, LuaKeyword::Then)
            .ok_or(ParsingError::ThenKeywordExpectedForIfStatement)?;

        let ((block, last_token), after_block_tokens) = parse_block_with_end(
            PhantomData::<T>,
            after_then_tokens,
            |token| is_one_of_keywords(token, &[
                LuaKeyword::End,
                LuaKeyword::Elseif,
                LuaKeyword::Else,
            ])

        )?;

        let mut branches = vec![(condition, block)];
        let mut next_tokens = after_block_tokens;
        let mut last_token = last_token;

        while last_token.get_content() == "elseif" {
            let (condition, after_condition_tokens) = try_parse_expression::<T>(next_tokens)?
                .ok_or(ParsingError::ConditionExpectedForElseIfClause)?;

            let after_then_tokens = skip_first_token_if_is_keyword(after_condition_tokens, LuaKeyword::Then)
                .ok_or(ParsingError::ThenKeywordExpectedForElseifClause)?;

            let ((block, block_end_token), after_block_tokens) = parse_block_with_end(
                PhantomData::<T>,
                after_then_tokens,
                |token| is_one_of_keywords(token, &[
                    LuaKeyword::End,
                    LuaKeyword::Elseif,
                    LuaKeyword::Else,
                ])

            )?;

            next_tokens = after_block_tokens;
            last_token = block_end_token;

            branches.push((condition, block))
        }

        let else_block = if last_token.get_content() == "else" {
            let (block, after_block_tokens) = parse_block::<T>(next_tokens, LuaKeyword::End)?;
            next_tokens = after_block_tokens;

            Some(block)
        } else {
            None
        };

        let if_statement = T::IfStatement::from((branches, else_block));

        Ok(Some((if_statement.into(), next_tokens)))
    } else {
        Ok(None)
    }
}