df_ls_lexical_analysis 0.3.0-rc.1

A language server for Dwarf Fortress RAW files
Documentation
use super::*;
use df_ls_diagnostics::{DMExtraInfo, DiagnosticsInfo};

/// The different phases the parser can be in while tokenizing a token.
#[derive(Debug, PartialEq, Eq)]
enum TokenizeTokenNamePhase {
    TokenNameFound,
    TokenNameError,
    TokenNameEoF,
}

/// Tokenize the name of the token.
/// This is the first value after the `[` and before the next `:` of `]`.
pub(crate) fn tokenize_token_name(
    tok_help: &mut TokenizerHelper,
    regex_list: &RegexList,
    diagnostics: &mut DiagnosticsInfo,
    token_id: u64,
) -> TokenizerResult {
    // Keep track for if we had an error until that point.
    // If next token is `:`, `[` or `]` this means the `token_name` is missing
    let current_phase = if tok_help.check_if_next_char_matches_any_of(&[':', '[', ']']) {
        TokenizeTokenNamePhase::TokenNameError
    } else {
        // `token_name`
        let token_name = tok_help.get_next_match(
            &regex_list.token_name,
            "token_name",
            Some("token_name"),
            false,
            true,
        );
        match token_name {
            TokenMatchStatus::Ok(result) => {
                tok_help.add_node_to_tree(result, token_id);
                TokenizeTokenNamePhase::TokenNameFound
            }
            TokenMatchStatus::OkWithPrefixFound(prefix, result) => {
                utils::handle_prefix(prefix, diagnostics);
                tok_help.add_node_to_tree(result, token_id);
                TokenizeTokenNamePhase::TokenNameFound
            }
            TokenMatchStatus::NoMatch => TokenizeTokenNamePhase::TokenNameError,
            TokenMatchStatus::EoF => TokenizeTokenNamePhase::TokenNameEoF,
        }
    };

    // In case of error add missing tokens.
    if current_phase == TokenizeTokenNamePhase::TokenNameError
        || current_phase == TokenizeTokenNamePhase::TokenNameEoF
    {
        // Add missing token
        let token_name = tok_help.create_start_tsnode("token_name", Some("token_name"));
        diagnostics.add_message(
            // No extra template data needed
            DMExtraInfo::new(token_name.get_range()),
            "missing_token_name",
        );
        tok_help.add_node_to_tree(token_name, token_id);
    }

    if current_phase == TokenizeTokenNamePhase::TokenNameEoF {
        return TokenizerResult::Err(TokenizerEnd::UnexpectedEoF);
    }

    // Check if something after `TokenName`
    // If token name is missing this should still consume everything up until `:` or `]` or
    // Anything that comes after it.

    // Check if Token Name is just lower case (or other chars)
    // Or if it has some other characters after it.
    let token_name_incorrect = tok_help.get_next_match(
        &regex_list.token_argument_all,
        "ERROR",
        Some("ERROR"),
        true,
        true,
    );
    if let TokenMatchStatus::Ok(result) = token_name_incorrect {
        diagnostics.add_message(
            // No extra template data needed
            DMExtraInfo::new(result.get_range()),
            "unexpected_characters",
        );
        tok_help.add_node_to_tree(result, token_id);
    }

    Ok(())
}