#include <string.h>

#include "prism/ast.h"

/**
 * Returns a string representation of the given token type.
 */
PRISM_EXPORTED_FUNCTION const char *
pm_token_type_name(pm_token_type_t token_type) {
    switch (token_type) {
<%- tokens.each do |token| -%>
        case PM_TOKEN_<%= token.name %>:
            return "<%= token.name %>";
<%- end -%>
        case PM_TOKEN_MAXIMUM:
            assert(false && "unreachable");
            return "";
    }

    // Provide a default, because some compilers can't determine that the above
    // switch is exhaustive.
    assert(false && "unreachable");
    return "";
}

/**
 * Returns the human name of the given token type.
 */
const char *
pm_token_type_human(pm_token_type_t token_type) {
    switch (token_type) {
        case PM_TOKEN_EOF:
            return "end-of-input";
        case PM_TOKEN_MISSING:
            return "missing token";
        case PM_TOKEN_NOT_PROVIDED:
            return "not provided token";
        case PM_TOKEN_AMPERSAND:
            return "'&'";
        case PM_TOKEN_AMPERSAND_AMPERSAND:
            return "'&&'";
        case PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL:
            return "'&&='";
        case PM_TOKEN_AMPERSAND_DOT:
            return "'&.'";
        case PM_TOKEN_AMPERSAND_EQUAL:
            return "'&='";
        case PM_TOKEN_BACKTICK:
            return "'`'";
        case PM_TOKEN_BACK_REFERENCE:
            return "back reference";
        case PM_TOKEN_BANG:
            return "'!'";
        case PM_TOKEN_BANG_EQUAL:
            return "'!='";
        case PM_TOKEN_BANG_TILDE:
            return "'!~'";
        case PM_TOKEN_BRACE_LEFT:
            return "'{'";
        case PM_TOKEN_BRACE_RIGHT:
            return "'}'";
        case PM_TOKEN_BRACKET_LEFT:
            return "'['";
        case PM_TOKEN_BRACKET_LEFT_ARRAY:
            return "'['";
        case PM_TOKEN_BRACKET_LEFT_RIGHT:
            return "'[]'";
        case PM_TOKEN_BRACKET_LEFT_RIGHT_EQUAL:
            return "'[]='";
        case PM_TOKEN_BRACKET_RIGHT:
            return "']'";
        case PM_TOKEN_CARET:
            return "'^'";
        case PM_TOKEN_CARET_EQUAL:
            return "'^='";
        case PM_TOKEN_CHARACTER_LITERAL:
            return "character literal";
        case PM_TOKEN_CLASS_VARIABLE:
            return "class variable";
        case PM_TOKEN_COLON:
            return "':'";
        case PM_TOKEN_COLON_COLON:
            return "'::'";
        case PM_TOKEN_COMMA:
            return "','";
        case PM_TOKEN_COMMENT:
            return "comment";
        case PM_TOKEN_CONSTANT:
            return "constant";
        case PM_TOKEN_DOT:
            return "'.'";
        case PM_TOKEN_DOT_DOT:
            return "..";
        case PM_TOKEN_DOT_DOT_DOT:
            return "...";
        case PM_TOKEN_EMBDOC_BEGIN:
            return "'=begin'";
        case PM_TOKEN_EMBDOC_END:
            return "'=end'";
        case PM_TOKEN_EMBDOC_LINE:
            return "embedded documentation line";
        case PM_TOKEN_EMBEXPR_BEGIN:
            return "'#{'";
        case PM_TOKEN_EMBEXPR_END:
            return "'}'";
        case PM_TOKEN_EMBVAR:
            return "'#'";
        case PM_TOKEN_EQUAL:
            return "'='";
        case PM_TOKEN_EQUAL_EQUAL:
            return "'=='";
        case PM_TOKEN_EQUAL_EQUAL_EQUAL:
            return "'==='";
        case PM_TOKEN_EQUAL_GREATER:
            return "'=>'";
        case PM_TOKEN_EQUAL_TILDE:
            return "'=~'";
        case PM_TOKEN_FLOAT:
            return "float";
        case PM_TOKEN_FLOAT_IMAGINARY:
            return "imaginary";
        case PM_TOKEN_FLOAT_RATIONAL:
            return "rational";
        case PM_TOKEN_FLOAT_RATIONAL_IMAGINARY:
            return "imaginary";
        case PM_TOKEN_GLOBAL_VARIABLE:
            return "global variable";
        case PM_TOKEN_GREATER:
            return "'>'";
        case PM_TOKEN_GREATER_EQUAL:
            return "'>='";
        case PM_TOKEN_GREATER_GREATER:
            return ">>";
        case PM_TOKEN_GREATER_GREATER_EQUAL:
            return ">>=";
        case PM_TOKEN_HEREDOC_END:
            return "heredoc ending";
        case PM_TOKEN_HEREDOC_START:
            return "heredoc beginning";
        case PM_TOKEN_IDENTIFIER:
            return "local variable or method";
        case PM_TOKEN_IGNORED_NEWLINE:
            return "ignored newline";
        case PM_TOKEN_INSTANCE_VARIABLE:
            return "instance variable";
        case PM_TOKEN_INTEGER:
            return "integer";
        case PM_TOKEN_INTEGER_IMAGINARY:
            return "imaginary";
        case PM_TOKEN_INTEGER_RATIONAL:
            return "rational";
        case PM_TOKEN_INTEGER_RATIONAL_IMAGINARY:
            return "imaginary";
        case PM_TOKEN_KEYWORD_ALIAS:
            return "'alias'";
        case PM_TOKEN_KEYWORD_AND:
            return "'and'";
        case PM_TOKEN_KEYWORD_BEGIN:
            return "'begin'";
        case PM_TOKEN_KEYWORD_BEGIN_UPCASE:
            return "'BEGIN'";
        case PM_TOKEN_KEYWORD_BREAK:
            return "'break'";
        case PM_TOKEN_KEYWORD_CASE:
            return "'case'";
        case PM_TOKEN_KEYWORD_CLASS:
            return "'class'";
        case PM_TOKEN_KEYWORD_DEF:
            return "'def'";
        case PM_TOKEN_KEYWORD_DEFINED:
            return "'defined?'";
        case PM_TOKEN_KEYWORD_DO:
            return "'do'";
        case PM_TOKEN_KEYWORD_DO_LOOP:
            return "'do'";
        case PM_TOKEN_KEYWORD_ELSE:
            return "'else'";
        case PM_TOKEN_KEYWORD_ELSIF:
            return "'elsif'";
        case PM_TOKEN_KEYWORD_END:
            return "'end'";
        case PM_TOKEN_KEYWORD_END_UPCASE:
            return "'END'";
        case PM_TOKEN_KEYWORD_ENSURE:
            return "'ensure'";
        case PM_TOKEN_KEYWORD_FALSE:
            return "'false'";
        case PM_TOKEN_KEYWORD_FOR:
            return "'for'";
        case PM_TOKEN_KEYWORD_IF:
            return "'if'";
        case PM_TOKEN_KEYWORD_IF_MODIFIER:
            return "'if'";
        case PM_TOKEN_KEYWORD_IN:
            return "'in'";
        case PM_TOKEN_KEYWORD_MODULE:
            return "'module'";
        case PM_TOKEN_KEYWORD_NEXT:
            return "'next'";
        case PM_TOKEN_KEYWORD_NIL:
            return "'nil'";
        case PM_TOKEN_KEYWORD_NOT:
            return "'not'";
        case PM_TOKEN_KEYWORD_OR:
            return "'or'";
        case PM_TOKEN_KEYWORD_REDO:
            return "'redo'";
        case PM_TOKEN_KEYWORD_RESCUE:
            return "'rescue'";
        case PM_TOKEN_KEYWORD_RESCUE_MODIFIER:
            return "'rescue' modifier";
        case PM_TOKEN_KEYWORD_RETRY:
            return "'retry'";
        case PM_TOKEN_KEYWORD_RETURN:
            return "'return'";
        case PM_TOKEN_KEYWORD_SELF:
            return "'self'";
        case PM_TOKEN_KEYWORD_SUPER:
            return "'super'";
        case PM_TOKEN_KEYWORD_THEN:
            return "'then'";
        case PM_TOKEN_KEYWORD_TRUE:
            return "'true'";
        case PM_TOKEN_KEYWORD_UNDEF:
            return "'undef'";
        case PM_TOKEN_KEYWORD_UNLESS:
            return "'unless'";
        case PM_TOKEN_KEYWORD_UNLESS_MODIFIER:
            return "'unless'";
        case PM_TOKEN_KEYWORD_UNTIL:
            return "'until'";
        case PM_TOKEN_KEYWORD_UNTIL_MODIFIER:
            return "'until'";
        case PM_TOKEN_KEYWORD_WHEN:
            return "'when'";
        case PM_TOKEN_KEYWORD_WHILE:
            return "'while'";
        case PM_TOKEN_KEYWORD_WHILE_MODIFIER:
            return "'while'";
        case PM_TOKEN_KEYWORD_YIELD:
            return "'yield'";
        case PM_TOKEN_KEYWORD___ENCODING__:
            return "'__ENCODING__'";
        case PM_TOKEN_KEYWORD___FILE__:
            return "'__FILE__'";
        case PM_TOKEN_KEYWORD___LINE__:
            return "'__LINE__'";
        case PM_TOKEN_LABEL:
            return "label";
        case PM_TOKEN_LABEL_END:
            return "label terminator";
        case PM_TOKEN_LAMBDA_BEGIN:
            return "'{'";
        case PM_TOKEN_LESS:
            return "'<'";
        case PM_TOKEN_LESS_EQUAL:
            return "'<='";
        case PM_TOKEN_LESS_EQUAL_GREATER:
            return "'<=>'";
        case PM_TOKEN_LESS_LESS:
            return "<<";
        case PM_TOKEN_LESS_LESS_EQUAL:
            return "<<=";
        case PM_TOKEN_METHOD_NAME:
            return "method name";
        case PM_TOKEN_MINUS:
            return "'-'";
        case PM_TOKEN_MINUS_EQUAL:
            return "'-='";
        case PM_TOKEN_MINUS_GREATER:
            return "'->'";
        case PM_TOKEN_NEWLINE:
            return "newline";
        case PM_TOKEN_NUMBERED_REFERENCE:
            return "numbered reference";
        case PM_TOKEN_PARENTHESIS_LEFT:
            return "'('";
        case PM_TOKEN_PARENTHESIS_LEFT_PARENTHESES:
            return "'('";
        case PM_TOKEN_PARENTHESIS_RIGHT:
            return "')'";
        case PM_TOKEN_PERCENT:
            return "'%'";
        case PM_TOKEN_PERCENT_EQUAL:
            return "'%='";
        case PM_TOKEN_PERCENT_LOWER_I:
            return "'%i'";
        case PM_TOKEN_PERCENT_LOWER_W:
            return "'%w'";
        case PM_TOKEN_PERCENT_LOWER_X:
            return "'%x'";
        case PM_TOKEN_PERCENT_UPPER_I:
            return "'%I'";
        case PM_TOKEN_PERCENT_UPPER_W:
            return "'%W'";
        case PM_TOKEN_PIPE:
            return "'|'";
        case PM_TOKEN_PIPE_EQUAL:
            return "'|='";
        case PM_TOKEN_PIPE_PIPE:
            return "'||'";
        case PM_TOKEN_PIPE_PIPE_EQUAL:
            return "'||='";
        case PM_TOKEN_PLUS:
            return "'+'";
        case PM_TOKEN_PLUS_EQUAL:
            return "'+='";
        case PM_TOKEN_QUESTION_MARK:
            return "'?'";
        case PM_TOKEN_REGEXP_BEGIN:
            return "regular expression beginning";
        case PM_TOKEN_REGEXP_END:
            return "regular expression ending";
        case PM_TOKEN_SEMICOLON:
            return "';'";
        case PM_TOKEN_SLASH:
            return "'/'";
        case PM_TOKEN_SLASH_EQUAL:
            return "'/='";
        case PM_TOKEN_STAR:
            return "'*'";
        case PM_TOKEN_STAR_EQUAL:
            return "'*='";
        case PM_TOKEN_STAR_STAR:
            return "'**'";
        case PM_TOKEN_STAR_STAR_EQUAL:
            return "'**='";
        case PM_TOKEN_STRING_BEGIN:
            return "string literal";
        case PM_TOKEN_STRING_CONTENT:
            return "string content";
        case PM_TOKEN_STRING_END:
            return "string ending";
        case PM_TOKEN_SYMBOL_BEGIN:
            return "symbol literal";
        case PM_TOKEN_TILDE:
            return "'~'";
        case PM_TOKEN_UAMPERSAND:
            return "'&'";
        case PM_TOKEN_UCOLON_COLON:
            return "'::'";
        case PM_TOKEN_UDOT_DOT:
            return "'..'";
        case PM_TOKEN_UDOT_DOT_DOT:
            return "'...'";
        case PM_TOKEN_UMINUS:
            return "'-'";
        case PM_TOKEN_UMINUS_NUM:
            return "'-'";
        case PM_TOKEN_UPLUS:
            return "'+'";
        case PM_TOKEN_USTAR:
            return "*";
        case PM_TOKEN_USTAR_STAR:
            return "**";
        case PM_TOKEN_WORDS_SEP:
            return "string separator";
        case PM_TOKEN___END__:
            return "'__END__'";
        case PM_TOKEN_MAXIMUM:
            assert(false && "unreachable");
            return "";
    }

    // Provide a default, because some compilers can't determine that the above
    // switch is exhaustive.
    assert(false && "unreachable");
    return "";
}
