luaparser 0.1.1

Read Lua 5.1 code and produce an abstract syntax tree
Documentation
use crate::parser::{
    parse_function_expression,
    parse_unary_expression,
    try_parse_table_expression,
    OptionParsingResult,
};
use crate::parser::token_utils::{
    skip_first_token,
    LuaKeyword,
    LuaSymbol,
};
use crate::parser::node_types::NodeTypes;
use crate::parser::node_types::builders::{
    Expression,
    UnaryOperator,
};

use lualexer::{Token, TokenType};
use std::convert::TryFrom;

pub fn try_parse_primary_expression<'a, T: NodeTypes>(
    tokens: &'a [Token<'a>],
) -> OptionParsingResult<'a, T::Expression> {
    if let Some(token) = tokens.first() {
        let expression_and_tokens = if let Ok(keyword) = LuaKeyword::try_from(token.get_content()) {
            match keyword {
                LuaKeyword::True => {
                    let expression = T::Expression::true_expression();
                    (expression, skip_first_token(tokens))
                }
                LuaKeyword::False => {
                    let expression = T::Expression::false_expression();
                    (expression, skip_first_token(tokens))
                }
                LuaKeyword::Nil => {
                    let expression = T::Expression::nil_expression();
                    (expression, skip_first_token(tokens))
                }
                LuaKeyword::Function => {
                    return parse_function_expression::<T>(tokens)
                        .map(|(function, next_tokens)| Some((function.into(), next_tokens)))
                }
                LuaKeyword::Not => {
                    let (expression, tokens) = parse_unary_expression::<T>(
                        T::UnaryOperator::not(),
                        skip_first_token(tokens)
                    )?;
                    (expression.into(), tokens)
                }
                _ => return Ok(None),
            }
        } else if let Ok(symbol) = LuaSymbol::try_from(token.get_content()) {
            match symbol {
                LuaSymbol::OpenBrace => {
                    return Ok(try_parse_table_expression::<T>(tokens)?
                        .map(|(table, next_tokens)| (table.into(), next_tokens)))
                }
                LuaSymbol::Length => {
                    let (expression, tokens) = parse_unary_expression::<T>(
                        T::UnaryOperator::length(),
                        skip_first_token(tokens)
                    )?;
                    (expression.into(), tokens)
                }
                LuaSymbol::Minus => {
                    let (expression, tokens) = parse_unary_expression::<T>(
                        T::UnaryOperator::minus(),
                        skip_first_token(tokens)
                    )?;
                    (expression.into(), tokens)
                }
                LuaSymbol::VariableArguments => {
                    (T::Expression::variable_arguments(), skip_first_token(tokens))
                }
                _ => return Ok(None),
            }
        } else {
            match (token.get_type(), token.get_content()) {
                (TokenType::Number, number) => {
                    let expression = T::NumberExpression::from(number.to_owned());
                    (expression.into(), skip_first_token(tokens))
                }
                (TokenType::String, string) => {
                    let expression = T::StringExpression::from(string.to_owned());
                    (expression.into(), skip_first_token(tokens))
                }
                _ => return Ok(None),
            }
        };

        Ok(Some(expression_and_tokens))
    } else {
        Ok(None)
    }
}