1 /************************************************************
2 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 ********************************************************/
28 * The parser should work with reasonably recent versions of either
29 * bison or byacc. So if you make changes, try to make sure it works
34 #include "xkbcomp-priv.h"
35 #include "ast-build.h"
36 #include "parser-priv.h"
39 struct xkb_context *ctx;
40 struct scanner *scanner;
45 #define parser_err(param, fmt, ...) \
46 scanner_err((param)->scanner, fmt, ##__VA_ARGS__)
48 #define parser_warn(param, fmt, ...) \
49 scanner_warn((param)->scanner, fmt, ##__VA_ARGS__)
52 _xkbcommon_error(struct parser_param *param, const char *msg)
54 parser_err(param, "%s", msg);
58 resolve_keysym(const char *str, xkb_keysym_t *sym_rtrn)
62 if (!str || istreq(str, "any") || istreq(str, "nosymbol")) {
63 *sym_rtrn = XKB_KEY_NoSymbol;
67 if (istreq(str, "none") || istreq(str, "voidsymbol")) {
68 *sym_rtrn = XKB_KEY_VoidSymbol;
72 sym = xkb_keysym_from_name(str, XKB_KEYSYM_NO_FLAGS);
73 if (sym != XKB_KEY_NoSymbol) {
81 #define param_scanner param->scanner
85 %lex-param { struct scanner *param_scanner }
86 %parse-param { struct parser_param *param }
164 enum xkb_file_type file_type;
167 enum merge_mode merge;
168 enum xkb_map_flags mapFlags;
178 GroupCompatDef *groupCompat;
182 KeyAliasDef *keyAlias;
187 %type <num> INTEGER FLOAT
188 %type <str> IDENT STRING
191 %type <ival> Number Integer Float SignedNumber DoodadType
192 %type <merge> MergeMode OptMergeMode
193 %type <file_type> XkbCompositeType FileType
194 %type <mapFlags> Flag Flags OptFlags
195 %type <str> MapName OptMapName
196 %type <sval> FieldSpec Ident Element String
197 %type <keysym> KeySym
198 %type <any> DeclList Decl
199 %type <expr> OptExprList ExprList Expr Term Lhs Terminal ArrayInit KeySyms
200 %type <expr> OptKeySymList KeySymList Action ActionList Coord CoordList
201 %type <var> VarDecl VarDeclList SymbolsBody SymbolsVarDecl
202 %type <vmod> VModDecl VModDefList VModDef
203 %type <interp> InterpretDecl InterpretMatch
204 %type <keyType> KeyTypeDecl
205 %type <syms> SymbolsDecl
206 %type <modMask> ModMapDecl
207 %type <groupCompat> GroupCompatDecl
208 %type <ledMap> LedMapDecl
209 %type <ledName> LedNameDecl
210 %type <keyCode> KeyNameDecl
211 %type <keyAlias> KeyAliasDecl
212 %type <geom> ShapeDecl SectionDecl SectionBody SectionBodyItem RowBody RowBodyItem
213 %type <geom> Keys Key OverlayDecl OverlayKeyList OverlayKey OutlineList OutlineInList
214 %type <geom> DoodadDecl
215 %type <file> XkbFile XkbMapConfigList XkbMapConfig
216 %type <file> XkbCompositeMap
221 * An actual file may contain more than one map. However, if we do things
222 * in the normal yacc way, i.e. aggregate all of the maps into a list and
223 * let the caller find the map it wants, we end up scanning and parsing a
224 * lot of unneeded maps (in the end we always just need one).
225 * Instead of doing that, we make yyparse return one map at a time, and
226 * then call it repeatedly until we find the map we need. Once we find it,
227 * we don't need to parse everything that follows in the file.
228 * This does mean that if we e.g. always use the first map, the file may
229 * contain complete garbage after that. But it's worth it.
232 XkbFile : XkbCompositeMap
233 { $$ = param->rtrn = $1; param->more_maps = true; }
235 { $$ = param->rtrn = $1; param->more_maps = true; YYACCEPT; }
237 { $$ = param->rtrn = NULL; param->more_maps = false; }
240 XkbCompositeMap : OptFlags XkbCompositeType OptMapName OBRACE
243 { $$ = XkbFileCreate($2, $3, &$5->common, $1); }
246 XkbCompositeType: XKB_KEYMAP { $$ = FILE_TYPE_KEYMAP; }
247 | XKB_SEMANTICS { $$ = FILE_TYPE_KEYMAP; }
248 | XKB_LAYOUT { $$ = FILE_TYPE_KEYMAP; }
251 XkbMapConfigList : XkbMapConfigList XkbMapConfig
256 $$ = (XkbFile *)AppendStmt(&$1->common, &$2->common);
262 XkbMapConfig : OptFlags FileType OptMapName OBRACE
266 if ($2 == FILE_TYPE_GEOMETRY) {
272 $$ = XkbFileCreate($2, $3, $5, $1);
277 FileType : XKB_KEYCODES { $$ = FILE_TYPE_KEYCODES; }
278 | XKB_TYPES { $$ = FILE_TYPE_TYPES; }
279 | XKB_COMPATMAP { $$ = FILE_TYPE_COMPAT; }
280 | XKB_SYMBOLS { $$ = FILE_TYPE_SYMBOLS; }
281 | XKB_GEOMETRY { $$ = FILE_TYPE_GEOMETRY; }
284 OptFlags : Flags { $$ = $1; }
288 Flags : Flags Flag { $$ = ($1 | $2); }
292 Flag : PARTIAL { $$ = MAP_IS_PARTIAL; }
293 | DEFAULT { $$ = MAP_IS_DEFAULT; }
294 | HIDDEN { $$ = MAP_IS_HIDDEN; }
295 | ALPHANUMERIC_KEYS { $$ = MAP_HAS_ALPHANUMERIC; }
296 | MODIFIER_KEYS { $$ = MAP_HAS_MODIFIER; }
297 | KEYPAD_KEYS { $$ = MAP_HAS_KEYPAD; }
298 | FUNCTION_KEYS { $$ = MAP_HAS_FN; }
299 | ALTERNATE_GROUP { $$ = MAP_IS_ALTGR; }
302 DeclList : DeclList Decl
303 { $$ = AppendStmt($1, $2); }
307 Decl : OptMergeMode VarDecl
312 | OptMergeMode VModDecl
317 | OptMergeMode InterpretDecl
322 | OptMergeMode KeyNameDecl
327 | OptMergeMode KeyAliasDecl
332 | OptMergeMode KeyTypeDecl
337 | OptMergeMode SymbolsDecl
342 | OptMergeMode ModMapDecl
347 | OptMergeMode GroupCompatDecl
352 | OptMergeMode LedMapDecl
357 | OptMergeMode LedNameDecl
362 | OptMergeMode ShapeDecl { $$ = NULL; }
363 | OptMergeMode SectionDecl { $$ = NULL; }
364 | OptMergeMode DoodadDecl { $$ = NULL; }
367 $$ = &IncludeCreate(param->ctx, $2, $1)->common;
372 VarDecl : Lhs EQUALS Expr SEMI
373 { $$ = VarCreate($1, $3); }
375 { $$ = BoolVarCreate($1, true); }
377 { $$ = BoolVarCreate($2, false); }
380 KeyNameDecl : KEYNAME EQUALS KeyCode SEMI
381 { $$ = KeycodeCreate($1, $3); }
384 KeyAliasDecl : ALIAS KEYNAME EQUALS KEYNAME SEMI
385 { $$ = KeyAliasCreate($2, $4); }
388 VModDecl : VIRTUAL_MODS VModDefList SEMI
392 VModDefList : VModDefList COMMA VModDef
393 { $$ = (VModDef *)AppendStmt(&$1->common, &$3->common); }
399 { $$ = VModCreate($1, NULL); }
401 { $$ = VModCreate($1, $3); }
404 InterpretDecl : INTERPRET InterpretMatch OBRACE
407 { $2->def = $4; $$ = $2; }
410 InterpretMatch : KeySym PLUS Expr
411 { $$ = InterpCreate($1, $3); }
413 { $$ = InterpCreate($1, NULL); }
416 VarDeclList : VarDeclList VarDecl
417 { $$ = (VarDef *)AppendStmt(&$1->common, &$2->common); }
422 KeyTypeDecl : TYPE String OBRACE
425 { $$ = KeyTypeCreate($2, $4); }
428 SymbolsDecl : KEY KEYNAME OBRACE
431 { $$ = SymbolsCreate($2, $4); }
434 SymbolsBody : SymbolsBody COMMA SymbolsVarDecl
435 { $$ = (VarDef *)AppendStmt(&$1->common, &$3->common); }
441 SymbolsVarDecl : Lhs EQUALS Expr { $$ = VarCreate($1, $3); }
442 | Lhs EQUALS ArrayInit { $$ = VarCreate($1, $3); }
443 | Ident { $$ = BoolVarCreate($1, true); }
444 | EXCLAM Ident { $$ = BoolVarCreate($2, false); }
445 | ArrayInit { $$ = VarCreate(NULL, $1); }
448 ArrayInit : OBRACKET OptKeySymList CBRACKET
450 | OBRACKET ActionList CBRACKET
451 { $$ = ExprCreateUnary(EXPR_ACTION_LIST, EXPR_TYPE_ACTION, $2); }
454 GroupCompatDecl : GROUP Integer EQUALS Expr SEMI
455 { $$ = GroupCompatCreate($2, $4); }
458 ModMapDecl : MODIFIER_MAP Ident OBRACE ExprList CBRACE SEMI
459 { $$ = ModMapCreate($2, $4); }
462 LedMapDecl: INDICATOR String OBRACE VarDeclList CBRACE SEMI
463 { $$ = LedMapCreate($2, $4); }
466 LedNameDecl: INDICATOR Integer EQUALS Expr SEMI
467 { $$ = LedNameCreate($2, $4, false); }
468 | VIRTUAL INDICATOR Integer EQUALS Expr SEMI
469 { $$ = LedNameCreate($3, $5, true); }
472 ShapeDecl : SHAPE String OBRACE OutlineList CBRACE SEMI
474 | SHAPE String OBRACE CoordList CBRACE SEMI
478 SectionDecl : SECTION String OBRACE SectionBody CBRACE SEMI
482 SectionBody : SectionBody SectionBodyItem { $$ = NULL;}
483 | SectionBodyItem { $$ = NULL; }
486 SectionBodyItem : ROW OBRACE RowBody CBRACE SEMI
489 { FreeStmt(&$1->common); $$ = NULL; }
493 { FreeStmt(&$1->common); $$ = NULL; }
498 RowBody : RowBody RowBodyItem { $$ = NULL;}
499 | RowBodyItem { $$ = NULL; }
502 RowBodyItem : KEYS OBRACE Keys CBRACE SEMI { $$ = NULL; }
504 { FreeStmt(&$1->common); $$ = NULL; }
507 Keys : Keys COMMA Key { $$ = NULL; }
513 | OBRACE ExprList CBRACE
514 { FreeStmt(&$2->common); $$ = NULL; }
517 OverlayDecl : OVERLAY String OBRACE OverlayKeyList CBRACE SEMI
521 OverlayKeyList : OverlayKeyList COMMA OverlayKey { $$ = NULL; }
522 | OverlayKey { $$ = NULL; }
525 OverlayKey : KEYNAME EQUALS KEYNAME { $$ = NULL; }
528 OutlineList : OutlineList COMMA OutlineInList
534 OutlineInList : OBRACE CoordList CBRACE
536 | Ident EQUALS OBRACE CoordList CBRACE
539 { FreeStmt(&$3->common); $$ = NULL; }
542 CoordList : CoordList COMMA Coord
548 Coord : OBRACKET SignedNumber COMMA SignedNumber CBRACKET
552 DoodadDecl : DoodadType String OBRACE VarDeclList CBRACE SEMI
553 { FreeStmt(&$4->common); $$ = NULL; }
556 DoodadType : TEXT { $$ = 0; }
557 | OUTLINE { $$ = 0; }
562 FieldSpec : Ident { $$ = $1; }
563 | Element { $$ = $1; }
567 { $$ = xkb_atom_intern_literal(param->ctx, "action"); }
569 { $$ = xkb_atom_intern_literal(param->ctx, "interpret"); }
571 { $$ = xkb_atom_intern_literal(param->ctx, "type"); }
573 { $$ = xkb_atom_intern_literal(param->ctx, "key"); }
575 { $$ = xkb_atom_intern_literal(param->ctx, "group"); }
577 {$$ = xkb_atom_intern_literal(param->ctx, "modifier_map");}
579 { $$ = xkb_atom_intern_literal(param->ctx, "indicator"); }
581 { $$ = XKB_ATOM_NONE; }
583 { $$ = XKB_ATOM_NONE; }
585 { $$ = XKB_ATOM_NONE; }
587 { $$ = XKB_ATOM_NONE; }
590 OptMergeMode : MergeMode { $$ = $1; }
591 | { $$ = MERGE_DEFAULT; }
594 MergeMode : INCLUDE { $$ = MERGE_DEFAULT; }
595 | AUGMENT { $$ = MERGE_AUGMENT; }
596 | OVERRIDE { $$ = MERGE_OVERRIDE; }
597 | REPLACE { $$ = MERGE_REPLACE; }
601 * This used to be MERGE_ALT_FORM. This functionality was
602 * unused and has been removed.
608 OptExprList : ExprList { $$ = $1; }
612 ExprList : ExprList COMMA Expr
613 { $$ = (ExprDef *)AppendStmt(&$1->common, &$3->common); }
618 Expr : Expr DIVIDE Expr
619 { $$ = ExprCreateBinary(EXPR_DIVIDE, $1, $3); }
621 { $$ = ExprCreateBinary(EXPR_ADD, $1, $3); }
623 { $$ = ExprCreateBinary(EXPR_SUBTRACT, $1, $3); }
625 { $$ = ExprCreateBinary(EXPR_MULTIPLY, $1, $3); }
627 { $$ = ExprCreateBinary(EXPR_ASSIGN, $1, $3); }
633 { $$ = ExprCreateUnary(EXPR_NEGATE, $2->expr.value_type, $2); }
635 { $$ = ExprCreateUnary(EXPR_UNARY_PLUS, $2->expr.value_type, $2); }
637 { $$ = ExprCreateUnary(EXPR_NOT, EXPR_TYPE_BOOLEAN, $2); }
639 { $$ = ExprCreateUnary(EXPR_INVERT, $2->expr.value_type, $2); }
642 | FieldSpec OPAREN OptExprList CPAREN %prec OPAREN
643 { $$ = ExprCreateAction($1, $3); }
650 ActionList : ActionList COMMA Action
651 { $$ = (ExprDef *)AppendStmt(&$1->common, &$3->common); }
656 Action : FieldSpec OPAREN OptExprList CPAREN
657 { $$ = ExprCreateAction($1, $3); }
661 { $$ = ExprCreateIdent($1); }
662 | FieldSpec DOT FieldSpec
663 { $$ = ExprCreateFieldRef($1, $3); }
664 | FieldSpec OBRACKET Expr CBRACKET
665 { $$ = ExprCreateArrayRef(XKB_ATOM_NONE, $1, $3); }
666 | FieldSpec DOT FieldSpec OBRACKET Expr CBRACKET
667 { $$ = ExprCreateArrayRef($1, $3, $5); }
671 { $$ = ExprCreateString($1); }
673 { $$ = ExprCreateInteger($1); }
677 { $$ = ExprCreateKeyName($1); }
680 OptKeySymList : KeySymList { $$ = $1; }
684 KeySymList : KeySymList COMMA KeySym
685 { $$ = ExprAppendKeysymList($1, $3); }
686 | KeySymList COMMA KeySyms
687 { $$ = ExprAppendMultiKeysymList($1, $3); }
689 { $$ = ExprCreateKeysymList($1); }
691 { $$ = ExprCreateMultiKeysymList($1); }
694 KeySyms : OBRACE KeySymList CBRACE
700 if (!resolve_keysym($1, &$$))
701 parser_warn(param, "unrecognized keysym");
704 | SECTION { $$ = XKB_KEY_section; }
708 parser_warn(param, "unrecognized keysym");
709 $$ = XKB_KEY_NoSymbol;
711 else if ($1 < 10) { /* XKB_KEY_0 .. XKB_KEY_9 */
712 $$ = XKB_KEY_0 + (xkb_keysym_t) $1;
716 snprintf(buf, sizeof(buf), "0x%x", $1);
717 if (!resolve_keysym(buf, &$$)) {
718 parser_warn(param, "unrecognized keysym");
719 $$ = XKB_KEY_NoSymbol;
725 SignedNumber : MINUS Number { $$ = -$2; }
726 | Number { $$ = $1; }
729 Number : FLOAT { $$ = $1; }
730 | INTEGER { $$ = $1; }
733 Float : FLOAT { $$ = 0; }
736 Integer : INTEGER { $$ = $1; }
739 KeyCode : INTEGER { $$ = $1; }
742 Ident : IDENT { $$ = xkb_atom_steal(param->ctx, $1); }
743 | DEFAULT { $$ = xkb_atom_intern_literal(param->ctx, "default"); }
746 String : STRING { $$ = xkb_atom_steal(param->ctx, $1); }
749 OptMapName : MapName { $$ = $1; }
753 MapName : STRING { $$ = $1; }
759 parse(struct xkb_context *ctx, struct scanner *scanner, const char *map)
762 XkbFile *first = NULL;
763 struct parser_param param = {
769 * If we got a specific map, we look for it exclusively and return
770 * immediately upon finding it. Otherwise, we need to get the
771 * default map. If we find a map marked as default, we return it
772 * immediately. If there are no maps marked as default, we return
773 * the first map in the file.
776 while ((ret = yyparse(¶m)) == 0 && param.more_maps) {
778 if (streq_not_null(map, param.rtrn->name))
781 FreeXkbFile(param.rtrn);
784 if (param.rtrn->flags & MAP_IS_DEFAULT) {
792 FreeXkbFile(param.rtrn);