%{ /* YACC grammar for reading Keyman-style keyboard definition files and outputting UTF-8 byte code for the Linux interpreter */ #include #include #include #include "compiler.h" extern char *fname; /* Current file name */ extern int yylex(); /* Reference needed by yacc.c */ int lineno = 1; /* Current line number in file */ int errcount = 0; /* Count of errors */ int n; /* Temporary index value */ GROUP *gp = NULL; /* Temporary group pointer */ #define YYDEBUG 1 /* Allow compiler debugging (if yydebug true) */ %} %union { int simple; ITEM number; char *string; ITEM *items; RULE *rule; GROUP *group; } %type T_BYTES %type T_FILE %type T_GHEADER %type T_GROUP %type T_GROUPS %type T_HEADER %type T_HEADLINE %type T_KEYDEF %type T_KEYMODS %type T_ITEM %type T_ITEMS %type T_PARAMETER %type T_RULELINE %type T_RULES %type T_STRING %token TOK_ANY %token TOK_ANSI %token TOK_AUTHOR %token TOK_BEEP %token TOK_BITMAP %token TOK_BRKT %token TOK_CALL %token TOK_CAPSFREE %token TOK_CAPSOFF %token TOK_CAPSON %token TOK_COMMA %token TOK_CONTEXT %token TOK_COPYRIGHT %token TOK_CHAR %token TOK_DEADKEY %token TOK_DOLLAR %token TOK_ERROR %token TOK_ETHNOLOGUE %token TOK_GROUP %token TOK_GT %token TOK_HOTKEY %token TOK_INDEX %token TOK_LANGUAGE %token TOK_LAYOUT %token TOK_MATCH %token TOK_MESSAGE %token TOK_MNEMONIC %token TOK_NOMATCH %token TOK_NAME %token TOK_NUL %token TOK_NUMBER %token TOK_NL %token TOK_OUTS %token TOK_RAWKEY %token TOK_PLUS %token TOK_QM %token TOK_RTN %token TOK_SB %token TOK_SHIFT %token TOK_STORE %token TOK_STOREINSTORE %token TOK_SWITCH %token TOK_UNICODE %token TOK_USE %token TOK_USINGKEYS %token TOK_UTF %token TOK_VERSION %token TOK_XKEYSYM %% T_FILE : T_HEADER T_GROUPS { kbp->groups = $2; kbp->ngroups = count_groups($2); kbp->nstores = count_stores(kbp->stores); } | T_GROUPS { kbp->groups = $1; kbp->ngroups = count_groups($1); kbp->nstores = count_stores(kbp->stores); } ; T_HEADER : T_HEADLINE | T_HEADLINE T_HEADER ; T_HEADLINE : TOK_NAME T_BYTES TOK_NL { new_store_from_string("&name",$2,lineno); } | TOK_NAME T_STRING TOK_NL { new_store_from_string("&name",$2,lineno); } | TOK_HOTKEY TOK_SB T_KEYDEF TOK_SB TOK_NL { new_store("&hotkey",new_list($3),lineno); } | TOK_HOTKEY T_STRING TOK_NL { new_store_from_string("&hotkey",$2,lineno); } | TOK_VERSION T_BYTES TOK_NL { new_store_from_string("&version",$2,lineno); } | TOK_VERSION T_STRING TOK_NL { new_store_from_string("&version",$2,lineno); } | TOK_BITMAP T_BYTES TOK_NL { new_store_from_string("&bitmap",$2,lineno); } | TOK_BITMAP T_STRING TOK_NL { new_store_from_string("&bitmap",$2,lineno); } | TOK_COPYRIGHT T_STRING TOK_NL { new_store_from_string("©right",$2,lineno); } | TOK_MESSAGE T_STRING TOK_NL { new_store_from_string("&message",$2,lineno); } | TOK_LANGUAGE T_ITEMS TOK_NL { new_store_from_string("&language",$2,lineno); } | TOK_LAYOUT T_STRING TOK_NL { new_store_from_string("&layout",$2,lineno); } | TOK_LAYOUT T_BYTES TOK_NL { new_store_from_string("&layout",$2,lineno); } | TOK_CAPSOFF TOK_NL { new_store_from_string("&capsalwaysoff","1",lineno); } | TOK_CAPSON TOK_NL { new_store_from_string("&capsononly","1",lineno); } | TOK_CAPSFREE TOK_NL { new_store_from_string("&shiftfreescaps","1",lineno); } | TOK_STORE T_PARAMETER T_ITEMS TOK_NL { new_store($2,$3,lineno); } | TOK_ANSI TOK_GT TOK_USE T_PARAMETER TOK_NL { set_start_group($4,KF_ANSI, lineno); } | TOK_UNICODE TOK_GT TOK_USE T_PARAMETER TOK_NL { set_start_group($4,KF_UNICODE, lineno); } | TOK_ANSI TOK_GT TOK_USE T_PARAMETER TOK_USE T_PARAMETER TOK_NL { kmflcomp_error(lineno,"alternate starting groups not supported"); fail(11,"obsolete syntax"); } | TOK_AUTHOR T_STRING TOK_NL { new_store_from_string("&author",$2,lineno); } | TOK_MNEMONIC T_STRING TOK_NL { new_store_from_string("&mnemoniclayout",$2,lineno); } | TOK_ETHNOLOGUE T_STRING TOK_NL { new_store_from_string("ðnologuecode",$2,lineno); } | TOK_ERROR T_BYTES TOK_NL | TOK_NL ; T_GROUPS : T_GROUP { $$ = kbp->groups; } | T_GROUP T_GROUPS { $$ = kbp->groups; } ; T_GROUP : T_GHEADER { $$ = $1; ($$)->rules = NULL; ($$)->nrules = 0; kmflcomp_warn(0,"group(%s) is empty!",($1)->name); } | T_GHEADER T_RULES { $$ = $1; ($$)->rules = $2; ($$)->nrules = count_rules($2); if(($$)->nrules == 0) kmflcomp_warn(0,"group(%s) is empty!",($1)->name); } ; T_GHEADER : TOK_GROUP T_PARAMETER TOK_NL { $$ = gp = new_group($2, lineno); if(gp) gp->flags = 0; } | TOK_GROUP T_PARAMETER TOK_USINGKEYS TOK_NL { $$ = gp = new_group($2, lineno); if(gp) gp->flags = GF_USEKEYS; } ; T_RULES : T_RULELINE { $$ = $1; } | T_RULELINE T_RULES { $$ = add_rule($1, $2); } ; T_RULELINE : T_ITEMS TOK_GT T_ITEMS TOK_NL { $$ = new_rule(gp, $1, $3, lineno); } | TOK_STORE T_PARAMETER T_ITEMS TOK_NL { new_store($2,$3,lineno); $$ = NULL; } | TOK_NL { $$ = NULL; } ; T_ITEMS : T_ITEM { $$ = new_list($1); } | T_STRING { $$ = items_from_string($1,lineno); } | T_ITEM T_ITEMS { $$ = add_item_to_list($2,$1); } | T_STRING T_ITEMS { $$ = add_lists($2,items_from_string($1,lineno)); } ; T_ITEM : TOK_NUMBER { $$ = MAKE_ITEM(ITEM_CHAR,$1); } | TOK_SB T_KEYDEF TOK_SB { $$ = MAKE_ITEM(ITEM_KEYSYM,$2); } | TOK_PLUS { $$ = MAKE_ITEM(ITEM_PLUS,0); /* include in item list - remove later when testing validity */ } | TOK_ANY T_PARAMETER { if((n=store_number($2,lineno)) != UNDEFINED) { $$ = MAKE_ITEM(ITEM_ANY,n); } else { kmflcomp_warn(lineno,"store (%s) is undefined!",$2); $$ = 0; } } | TOK_OUTS T_PARAMETER { if((n=store_number($2,lineno)) != UNDEFINED) { $$ = MAKE_ITEM(ITEM_OUTS,n); } else { kmflcomp_warn(lineno,"store (%s) is undefined!",$2); $$ = 0; } } | TOK_DEADKEY T_PARAMETER { $$ = MAKE_ITEM(ITEM_DEADKEY,deadkey_number($2, lineno)); } | TOK_NUL { $$ = MAKE_ITEM(ITEM_NUL,0); } | TOK_INDEX TOK_BRKT T_BYTES TOK_COMMA T_BYTES TOK_BRKT { if((n=store_number($3,lineno)) != UNDEFINED) { $$ = MAKE_PARAMETER_ITEM(ITEM_INDEX,atoi($5),n); } else { kmflcomp_warn(lineno,"store (%s) is undefined!",$3); $$ = 0; } } | TOK_INDEX TOK_BRKT T_BYTES TOK_BRKT { kmflcomp_warn(lineno,"index(%s) must have TWO parameters!",$3); $$ = 0; } | TOK_RTN { $$ = MAKE_ITEM(ITEM_RETURN,0); } | TOK_BEEP { $$ = MAKE_ITEM(ITEM_BEEP,0); } | TOK_CONTEXT { $$ = MAKE_ITEM(ITEM_CONTEXT,0); } | TOK_CONTEXT TOK_BRKT T_BYTES TOK_BRKT { $$ = MAKE_ITEM(ITEM_CONTEXT,atoi($3)); } | TOK_USE T_PARAMETER { $$ = MAKE_ITEM(ITEM_USE,group_number($2, lineno)); } | TOK_MATCH { $$ = MAKE_ITEM(ITEM_MATCH,0); } | TOK_NOMATCH { $$ = MAKE_ITEM(ITEM_NOMATCH,0); } | TOK_CALL T_PARAMETER { kmflcomp_error(lineno,"call keyword not implemented"); fail(12,"unsupported keyword"); } | TOK_SWITCH T_PARAMETER { kmflcomp_error(lineno,"switch keyword not implemented"); fail(11,"obsolete syntax"); } | TOK_DOLLAR T_BYTES { STORE *sp; /* check for named constants */ sp = find_store($2); if(sp) { $$ = *sp->items; } else { $$ = 0; kmflcomp_error(lineno,"undefined constant"); } } | TOK_ERROR { kmflcomp_error(lineno,"illegal or unrecognized item in rule or store"); } ; T_STRING : TOK_QM T_BYTES TOK_QM { $$ = $2; } | TOK_QM TOK_QM { $$ = new_string(0); /* allow for empty strings */ } ; T_PARAMETER: TOK_BRKT T_BYTES TOK_BRKT { $$ = $2; } ; T_KEYDEF : T_STRING { $$ = make_keysym(lineno, 0,string_to_keysym($1,lineno)); } | T_KEYMODS T_STRING { $$ = make_keysym(lineno, 0,string_to_keysym($2,lineno)); } | T_KEYMODS TOK_RAWKEY { $$ = make_keysym(lineno, $1,$2); } | TOK_RAWKEY { $$ = make_keysym(lineno, 0,$1); } | T_KEYMODS TOK_XKEYSYM { $$ = make_xkeysym(lineno, $1, $2); } | TOK_XKEYSYM { $$ = make_xkeysym(lineno, 0, $1); } ; T_KEYMODS : T_KEYMODS TOK_SHIFT { $$ = $1 | $2; } | TOK_SHIFT { $$ = $1; } ; T_BYTES : TOK_CHAR { $$ = new_string($1); } | TOK_CHAR T_BYTES { $$ = add_char($2,$1); } ; %% void yyerror(char *str) { fflush (stdout); (void) fflush (stderr); fprintf (stderr, "Error: %s (line %d)\n", str, lineno); fflush (stderr); errcount++; } #ifdef _WIN32 int yywrap(void) { return 1; } #endif