#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os,sys,re

kar_types = frozenset([
  "char",
  "signed char",
  "unsigned char",
  "int",
  "signed",
  "signed int",
  "unsigned",
  "unsigned int",
  "short",
  "short int",
  "short signed",
  "short signed int",
  "short unsigned",
  "short unsigned int",
  "signed short",
  "signed short int",
  "unsigned short",
  "unsigned short int",
  "long",
  "long int",
  "long signed",
  "long signed int",
  "long unsigned",
  "long unsigned int",
  "signed long",
  "signed long int",
  "unsigned long",
  "unsigned long int",
  "float",
  "double",
])

ansi_types = frozenset([
  "void",
  "wchar_t",
  "wint_t",
  "size_t",
  "long double",
])

c99_types = frozenset([
  "long long",
  "long long int",
  "long long signed",
  "long long signed int",
  "long long unsigned",
  "long long unsigned int",
  "signed long long",
  "signed long long int",
  "unsigned long long",
  "unsigned long long int",
  "char16_t",
  "char32_t",
  "errno_t",
  "int8_t",
  "int16_t",
  "int32_t",
  "int64_t",
  "int_fast8_t",
  "int_fast16_t",
  "int_fast32_t",
  "int_fast64_t",
  "int_least16_t",
  "int_least32_t",
  "int_least64_t",
  "int_least8_t",
  "uint_fast16_t",
  "uint_fast32_t",
  "uint_fast64_t",
  "uint_fast8_t",
  "uint_least16_t",
  "uint_least32_t",
  "uint_least64_t",
  "uint_least8_t",
  "intmax_t",
  "intptr_t",
  "ptrdiff_t",
  "ssize_t",
  "uint16_t",
  "uint32_t",
  "uint64_t",
  "uint64_t",
  "uint8_t",
  "uintmax_t",
  "uintptr_t",
])

c11_types = frozenset([
  "atomic_bool",
  "atomic_char",
  "atomic_schar",
  "atomic_uchar",
  "atomic_short",
  "atomic_ushort",
  "atomic_int",
  "atomic_uint",
  "atomic_long",
  "atomic_ulong",
  "atomic_llong",
  "atomic_ullong",
  "atomic_char16_t",
  "atomic_char32_t",
  "atomic_wchar_t",
  "atomic_int_least8_t",
  "atomic_uint_least8_t",
  "atomic_int_least16_t",
  "atomic_uint_least16_t",
  "atomic_int_least32_t",
  "atomic_uint_least32_t",
  "atomic_int_least64_t",
  "atomic_uint_least64_t",
  "atomic_int_fast8_t",
  "atomic_uint_fast8_t",
  "atomic_int_fast16_t",
  "atomic_uint_fast16_t",
  "atomic_int_fast32_t",
  "atomic_uint_fast32_t",
  "atomic_int_fast64_t",
  "atomic_uint_fast64_t",
  "atomic_intptr_t",
  "atomic_uintptr_t",
  "atomic_size_t",
  "atomic_ptrdiff_t",
  "atomic_intmax_t",
  "atomic_uintmax_t",
])

gnu_types = frozenset([
  "__int128",
  "signed __int128",
  "unsigned __int128",
])

cxx17_types = frozenset([
  "bool",
])

cosmo_types = frozenset([
  "bool32",
  "int128_t",
  "int_fast128_t",
  "int_least128_t",
  "uint128_t",
])

x86intrin_types = frozenset([
  "__m1",
  "__m2",
  "__m64",
  "__m128",
  "__m128_u",
  "__m128d",
  "__m128d_u",
  "__m128i",
  "__m128i_u",
  "__v16qi",
  "__v16qs",
  "__v16qu",
  "__v1di",
  "__v2df",
  "__v2di",
  "__v2du",
  "__v2sf",
  "__v2si",
  "__v4hi",
  "__v4sf",
  "__v4si",
  "__v4su",
  "__v8hi",
  "__v8hu",
  "__v8qi",
])

################################################################################

kar_kws = frozenset([
  "auto",
  "if",
  "break",
  "case",
  "while",
  "continue",
  "default",
  "return",
  "do",
  "signed",
  "else",
  "sizeof",
  "extern",
  "struct",
  "switch",
  "for",
  "goto",
  "union",
])

ansi_kws = frozenset([
  "auto",
  "if",
  "break",
  "case",
  "volatile",
  "while",
  "const",
  "register",
  "continue",
  "default",
  "return",
  "do",
  "double",
  "signed",
  "else",
  "sizeof",
  "static",
  "extern",
  "struct",
  "float",
  "switch",
  "for",
  "typedef",
  "goto",
  "union",
  "typedef",
  "enum",
])

c99_kws= frozenset([
  "_Bool",
  "_Complex",
  "_Imaginary",
  "inline",
  "restrict",
])

c11_kws = frozenset([
  "_Alignas",
  "_Alignof",
  "_Atomic",
  "_Generic",
  "_Noreturn",
  "_Static_assert",
  "_Thread_local",
])

cxx17_kws = frozenset([
  "alignas",
  "alignof",
  "asm",
  "auto",
  "bool",
  "break",
  "case",
  "catch",
  "class",
  "const",
  "const_cast",
  "constexpr",
  "continue",
  "decltype",
  "default",
  "delete",
  "do",
  "double",
  "dynamic_cast",
  "else",
  "enum",
  "explicit",
  "export",
  "extern",
  "false",
  "float",
  "for",
  "friend",
  "goto",
  "if",
  "inline",
  "mutable",
  "namespace",
  "new",
  "noexcept",
  "nullptr",
  "operator",
  "private",
  "protected",
  "public",
  "register",
  "reinterpret_cast",
  "return",
  "short",
  "signed",
  "sizeof",
  "static",
  "static_assert",
  "static_cast",
  "struct",
  "switch",
  "template",
  "this",
  "thread_local",
  "throw",
  "true",
  "try",
  "typedef",
  "typeid",
  "typename",
  "union",
  "using",
  "virtual",
  "virtual",
  "volatile",
  "volatile",
  "while",
])

cosmo_kws = frozenset([
  "pass",
  "alignas",
  "aligned",
  "alignof",
  "artificial",
  "attributeallocalign",
  "attributeallocsize",
  "autotype",
  "byanymeansnecessary",
  "compatfn",
  "decltype",
  "externinline",
  "firstclass",
  "flattenout",
  "forcealignargpointer",
  "forceinline",
  "frownedupon",
  "hasatleast",
  "hidden",
  "initarray",
  "interruptfn",
  "mallocesque",
  "mayalias",
  "memcpyesque",
  "nocallback",
  "nodebuginfo",
  "nodiscard",
  "noinline",
  "noinstrument",
  "nointerpose",
  "nooptimize",
  "noprune",
  "wontreturn",
  "nosideeffect",
  "nothrow",
  "nothrow",
  "null",
  "nullterminated",
  "paramsnonnull",
  "preinitarray",
  "printfesque",
  "privileged",
  "pureconst",
  "reallocesque",
  "relegated",
  "returnsnonnull",
  "returnspointerwithnoaliases",
  "returnstwice",
  "scanfesque",
  "strftimeesque",
  "strlenesque",
  "testonly",
  "textexit",
  "textreal",
  "textstartup",
  "textwindows",
  "thatispacked",
  "threadlocal",
  "typeof",
  "unreachable",
  "warnifused",
  "winstruct",
  "nocallersavedregisters",
  "pass",
  "alignas",
  "aligned",
  "alignof",
  "artificial",
  "attributeallocalign",
  "attributeallocsize",
  "autotype",
  "byanymeansnecessary",
  "compatfn",
  "decltype",
  "externinline",
  "firstclass",
  "flattenout",
  "forcealignargpointer",
  "forceinline",
  "frownedupon",
  "hasatleast",
  "hidden",
  "initarray",
  "interruptfn",
  "mallocesque",
  "mayalias",
  "memcpyesque",
  "nocallback",
  "nodebuginfo",
  "nodiscard",
  "noinline",
  "noinstrument",
  "nointerpose",
  "nooptimize",
  "noprune",
  "wontreturn",
  "nosideeffect",
  "nothrow",
  "nothrow",
  "null",
  "nullterminated",
  "paramsnonnull",
  "preinitarray",
  "printfesque",
  "privileged",
  "pureconst",
  "reallocesque",
  "relegated",
  "returnsnonnull",
  "returnspointerwithnoaliases",
  "returnstwice",
  "scanfesque",
  "strftimeesque",
  "strlenesque",
  "testonly",
  "textexit",
  "textreal",
  "textstartup",
  "textwindows",
  "thatispacked",
  "threadlocal",
  "typeof",
  "unreachable",
  "warnifused",
  "winstruct",
  "nocallersavedregisters",
])

################################################################################

typegroups = (("kar", kar_types),
              ("ansi", ansi_types),
              ("c99", c99_types),
              ("c11", c11_types),
              ("gnu", gnu_types),
              ("cxx17", cxx17_types),
              ("cosmo", cosmo_types),
              ("x86intrin", x86intrin_types))

kwgroups = (("kar", kar_kws),
            ("ansi", ansi_kws),
            ("c99", c99_kws),
            ("c11", c11_kws),
            ("cxx17", cxx17_kws),
            ("cosmo", cosmo_kws))

types = reduce(lambda a,b: a|b[1], typegroups, set())
kws = reduce(lambda a,b: a|b[1], kwgroups, set())

################################################################################

for name, gg, nonono in (("cosmo-c-types", typegroups, kws),
                         ("cosmo-c-keywords", kwgroups, types)):
  first = True
  sys.stdout.write("""\
(defconst %s-regex
  (let (""" % name)
  for k, vs in gg:
    sys.stdout.write(("""%s(%s (list %s))
    """ % ("" if first else "\n       ", k, """
                   """.join('"%s"' % repr(s)[1:][:-1]
                          for s in vs - nonono))).rstrip())
    first = False
  sys.stdout.write(""")
    (concat "\\<" (regexp-opt (append """)
  sys.stdout.write("""
                                     """.join(k for k,_ in gg))
  sys.stdout.write(""")) "\\>")))\n\n""")
