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;
46 parser_error(struct parser_param *param, const char *msg)
48 scanner_error(param->scanner, msg);
52 parser_warn(struct parser_param *param, const char *msg)
54 scanner_warn(param->scanner, msg);
58 _xkbcommon_error(struct parser_param *param, const char *msg)
60 parser_error(param, msg);
64 resolve_keysym(const char *str, xkb_keysym_t *sym_rtrn)
68 if (!str || istreq(str, "any") || istreq(str, "nosymbol")) {
69 *sym_rtrn = XKB_KEY_NoSymbol;
73 if (istreq(str, "none") || istreq(str, "voidsymbol")) {
74 *sym_rtrn = XKB_KEY_VoidSymbol;
78 sym = xkb_keysym_from_name(str, XKB_KEYSYM_NO_FLAGS);
79 if (sym != XKB_KEY_NoSymbol) {
87 #define scanner param->scanner
91 %lex-param { struct scanner *scanner }
92 %parse-param { struct parser_param *param }
171 enum xkb_file_type file_type;
174 enum merge_mode merge;
175 enum xkb_map_flags mapFlags;
185 GroupCompatDef *groupCompat;
189 KeyAliasDef *keyAlias;
194 %type <num> INTEGER FLOAT
195 %type <str> IDENT STRING
198 %type <ival> Number Integer Float SignedNumber
199 %type <merge> MergeMode OptMergeMode
200 %type <file_type> XkbCompositeType FileType
201 %type <uval> DoodadType
202 %type <mapFlags> Flag Flags OptFlags
203 %type <str> MapName OptMapName
204 %type <sval> FieldSpec Ident Element String
205 %type <keysym> KeySym
206 %type <any> DeclList Decl
207 %type <expr> OptExprList ExprList Expr Term Lhs Terminal ArrayInit KeySyms
208 %type <expr> OptKeySymList KeySymList Action ActionList Coord CoordList
209 %type <var> VarDecl VarDeclList SymbolsBody SymbolsVarDecl
210 %type <vmod> VModDecl VModDefList VModDef
211 %type <interp> InterpretDecl InterpretMatch
212 %type <keyType> KeyTypeDecl
213 %type <syms> SymbolsDecl
214 %type <modMask> ModMapDecl
215 %type <groupCompat> GroupCompatDecl
216 %type <ledMap> LedMapDecl
217 %type <ledName> LedNameDecl
218 %type <keyCode> KeyNameDecl
219 %type <keyAlias> KeyAliasDecl
220 %type <geom> ShapeDecl SectionDecl SectionBody SectionBodyItem RowBody RowBodyItem
221 %type <geom> Keys Key OverlayDecl OverlayKeyList OverlayKey OutlineList OutlineInList
222 %type <geom> DoodadDecl
223 %type <file> XkbFile XkbMapConfigList XkbMapConfig
224 %type <file> XkbCompositeMap
229 * An actual file may contain more than one map. However, if we do things
230 * in the normal yacc way, i.e. aggregate all of the maps into a list and
231 * let the caller find the map it wants, we end up scanning and parsing a
232 * lot of unneeded maps (in the end we always just need one).
233 * Instead of doing that, we make yyparse return one map at a time, and
234 * then call it repeatedly until we find the map we need. Once we find it,
235 * we don't need to parse everything that follows in the file.
236 * This does mean that if we e.g. always use the first map, the file may
237 * contain complete garbage after that. But it's worth it.
240 XkbFile : XkbCompositeMap
241 { $$ = param->rtrn = $1; param->more_maps = true; }
243 { $$ = param->rtrn = $1; param->more_maps = true; YYACCEPT; }
245 { $$ = param->rtrn = NULL; param->more_maps = false; }
248 XkbCompositeMap : OptFlags XkbCompositeType OptMapName OBRACE
251 { $$ = XkbFileCreate(param->ctx, $2, $3, &$5->common, $1); }
254 XkbCompositeType: XKB_KEYMAP { $$ = FILE_TYPE_KEYMAP; }
255 | XKB_SEMANTICS { $$ = FILE_TYPE_KEYMAP; }
256 | XKB_LAYOUT { $$ = FILE_TYPE_KEYMAP; }
259 XkbMapConfigList : XkbMapConfigList XkbMapConfig
264 $$ = (XkbFile *)AppendStmt(&$1->common, &$2->common);
270 XkbMapConfig : OptFlags FileType OptMapName OBRACE
274 if ($2 == FILE_TYPE_GEOMETRY) {
280 $$ = XkbFileCreate(param->ctx, $2, $3, $5, $1);
285 FileType : XKB_KEYCODES { $$ = FILE_TYPE_KEYCODES; }
286 | XKB_TYPES { $$ = FILE_TYPE_TYPES; }
287 | XKB_COMPATMAP { $$ = FILE_TYPE_COMPAT; }
288 | XKB_SYMBOLS { $$ = FILE_TYPE_SYMBOLS; }
289 | XKB_GEOMETRY { $$ = FILE_TYPE_GEOMETRY; }
292 OptFlags : Flags { $$ = $1; }
296 Flags : Flags Flag { $$ = ($1 | $2); }
300 Flag : PARTIAL { $$ = MAP_IS_PARTIAL; }
301 | DEFAULT { $$ = MAP_IS_DEFAULT; }
302 | HIDDEN { $$ = MAP_IS_HIDDEN; }
303 | ALPHANUMERIC_KEYS { $$ = MAP_HAS_ALPHANUMERIC; }
304 | MODIFIER_KEYS { $$ = MAP_HAS_MODIFIER; }
305 | KEYPAD_KEYS { $$ = MAP_HAS_KEYPAD; }
306 | FUNCTION_KEYS { $$ = MAP_HAS_FN; }
307 | ALTERNATE_GROUP { $$ = MAP_IS_ALTGR; }
310 DeclList : DeclList Decl
311 { $$ = AppendStmt($1, $2); }
315 Decl : OptMergeMode VarDecl
320 | OptMergeMode VModDecl
325 | OptMergeMode InterpretDecl
330 | OptMergeMode KeyNameDecl
335 | OptMergeMode KeyAliasDecl
340 | OptMergeMode KeyTypeDecl
345 | OptMergeMode SymbolsDecl
350 | OptMergeMode ModMapDecl
355 | OptMergeMode GroupCompatDecl
360 | OptMergeMode LedMapDecl
365 | OptMergeMode LedNameDecl
370 | OptMergeMode ShapeDecl { $$ = NULL; }
371 | OptMergeMode SectionDecl { $$ = NULL; }
372 | OptMergeMode DoodadDecl { $$ = NULL; }
375 $$ = &IncludeCreate(param->ctx, $2, $1)->common;
380 VarDecl : Lhs EQUALS Expr SEMI
381 { $$ = VarCreate($1, $3); }
383 { $$ = BoolVarCreate($1, true); }
385 { $$ = BoolVarCreate($2, false); }
388 KeyNameDecl : KEYNAME EQUALS KeyCode SEMI
389 { $$ = KeycodeCreate($1, $3); }
392 KeyAliasDecl : ALIAS KEYNAME EQUALS KEYNAME SEMI
393 { $$ = KeyAliasCreate($2, $4); }
396 VModDecl : VIRTUAL_MODS VModDefList SEMI
400 VModDefList : VModDefList COMMA VModDef
401 { $$ = (VModDef *)AppendStmt(&$1->common, &$3->common); }
407 { $$ = VModCreate($1, NULL); }
409 { $$ = VModCreate($1, $3); }
412 InterpretDecl : INTERPRET InterpretMatch OBRACE
415 { $2->def = $4; $$ = $2; }
418 InterpretMatch : KeySym PLUS Expr
419 { $$ = InterpCreate($1, $3); }
421 { $$ = InterpCreate($1, NULL); }
424 VarDeclList : VarDeclList VarDecl
425 { $$ = (VarDef *)AppendStmt(&$1->common, &$2->common); }
430 KeyTypeDecl : TYPE String OBRACE
433 { $$ = KeyTypeCreate($2, $4); }
436 SymbolsDecl : KEY KEYNAME OBRACE
439 { $$ = SymbolsCreate($2, (ExprDef *)$4); }
442 SymbolsBody : SymbolsBody COMMA SymbolsVarDecl
443 { $$ = (VarDef *)AppendStmt(&$1->common, &$3->common); }
449 SymbolsVarDecl : Lhs EQUALS Expr { $$ = VarCreate($1, $3); }
450 | Lhs EQUALS ArrayInit { $$ = VarCreate($1, $3); }
451 | Ident { $$ = BoolVarCreate($1, true); }
452 | EXCLAM Ident { $$ = BoolVarCreate($2, false); }
453 | ArrayInit { $$ = VarCreate(NULL, $1); }
456 ArrayInit : OBRACKET OptKeySymList CBRACKET
458 | OBRACKET ActionList CBRACKET
459 { $$ = ExprCreateUnary(EXPR_ACTION_LIST, EXPR_TYPE_ACTION, $2); }
462 GroupCompatDecl : GROUP Integer EQUALS Expr SEMI
463 { $$ = GroupCompatCreate($2, $4); }
466 ModMapDecl : MODIFIER_MAP Ident OBRACE ExprList CBRACE SEMI
467 { $$ = ModMapCreate($2, $4); }
470 LedMapDecl: INDICATOR String OBRACE VarDeclList CBRACE SEMI
471 { $$ = LedMapCreate($2, $4); }
474 LedNameDecl: INDICATOR Integer EQUALS Expr SEMI
475 { $$ = LedNameCreate($2, $4, false); }
476 | VIRTUAL INDICATOR Integer EQUALS Expr SEMI
477 { $$ = LedNameCreate($3, $5, true); }
480 ShapeDecl : SHAPE String OBRACE OutlineList CBRACE SEMI
482 | SHAPE String OBRACE CoordList CBRACE SEMI
486 SectionDecl : SECTION String OBRACE SectionBody CBRACE SEMI
490 SectionBody : SectionBody SectionBodyItem { $$ = NULL;}
491 | SectionBodyItem { $$ = NULL; }
494 SectionBodyItem : ROW OBRACE RowBody CBRACE SEMI
497 { FreeStmt(&$1->common); $$ = NULL; }
501 { FreeStmt(&$1->common); $$ = NULL; }
506 RowBody : RowBody RowBodyItem { $$ = NULL;}
507 | RowBodyItem { $$ = NULL; }
510 RowBodyItem : KEYS OBRACE Keys CBRACE SEMI { $$ = NULL; }
512 { FreeStmt(&$1->common); $$ = NULL; }
515 Keys : Keys COMMA Key { $$ = NULL; }
521 | OBRACE ExprList CBRACE
522 { FreeStmt(&$2->common); $$ = NULL; }
525 OverlayDecl : OVERLAY String OBRACE OverlayKeyList CBRACE SEMI
529 OverlayKeyList : OverlayKeyList COMMA OverlayKey { $$ = NULL; }
530 | OverlayKey { $$ = NULL; }
533 OverlayKey : KEYNAME EQUALS KEYNAME { $$ = NULL; }
536 OutlineList : OutlineList COMMA OutlineInList
542 OutlineInList : OBRACE CoordList CBRACE
544 | Ident EQUALS OBRACE CoordList CBRACE
547 { FreeStmt(&$3->common); $$ = NULL; }
550 CoordList : CoordList COMMA Coord
556 Coord : OBRACKET SignedNumber COMMA SignedNumber CBRACKET
560 DoodadDecl : DoodadType String OBRACE VarDeclList CBRACE SEMI
561 { FreeStmt(&$4->common); $$ = NULL; }
564 DoodadType : TEXT { $$ = 0; }
565 | OUTLINE { $$ = 0; }
570 FieldSpec : Ident { $$ = $1; }
571 | Element { $$ = $1; }
575 { $$ = xkb_atom_intern_literal(param->ctx, "action"); }
577 { $$ = xkb_atom_intern_literal(param->ctx, "interpret"); }
579 { $$ = xkb_atom_intern_literal(param->ctx, "type"); }
581 { $$ = xkb_atom_intern_literal(param->ctx, "key"); }
583 { $$ = xkb_atom_intern_literal(param->ctx, "group"); }
585 {$$ = xkb_atom_intern_literal(param->ctx, "modifier_map");}
587 { $$ = xkb_atom_intern_literal(param->ctx, "indicator"); }
589 { $$ = XKB_ATOM_NONE; }
591 { $$ = XKB_ATOM_NONE; }
593 { $$ = XKB_ATOM_NONE; }
595 { $$ = XKB_ATOM_NONE; }
598 OptMergeMode : MergeMode { $$ = $1; }
599 | { $$ = MERGE_DEFAULT; }
602 MergeMode : INCLUDE { $$ = MERGE_DEFAULT; }
603 | AUGMENT { $$ = MERGE_AUGMENT; }
604 | OVERRIDE { $$ = MERGE_OVERRIDE; }
605 | REPLACE { $$ = MERGE_REPLACE; }
609 * This used to be MERGE_ALT_FORM. This functionality was
610 * unused and has been removed.
616 OptExprList : ExprList { $$ = $1; }
620 ExprList : ExprList COMMA Expr
621 { $$ = (ExprDef *)AppendStmt(&$1->common, &$3->common); }
626 Expr : Expr DIVIDE Expr
627 { $$ = ExprCreateBinary(EXPR_DIVIDE, $1, $3); }
629 { $$ = ExprCreateBinary(EXPR_ADD, $1, $3); }
631 { $$ = ExprCreateBinary(EXPR_SUBTRACT, $1, $3); }
633 { $$ = ExprCreateBinary(EXPR_MULTIPLY, $1, $3); }
635 { $$ = ExprCreateBinary(EXPR_ASSIGN, $1, $3); }
641 { $$ = ExprCreateUnary(EXPR_NEGATE, $2->value_type, $2); }
643 { $$ = ExprCreateUnary(EXPR_UNARY_PLUS, $2->value_type, $2); }
645 { $$ = ExprCreateUnary(EXPR_NOT, EXPR_TYPE_BOOLEAN, $2); }
647 { $$ = ExprCreateUnary(EXPR_INVERT, $2->value_type, $2); }
650 | FieldSpec OPAREN OptExprList CPAREN %prec OPAREN
651 { $$ = ActionCreate($1, $3); }
658 ActionList : ActionList COMMA Action
659 { $$ = (ExprDef *)AppendStmt(&$1->common, &$3->common); }
664 Action : FieldSpec OPAREN OptExprList CPAREN
665 { $$ = ActionCreate($1, $3); }
669 { $$ = ExprCreateIdent($1); }
670 | FieldSpec DOT FieldSpec
671 { $$ = ExprCreateFieldRef($1, $3); }
672 | FieldSpec OBRACKET Expr CBRACKET
673 { $$ = ExprCreateArrayRef(XKB_ATOM_NONE, $1, $3); }
674 | FieldSpec DOT FieldSpec OBRACKET Expr CBRACKET
675 { $$ = ExprCreateArrayRef($1, $3, $5); }
679 { $$ = ExprCreateString($1); }
681 { $$ = ExprCreateInteger($1); }
685 { $$ = ExprCreateKeyName($1); }
688 OptKeySymList : KeySymList { $$ = $1; }
692 KeySymList : KeySymList COMMA KeySym
693 { $$ = AppendKeysymList($1, $3); }
694 | KeySymList COMMA KeySyms
695 { $$ = AppendMultiKeysymList($1, $3); }
697 { $$ = CreateKeysymList($1); }
699 { $$ = CreateMultiKeysymList($1); }
702 KeySyms : OBRACE KeySymList CBRACE
708 if (!resolve_keysym($1, &$$))
709 parser_warn(param, "unrecognized keysym");
712 | SECTION { $$ = XKB_KEY_section; }
715 if ($1 < 10) { /* XKB_KEY_0 .. XKB_KEY_9 */
720 snprintf(buf, sizeof(buf), "0x%x", $1);
721 if (!resolve_keysym(buf, &$$))
722 parser_warn(param, "unrecognized keysym");
727 SignedNumber : MINUS Number { $$ = -$2; }
728 | Number { $$ = $1; }
731 Number : FLOAT { $$ = $1; }
732 | INTEGER { $$ = $1; }
735 Float : FLOAT { $$ = 0; }
738 Integer : INTEGER { $$ = $1; }
741 KeyCode : INTEGER { $$ = $1; }
744 Ident : IDENT { $$ = xkb_atom_steal(param->ctx, $1); }
745 | DEFAULT { $$ = xkb_atom_intern_literal(param->ctx, "default"); }
748 String : STRING { $$ = xkb_atom_steal(param->ctx, $1); }
751 OptMapName : MapName { $$ = $1; }
755 MapName : STRING { $$ = $1; }
763 parse(struct xkb_context *ctx, void *scanner, const char *map)
765 struct parser_param param;
767 XkbFile *first = NULL;
769 param.scanner = scanner;
773 * If we got a specific map, we look for it exclusively and return
774 * immediately upon finding it. Otherwise, we need to get the
775 * default map. If we find a map marked as default, we return it
776 * immediately. If there are no maps marked as default, we return
777 * the first map in the file.
780 while ((ret = yyparse(¶m)) == 0 && param.more_maps) {
782 if (streq_not_null(map, param.rtrn->name))
785 FreeXkbFile(param.rtrn);
788 if (param.rtrn->flags & MAP_IS_DEFAULT) {
796 FreeXkbFile(param.rtrn);
809 #define scanner param->scanner