+%{
+/*
+ * Copyright © 2023 Nick Bowler
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <string.h>
+#include <inttypes.h>
+#include "cdecl-internal.h"
+#include "parse.h"
+
+static const struct keyword *in_word_set();
+%}
+
+%struct-type
+%readonly-tables
+%language=ANSI-C
+%global-table
+%pic
+
+struct keyword {
+ int_least16_t name;
+ uint_least8_t token;
+};
+%%
+_Bool, (T_BOOL & 0x7f)
+_Complex, (T_COMPLEX & 0x7f)
+_Imaginary, (T_IMAGINARY & 0x7f)
+auto, (T_AUTO & 0x7f)
+char, (T_CHAR & 0x7f)
+const, (T_CONST & 0x7f)
+double, (T_DOUBLE & 0x7f)
+enum, (T_ENUM & 0x7f)
+extern, (T_EXTERN & 0x7f)
+float, (T_FLOAT & 0x7f)
+inline, (T_INLINE & 0x7f)
+int, (T_INT & 0x7f)
+long, (T_LONG & 0x7f)
+register, (T_REGISTER & 0x7f)
+restrict, (T_RESTRICT & 0x7f)
+short, (T_SHORT & 0x7f)
+signed, (T_SIGNED & 0x7f)
+static, (T_STATIC & 0x7f)
+struct, (T_STRUCT & 0x7f)
+typedef, (T_TYPEDEF & 0x7f)
+union, (T_UNION & 0x7f)
+unsigned, (T_UNSIGNED & 0x7f)
+void, (T_VOID & 0x7f)
+volatile, (T_VOLATILE & 0x7f)
+# english keywords
+array, (T_ARRAY & 0x7f) | 0x80
+as, (T_AS & 0x7f) | 0x80
+declare, (T_DECLARE & 0x7f) | 0x80
+function, (T_FUNCTION & 0x7f) | 0x80
+of, (T_OF & 0x7f) | 0x80
+pointer, (T_POINTER & 0x7f) | 0x80
+returning, (T_RETURNING & 0x7f) | 0x80
+to, (T_TO & 0x7f) | 0x80
+type, (T_TYPE & 0x7f) | 0x80
+variable-length, (T_VLA & 0x7f) | 0x80
+%%
+int cdecl__to_keyword(const char *s, int len, int english_mode)
+{
+ const struct keyword *k;
+
+ if ((k = in_word_set(s, len))) {
+ unsigned x = (k->token & 0x7fu);
+
+ if (english_mode || !(k->token & ~0x7fu)) {
+ if (T_VOID >= 256)
+ x += 256;
+ return x;
+ }
+ }
+
+ return T_IDENT;
+}