Newer
Older
libj / modules / x-tokenizer / include / keyword.hpp
#ifndef XTOKENIZER_KEYWORD_HPP
#define XTOKENIZER_KEYWORD_HPP
#include <string>
#include <string_util.hpp>

namespace xtokenizer
{
    /**
     * キーワード。
     */
    enum class Keyword
    {
        K_UNKNOWN,         //!< no keyword
        K_ABSTRACT,        //!< abstract
        K_ALIAS,           //!< alias
        K_ALIGN,           //!< align
        K_ASM,             //!< asm
        K_ASSERT,          //!< assert
        K_AUTO,            //!< auto
        K_BODY,            //!< body
        K_BOOL,            //!< bool
        K_BREAK,           //!< break
        K_BYTE,            //!< byte
        K_CASE,            //!< case
        K_CAST,            //!< cast
        K_CATCH,           //!< catch
        K_CDOUBLE,         //!< cdouble
        K_CENT,            //!< cent
        K_CFLOAT,          //!< cfloat
        K_CHAR,            //!< char
        K_CLASS,           //!< class
        K_CONST,           //!< const
        K_CONTINUE,        //!< continue
        K_CREAL,           //!< creal
        K_DCHAR,           //!< dchar
        K_DEBUG,           //!< debug
        K_DEFAULT,         //!< default
        K_DELEGATE,        //!< delegate
        K_DELETE,          //!< delete
        K_DEPRECATED,      //!< deprecated
        K_DO,              //!< do
        K_DOUBLE,          //!< double
        K_ELSE,            //!< else
        K_ENUM,            //!< enum
        K_EXPORT,          //!< export
        K_EXTERN,          //!< extern
        K_FALSE,           //!< false
        K_FINAL,           //!< final
        K_FINALLY,         //!< finally
        K_FLOAT,           //!< float
        K_FOR,             //!< for
        K_FOREACH,         //!< foreach
        K_FUNCTION,        //!< function
        K_FOREACH_REVERSE, //!< foreach_reverse
        K_GOTO,            //!< goto
        K_IDOUBLE,         //!< idouble
        K_IF,              //!< if
        K_IFLOAT,          //!< ifloat
        K_IMPORT,          //!< import
        K_IN,              //!< in
        K_INOUT,           //!< inout
        K_INT,             //!< int
        K_INTERFACE,       //!< interface
        K_INVARIANT,       //!< invariant
        K_IREAL,           //!< ireal
        K_IS,              //!< is
        K_LAZY,            //!< lazy
        K_LONG,            //!< long
        K_MACRO,           //!< macro
        K_MIXIN,           //!< mixin
        K_MODULE,          //!< module
        K_NEW,             //!< new
        K_NOTHROW,         //!< nothrow
        K_NULL,            //!< null
        K_NULLPTR,         //!< nullptr
        K_OUT,             //!< out
        K_OVERRIDE,        //!< override
        K_PACKAGE,         //!< package
        K_PRAGMA,          //!< pragma
        K_PRIVATE,         //!< private
        K_PROTECTED,       //!< protected
        K_PUBLIC,          //!< public
        K_PURE,            //!< pure
        K_REAL,            //!< real
        K_REF,             //!< ref
        K_RETURN,          //!< return
        K_SCOPE,           //!< scope
        K_SHARED,          //!< shared
        K_SHORT,           //!< short
        K_STATIC,          //!< static
        K_STRUCT,          //!< struct
        K_SUPER,           //!< super
        K_SWITCH,          //!< switch
        K_SYNCHRONIZED,    //!< synchronized
        K_TEMPLATE,        //!< template
        K_THIS,            //!< this
        K_THROW,           //!< throw
        K_TRUE,            //!< true
        K_TRY,             //!< try
        K_TYPEDEF,         //!< typedef
        K_TYPEID,          //!< typeid
        K_TYPEOF,          //!< typeof
        K_UBYTE,           //!< ubyte
        K_UCENT,           //!< ucent
        K_UINT,            //!< uint
        K_ULONG,           //!< ulong
        K_UNION,           //!< union
        K_UNITTEST,        //!< unittest
        K_USHORT,          //!< ushort
        K_VERSION,         //!< version
        K_VOID,            //!< void
        K_VOLATILE,        //!< volatile
        K_WCHAR,           //!< wchar
        K_WHILE,           //!< while
        K_WITH,            //!< with
        K___FILE__,        //!< __FILE__
        K___FUNC__,        //!< __FUNC__
        K___LINE__,        //!< __LINE__
        K___GSHARED,       //!< __gshared
        K___THREAD,        //!< __thread
        K___TRAITS         //!< __traits
    };

    /**
     * キーワード情報
     */
    struct KeywordInfo
    {
        const Keyword keyword;
        const char *str;
        int len;
        const KeywordInfo *next;

        // constexpr コンストラクタ
        constexpr KeywordInfo(const Keyword k, const char *s, const KeywordInfo *n = nullptr)
            : keyword(k), str(s), len(constexpr_strlen(s)), next(n) {}
    };

    namespace
    {
        // 最長一致検索するため、next のリンクは長い物から順にすること。
        constexpr KeywordInfo knop = {Keyword::K_UNKNOWN, ""};

        // a
        constexpr KeywordInfo a0 = {Keyword::K_ABSTRACT, "abstract"};
        constexpr KeywordInfo a1 = {Keyword::K_ALIAS, "alias", &a0};
        constexpr KeywordInfo a2 = {Keyword::K_ALIGN, "align", &a1};
        constexpr KeywordInfo a3 = {Keyword::K_ASM, "asm", &a2};
        constexpr KeywordInfo a4 = {Keyword::K_ASSERT, "assert", &a3};
        constexpr KeywordInfo a5 = {Keyword::K_AUTO, "auto", &a4};

        // b
        constexpr KeywordInfo b0 = {Keyword::K_BODY, "body"};
        constexpr KeywordInfo b1 = {Keyword::K_BOOL, "bool", &b0};
        constexpr KeywordInfo b2 = {Keyword::K_BREAK, "break", &b1};
        constexpr KeywordInfo b3 = {Keyword::K_BYTE, "byte", &b2};

        // c
        constexpr KeywordInfo c0 = {Keyword::K_CASE, "case"};
        constexpr KeywordInfo c1 = {Keyword::K_CAST, "cast", &c0};
        constexpr KeywordInfo c2 = {Keyword::K_CATCH, "catch", &c1};
        constexpr KeywordInfo c3 = {Keyword::K_CDOUBLE, "cdouble", &c2};
        constexpr KeywordInfo c4 = {Keyword::K_CENT, "cent", &c3};
        constexpr KeywordInfo c5 = {Keyword::K_CFLOAT, "cfloat", &c4};
        constexpr KeywordInfo c6 = {Keyword::K_CHAR, "char", &c5};
        constexpr KeywordInfo c7 = {Keyword::K_CLASS, "class", &c6};
        constexpr KeywordInfo c8 = {Keyword::K_CONST, "const", &c7};
        constexpr KeywordInfo c9 = {Keyword::K_CONTINUE, "continue", &c8};
        constexpr KeywordInfo c10 = {Keyword::K_CREAL, "creal", &c9};

        // d
        constexpr KeywordInfo d0 = {Keyword::K_DCHAR, "dchar"};
        constexpr KeywordInfo d1 = {Keyword::K_DEBUG, "debug", &d0};
        constexpr KeywordInfo d2 = {Keyword::K_DEFAULT, "default", &d1};
        constexpr KeywordInfo d3 = {Keyword::K_DELEGATE, "delegate", &d2};
        constexpr KeywordInfo d4 = {Keyword::K_DELETE, "delete", &d3};
        constexpr KeywordInfo d5 = {Keyword::K_DEPRECATED, "deprecated", &d4};
        constexpr KeywordInfo d6 = {Keyword::K_DO, "do", &d5};
        constexpr KeywordInfo d7 = {Keyword::K_DOUBLE, "double", &d6};

        // e
        constexpr KeywordInfo e0 = {Keyword::K_ELSE, "else"};
        constexpr KeywordInfo e1 = {Keyword::K_ENUM, "enum", &e0};
        constexpr KeywordInfo e2 = {Keyword::K_EXPORT, "export", &e1};
        constexpr KeywordInfo e3 = {Keyword::K_EXTERN, "extern", &e2};

        // f
        constexpr KeywordInfo f0 = {Keyword::K_FALSE, "false"};
        constexpr KeywordInfo f1 = {Keyword::K_FINAL, "final", &f0};
        constexpr KeywordInfo f2 = {Keyword::K_FINALLY, "finally", &f1};
        constexpr KeywordInfo f3 = {Keyword::K_FLOAT, "float", &f2};
        constexpr KeywordInfo f4 = {Keyword::K_FOR, "for", &f3};
        constexpr KeywordInfo f5 = {Keyword::K_FOREACH, "foreach", &f4};
        constexpr KeywordInfo f6 = {Keyword::K_FUNCTION, "function", &f5};
        constexpr KeywordInfo f7 = {Keyword::K_FOREACH_REVERSE, "foreach_reverse", &f6};

        // g
        constexpr KeywordInfo g0 = {Keyword::K_GOTO, "goto"};

        // i
        constexpr KeywordInfo i0 = {Keyword::K_IDOUBLE, "idouble"};
        constexpr KeywordInfo i1 = {Keyword::K_IF, "if", &i0};
        constexpr KeywordInfo i2 = {Keyword::K_IFLOAT, "ifloat", &i1};
        constexpr KeywordInfo i3 = {Keyword::K_IMPORT, "import", &i2};
        constexpr KeywordInfo i4 = {Keyword::K_IN, "in", &i3};
        constexpr KeywordInfo i5 = {Keyword::K_INOUT, "inout", &i4};
        constexpr KeywordInfo i6 = {Keyword::K_INT, "int", &i5};
        constexpr KeywordInfo i7 = {Keyword::K_INTERFACE, "interface", &i6};
        constexpr KeywordInfo i8 = {Keyword::K_INVARIANT, "invariant", &i7};
        constexpr KeywordInfo i9 = {Keyword::K_IREAL, "ireal", &i8};
        constexpr KeywordInfo i10 = {Keyword::K_IS, "is", &i9};

        // l
        constexpr KeywordInfo l0 = {Keyword::K_LAZY, "lazy"};
        constexpr KeywordInfo l1 = {Keyword::K_LONG, "long", &l0};

        // m
        constexpr KeywordInfo m0 = {Keyword::K_MACRO, "macro"};
        constexpr KeywordInfo m1 = {Keyword::K_MIXIN, "mixin", &m0};
        constexpr KeywordInfo m2 = {Keyword::K_MODULE, "module", &m1};

        // n
        constexpr KeywordInfo n0 = {Keyword::K_NEW, "new"};
        constexpr KeywordInfo n1 = {Keyword::K_NOTHROW, "nothrow", &n0};
        constexpr KeywordInfo n2 = {Keyword::K_NULL, "null", &n1};
        constexpr KeywordInfo n3 = {Keyword::K_NULLPTR, "nullptr", &n2};

        // n
        constexpr KeywordInfo o0 = {Keyword::K_OUT, "out"};
        constexpr KeywordInfo o1 = {Keyword::K_OVERRIDE, "override", &o0};

        // p
        constexpr KeywordInfo p0 = {Keyword::K_PACKAGE, "package"};
        constexpr KeywordInfo p1 = {Keyword::K_PRAGMA, "pragma", &p0};
        constexpr KeywordInfo p2 = {Keyword::K_PRIVATE, "private", &p1};
        constexpr KeywordInfo p3 = {Keyword::K_PROTECTED, "protected", &p2};
        constexpr KeywordInfo p4 = {Keyword::K_PUBLIC, "public", &p3};
        constexpr KeywordInfo p5 = {Keyword::K_PURE, "pure", &p4};

        // r
        constexpr KeywordInfo r0 = {Keyword::K_REAL, "real"};
        constexpr KeywordInfo r1 = {Keyword::K_REF, "ref", &r0};
        constexpr KeywordInfo r2 = {Keyword::K_RETURN, "return", &r1};

        // s
        constexpr KeywordInfo s0 = {Keyword::K_SCOPE, "scope"};
        constexpr KeywordInfo s1 = {Keyword::K_SHARED, "shared", &s0};
        constexpr KeywordInfo s2 = {Keyword::K_SHORT, "short", &s1};
        constexpr KeywordInfo s3 = {Keyword::K_STATIC, "static", &s2};
        constexpr KeywordInfo s4 = {Keyword::K_STRUCT, "struct", &s3};
        constexpr KeywordInfo s5 = {Keyword::K_SUPER, "super", &s4};
        constexpr KeywordInfo s6 = {Keyword::K_SWITCH, "switch", &s5};
        constexpr KeywordInfo s7 = {Keyword::K_SYNCHRONIZED, "synchronized", &s6};

        // t
        constexpr KeywordInfo t0 = {Keyword::K_TEMPLATE, "template"};
        constexpr KeywordInfo t1 = {Keyword::K_THIS, "this", &t0};
        constexpr KeywordInfo t2 = {Keyword::K_THROW, "throw", &t1};
        constexpr KeywordInfo t3 = {Keyword::K_TRUE, "true", &t2};
        constexpr KeywordInfo t4 = {Keyword::K_TRY, "try", &t3};
        constexpr KeywordInfo t5 = {Keyword::K_TYPEDEF, "typedef", &t4};
        constexpr KeywordInfo t6 = {Keyword::K_TYPEID, "typeid", &t5};
        constexpr KeywordInfo t7 = {Keyword::K_TYPEOF, "typeof", &t6};

        // u
        constexpr KeywordInfo u0 = {Keyword::K_UBYTE, "ubyte"};
        constexpr KeywordInfo u1 = {Keyword::K_UCENT, "ucent", &u0};
        constexpr KeywordInfo u2 = {Keyword::K_UINT, "uint", &u1};
        constexpr KeywordInfo u3 = {Keyword::K_ULONG, "ulong", &u2};
        constexpr KeywordInfo u4 = {Keyword::K_UNION, "union", &u3};
        constexpr KeywordInfo u5 = {Keyword::K_UNITTEST, "unittest", &u4};
        constexpr KeywordInfo u6 = {Keyword::K_USHORT, "ushort", &u5};

        // u
        constexpr KeywordInfo v0 = {Keyword::K_VERSION, "version"};
        constexpr KeywordInfo v1 = {Keyword::K_VOID, "void", &v0};
        constexpr KeywordInfo v2 = {Keyword::K_VOLATILE, "volatile", &v1};

        // w
        constexpr KeywordInfo w0 = {Keyword::K_WCHAR, "wchar"};
        constexpr KeywordInfo w1 = {Keyword::K_WHILE, "while", &w0};
        constexpr KeywordInfo w2 = {Keyword::K_WITH, "with", &w1};

        // _
        constexpr KeywordInfo _0 = {Keyword::K___FILE__, "__FILE__"};
        constexpr KeywordInfo _1 = {Keyword::K___FUNC__, "__FUNC__", &_0};
        constexpr KeywordInfo _2 = {Keyword::K___LINE__, "__LINE__", &_1};
        constexpr KeywordInfo _3 = {Keyword::K___GSHARED, "__gshared", &_2};
        constexpr KeywordInfo _4 = {Keyword::K___THREAD, "__thread", &_3};
        constexpr KeywordInfo _5 = {Keyword::K___TRAITS, "__traits", &_4};

        constexpr KeywordInfo keywordInfoTable[] = {
            // 0     1     2     3     4     5     6     7     8     9     A     B     C     D     E     F
            knop, knop, knop, knop, knop, knop, knop, knop, knop, knop, knop, knop, knop, knop, knop, knop, // 制御コード
            knop, knop, knop, knop, knop, knop, knop, knop, knop, knop, knop, knop, knop, knop, knop, knop, // 制御コード

            knop, // 0x20: SPA (空白文字)
            knop, // 0x21: !
            knop, // 0x22: "
            knop, // 0x23: #
            knop, // 0x24: $
            knop, // 0x25: %
            knop, // 0x26: &
            knop, // 0x27: '
            knop, // 0x28: (
            knop, // 0x29: )
            knop, // 0x2A: *
            knop, // 0x2B: +
            knop, // 0x2C: ,
            knop, // 0x2D: -
            knop, // 0x2E: .
            knop, // 0x2F: /
            knop, // 0x30: 0
            knop, // 0x31: 1
            knop, // 0x32: 2
            knop, // 0x33: 3
            knop, // 0x34: 4
            knop, // 0x35: 5
            knop, // 0x36: 6
            knop, // 0x37: 7
            knop, // 0x38: 8
            knop, // 0x39: 9
            knop, // 0x3A: :
            knop, // 0x3B: ;
            knop, // 0x3C: <
            knop, // 0x3D: =
            knop, // 0x3E: >
            knop, // 0x3F: ?
            knop, // 0x40: @
            knop, // 0x41: A
            knop, // 0x42: B
            knop, // 0x43: C
            knop, // 0x44: D
            knop, // 0x45: E
            knop, // 0x46: F
            knop, // 0x47: G
            knop, // 0x48: H
            knop, // 0x49: I
            knop, // 0x4A: J
            knop, // 0x4B: K
            knop, // 0x4C: L
            knop, // 0x4D: M
            knop, // 0x4E: N
            knop, // 0x4F: O
            knop, // 0x50: P
            knop, // 0x51: Q
            knop, // 0x52: R
            knop, // 0x53: S
            knop, // 0x54: T
            knop, // 0x55: U
            knop, // 0x56: V
            knop, // 0x57: W
            knop, // 0x58: X
            knop, // 0x59: Y
            knop, // 0x5A: Z
            knop, // 0x5B: [
            knop, // 0x5C: '\'
            knop, // 0x5D: ]
            knop, // 0x5E: ^
            _5,   // 0x5F: _
            knop, // 0x60: `
            a5,   // 0x61: a
            b3,   // 0x62: b
            c10,  // 0x63: c
            d7,   // 0x64: d
            e3,   // 0x65: e
            f7,   // 0x66: f
            g0,   // 0x67: g
            knop, // 0x68: h
            i10,  // 0x69: i
            knop, // 0x6A: j
            knop, // 0x6B: k
            l1,   // 0x6C: l
            m2,   // 0x6D: m
            n3,   // 0x6E: n
            o1,   // 0x6F: o
            p5,   // 0x70: p
            knop, // 0x71: q
            r2,   // 0x72: r
            s7,   // 0x73: s
            t7,   // 0x74: t
            u6,   // 0x75: u
            v2,   // 0x76: v
            w2,   // 0x77: w
            knop, // 0x78: x
            knop, // 0x79: y
            knop, // 0x7A: z
            knop, // 0x7B: {
            knop, // 0x7C: |
            knop, // 0x7D: }
            knop, // 0x7E: }
            knop, // 0x7F: DEL(削除)
        };
    }

    /**
     * 指定されたトークンがキーワードである場合、対象のキーワード情報を返します。
     *
     * @param token トークン文字列
     * @return キーワード情報
     */
    inline const KeywordInfo getKeywordInfo(const std::string &token)
    {
        const KeywordInfo *info = &keywordInfoTable[static_cast<uint8_t>(token[0])];
        if (info == &knop)
        { // キーワードでない
            return knop;
        }

        while (info != nullptr)
        {
            if (token == info->str)
            {
                return *info;
            }
            info = info->next;
        }
        return knop;
    }

} // namespcae xtokenizer
#endif // XTOKENIZER_KEYWORD_HPP