-<ENGLISH>{
- "variable-length" return T_VLA;
- "type" return T_TYPE;
- "declare" return T_DECLARE;
- "pointer" return T_POINTER;
- "function" return T_FUNCTION;
- "returning" return T_RETURNING;
- "array" return T_ARRAY;
- "to" return T_TO;
- "of" return T_OF;
- "as" return T_AS;
+{IDENT} {
+ unsigned x = cdecl__to_keyword(yytext, yyleng, yyextra);
+ int tok;
+
+ yylval->spectype = UNPACK_SPEC(x & 0xff);
+ if ((tok = (x >> 8)) == PACK_TOKEN(T_IDENT)) {
+ /*
+ * Our IDENT pattern includes hyphens so we can match
+ * "variable-length" as a keyword. In all other cases a
+ * hyphen is an error.
+ *
+ * We could use yyless to re-scan the hyphen and hit the
+ * error catch-all, but jumping straight to the error code
+ * seems to produce better results with gcc with no obvious
+ * downsides.
+ */
+#if 1
+ if ((c = strchr(yytext, '-')))
+ goto invalid_char;
+#else
+ yyless(strcspn(yytext, "-"));
+#endif
+ if (!(yylval->item = cdecl__alloc_item(yyleng+1)))
+ return T_LEX_ERROR; \
+ memcpy(yylval->item->s, yytext, yyleng+1);
+ }
+ return UNPACK_TOKEN(tok);