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 _xkbcommon_error(struct parser_param *param, const char *msg)
48 scanner_error(param->scanner, msg);
51 #define scanner param->scanner
55 %lex-param { struct scanner *scanner }
56 %parse-param { struct parser_param *param }
135 enum xkb_file_type file_type;
138 enum merge_mode merge;
139 enum xkb_map_flags mapFlags;
148 GroupCompatDef *groupCompat;
152 KeyAliasDef *keyAlias;
157 %type <num> INTEGER FLOAT
158 %type <str> IDENT STRING
161 %type <ival> Number Integer Float SignedNumber
162 %type <merge> MergeMode OptMergeMode
163 %type <file_type> XkbCompositeType FileType
164 %type <uval> DoodadType
165 %type <mapFlags> Flag Flags OptFlags
166 %type <str> MapName OptMapName KeySym
167 %type <sval> FieldSpec Ident Element String
168 %type <any> DeclList Decl
169 %type <expr> OptExprList ExprList Expr Term Lhs Terminal ArrayInit KeySyms
170 %type <expr> OptKeySymList KeySymList Action ActionList Coord CoordList
171 %type <var> VarDecl VarDeclList SymbolsBody SymbolsVarDecl
172 %type <vmod> VModDecl VModDefList VModDef
173 %type <interp> InterpretDecl InterpretMatch
174 %type <keyType> KeyTypeDecl
175 %type <syms> SymbolsDecl
176 %type <modMask> ModMapDecl
177 %type <groupCompat> GroupCompatDecl
178 %type <ledMap> LedMapDecl
179 %type <ledName> LedNameDecl
180 %type <keyCode> KeyNameDecl
181 %type <keyAlias> KeyAliasDecl
182 %type <geom> ShapeDecl SectionDecl SectionBody SectionBodyItem RowBody RowBodyItem
183 %type <geom> Keys Key OverlayDecl OverlayKeyList OverlayKey OutlineList OutlineInList
184 %type <geom> DoodadDecl
185 %type <file> XkbFile XkbMapConfigList XkbMapConfig
186 %type <file> XkbCompositeMap
191 * An actual file may contain more than one map. However, if we do things
192 * in the normal yacc way, i.e. aggregate all of the maps into a list and
193 * let the caller find the map it wants, we end up scanning and parsing a
194 * lot of unneeded maps (in the end we always just need one).
195 * Instead of doing that, we make yyparse return one map at a time, and
196 * then call it repeatedly until we find the map we need. Once we find it,
197 * we don't need to parse everything that follows in the file.
198 * This does mean that if we e.g. always use the first map, the file may
199 * contain complete garbage after that. But it's worth it.
202 XkbFile : XkbCompositeMap
203 { $$ = param->rtrn = $1; param->more_maps = true; }
205 { $$ = param->rtrn = $1; param->more_maps = true; YYACCEPT; }
207 { $$ = param->rtrn = NULL; param->more_maps = false; }
210 XkbCompositeMap : OptFlags XkbCompositeType OptMapName OBRACE
213 { $$ = XkbFileCreate(param->ctx, $2, $3, &$5->common, $1); }
216 XkbCompositeType: XKB_KEYMAP { $$ = FILE_TYPE_KEYMAP; }
217 | XKB_SEMANTICS { $$ = FILE_TYPE_KEYMAP; }
218 | XKB_LAYOUT { $$ = FILE_TYPE_KEYMAP; }
221 XkbMapConfigList : XkbMapConfigList XkbMapConfig
226 $$ = (XkbFile *)AppendStmt(&$1->common, &$2->common);
232 XkbMapConfig : OptFlags FileType OptMapName OBRACE
236 if ($2 == FILE_TYPE_GEOMETRY) {
242 $$ = XkbFileCreate(param->ctx, $2, $3, $5, $1);
247 FileType : XKB_KEYCODES { $$ = FILE_TYPE_KEYCODES; }
248 | XKB_TYPES { $$ = FILE_TYPE_TYPES; }
249 | XKB_COMPATMAP { $$ = FILE_TYPE_COMPAT; }
250 | XKB_SYMBOLS { $$ = FILE_TYPE_SYMBOLS; }
251 | XKB_GEOMETRY { $$ = FILE_TYPE_GEOMETRY; }
254 OptFlags : Flags { $$ = $1; }
258 Flags : Flags Flag { $$ = ($1 | $2); }
262 Flag : PARTIAL { $$ = MAP_IS_PARTIAL; }
263 | DEFAULT { $$ = MAP_IS_DEFAULT; }
264 | HIDDEN { $$ = MAP_IS_HIDDEN; }
265 | ALPHANUMERIC_KEYS { $$ = MAP_HAS_ALPHANUMERIC; }
266 | MODIFIER_KEYS { $$ = MAP_HAS_MODIFIER; }
267 | KEYPAD_KEYS { $$ = MAP_HAS_KEYPAD; }
268 | FUNCTION_KEYS { $$ = MAP_HAS_FN; }
269 | ALTERNATE_GROUP { $$ = MAP_IS_ALTGR; }
272 DeclList : DeclList Decl
273 { $$ = AppendStmt($1, $2); }
277 Decl : OptMergeMode VarDecl
282 | OptMergeMode VModDecl
287 | OptMergeMode InterpretDecl
292 | OptMergeMode KeyNameDecl
297 | OptMergeMode KeyAliasDecl
302 | OptMergeMode KeyTypeDecl
307 | OptMergeMode SymbolsDecl
312 | OptMergeMode ModMapDecl
317 | OptMergeMode GroupCompatDecl
322 | OptMergeMode LedMapDecl
327 | OptMergeMode LedNameDecl
332 | OptMergeMode ShapeDecl { $$ = NULL; }
333 | OptMergeMode SectionDecl { $$ = NULL; }
334 | OptMergeMode DoodadDecl { $$ = NULL; }
337 $$ = &IncludeCreate(param->ctx, $2, $1)->common;
342 VarDecl : Lhs EQUALS Expr SEMI
343 { $$ = VarCreate($1, $3); }
345 { $$ = BoolVarCreate($1, 1); }
347 { $$ = BoolVarCreate($2, 0); }
350 KeyNameDecl : KEYNAME EQUALS KeyCode SEMI
351 { $$ = KeycodeCreate($1, $3); }
354 KeyAliasDecl : ALIAS KEYNAME EQUALS KEYNAME SEMI
355 { $$ = KeyAliasCreate($2, $4); }
358 VModDecl : VIRTUAL_MODS VModDefList SEMI
362 VModDefList : VModDefList COMMA VModDef
363 { $$ = (VModDef *)AppendStmt(&$1->common, &$3->common); }
369 { $$ = VModCreate($1, NULL); }
371 { $$ = VModCreate($1, $3); }
374 InterpretDecl : INTERPRET InterpretMatch OBRACE
377 { $2->def = $4; $$ = $2; }
380 InterpretMatch : KeySym PLUS Expr
381 { $$ = InterpCreate($1, $3); }
383 { $$ = InterpCreate($1, NULL); }
386 VarDeclList : VarDeclList VarDecl
387 { $$ = (VarDef *)AppendStmt(&$1->common, &$2->common); }
392 KeyTypeDecl : TYPE String OBRACE
395 { $$ = KeyTypeCreate($2, $4); }
398 SymbolsDecl : KEY KEYNAME OBRACE
401 { $$ = SymbolsCreate($2, (ExprDef *)$4); }
404 SymbolsBody : SymbolsBody COMMA SymbolsVarDecl
405 { $$ = (VarDef *)AppendStmt(&$1->common, &$3->common); }
411 SymbolsVarDecl : Lhs EQUALS Expr { $$ = VarCreate($1, $3); }
412 | Lhs EQUALS ArrayInit { $$ = VarCreate($1, $3); }
413 | Ident { $$ = BoolVarCreate($1, 1); }
414 | EXCLAM Ident { $$ = BoolVarCreate($2, 0); }
415 | ArrayInit { $$ = VarCreate(NULL, $1); }
418 ArrayInit : OBRACKET OptKeySymList CBRACKET
420 | OBRACKET ActionList CBRACKET
421 { $$ = ExprCreateUnary(EXPR_ACTION_LIST, EXPR_TYPE_ACTION, $2); }
424 GroupCompatDecl : GROUP Integer EQUALS Expr SEMI
425 { $$ = GroupCompatCreate($2, $4); }
428 ModMapDecl : MODIFIER_MAP Ident OBRACE ExprList CBRACE SEMI
429 { $$ = ModMapCreate($2, $4); }
432 LedMapDecl: INDICATOR String OBRACE VarDeclList CBRACE SEMI
433 { $$ = LedMapCreate($2, $4); }
436 LedNameDecl: INDICATOR Integer EQUALS Expr SEMI
437 { $$ = LedNameCreate($2, $4, false); }
438 | VIRTUAL INDICATOR Integer EQUALS Expr SEMI
439 { $$ = LedNameCreate($3, $5, true); }
442 ShapeDecl : SHAPE String OBRACE OutlineList CBRACE SEMI
444 | SHAPE String OBRACE CoordList CBRACE SEMI
448 SectionDecl : SECTION String OBRACE SectionBody CBRACE SEMI
452 SectionBody : SectionBody SectionBodyItem { $$ = NULL;}
453 | SectionBodyItem { $$ = NULL; }
456 SectionBodyItem : ROW OBRACE RowBody CBRACE SEMI
459 { FreeStmt(&$1->common); $$ = NULL; }
463 { FreeStmt(&$1->common); $$ = NULL; }
468 RowBody : RowBody RowBodyItem { $$ = NULL;}
469 | RowBodyItem { $$ = NULL; }
472 RowBodyItem : KEYS OBRACE Keys CBRACE SEMI { $$ = NULL; }
474 { FreeStmt(&$1->common); $$ = NULL; }
477 Keys : Keys COMMA Key { $$ = NULL; }
483 | OBRACE ExprList CBRACE
484 { FreeStmt(&$2->common); $$ = NULL; }
487 OverlayDecl : OVERLAY String OBRACE OverlayKeyList CBRACE SEMI
491 OverlayKeyList : OverlayKeyList COMMA OverlayKey { $$ = NULL; }
492 | OverlayKey { $$ = NULL; }
495 OverlayKey : KEYNAME EQUALS KEYNAME { $$ = NULL; }
498 OutlineList : OutlineList COMMA OutlineInList
504 OutlineInList : OBRACE CoordList CBRACE
506 | Ident EQUALS OBRACE CoordList CBRACE
509 { FreeStmt(&$3->common); $$ = NULL; }
512 CoordList : CoordList COMMA Coord
518 Coord : OBRACKET SignedNumber COMMA SignedNumber CBRACKET
522 DoodadDecl : DoodadType String OBRACE VarDeclList CBRACE SEMI
523 { FreeStmt(&$4->common); $$ = NULL; }
526 DoodadType : TEXT { $$ = 0; }
527 | OUTLINE { $$ = 0; }
532 FieldSpec : Ident { $$ = $1; }
533 | Element { $$ = $1; }
537 { $$ = xkb_atom_intern_literal(param->ctx, "action"); }
539 { $$ = xkb_atom_intern_literal(param->ctx, "interpret"); }
541 { $$ = xkb_atom_intern_literal(param->ctx, "type"); }
543 { $$ = xkb_atom_intern_literal(param->ctx, "key"); }
545 { $$ = xkb_atom_intern_literal(param->ctx, "group"); }
547 {$$ = xkb_atom_intern_literal(param->ctx, "modifier_map");}
549 { $$ = xkb_atom_intern_literal(param->ctx, "indicator"); }
551 { $$ = XKB_ATOM_NONE; }
553 { $$ = XKB_ATOM_NONE; }
555 { $$ = XKB_ATOM_NONE; }
557 { $$ = XKB_ATOM_NONE; }
560 OptMergeMode : MergeMode { $$ = $1; }
561 | { $$ = MERGE_DEFAULT; }
564 MergeMode : INCLUDE { $$ = MERGE_DEFAULT; }
565 | AUGMENT { $$ = MERGE_AUGMENT; }
566 | OVERRIDE { $$ = MERGE_OVERRIDE; }
567 | REPLACE { $$ = MERGE_REPLACE; }
571 * This used to be MERGE_ALT_FORM. This functionality was
572 * unused and has been removed.
578 OptExprList : ExprList { $$ = $1; }
582 ExprList : ExprList COMMA Expr
583 { $$ = (ExprDef *)AppendStmt(&$1->common, &$3->common); }
588 Expr : Expr DIVIDE Expr
589 { $$ = ExprCreateBinary(EXPR_DIVIDE, $1, $3); }
591 { $$ = ExprCreateBinary(EXPR_ADD, $1, $3); }
593 { $$ = ExprCreateBinary(EXPR_SUBTRACT, $1, $3); }
595 { $$ = ExprCreateBinary(EXPR_MULTIPLY, $1, $3); }
597 { $$ = ExprCreateBinary(EXPR_ASSIGN, $1, $3); }
603 { $$ = ExprCreateUnary(EXPR_NEGATE, $2->value_type, $2); }
605 { $$ = ExprCreateUnary(EXPR_UNARY_PLUS, $2->value_type, $2); }
607 { $$ = ExprCreateUnary(EXPR_NOT, EXPR_TYPE_BOOLEAN, $2); }
609 { $$ = ExprCreateUnary(EXPR_INVERT, $2->value_type, $2); }
612 | FieldSpec OPAREN OptExprList CPAREN %prec OPAREN
613 { $$ = ActionCreate($1, $3); }
620 ActionList : ActionList COMMA Action
621 { $$ = (ExprDef *)AppendStmt(&$1->common, &$3->common); }
626 Action : FieldSpec OPAREN OptExprList CPAREN
627 { $$ = ActionCreate($1, $3); }
633 expr = ExprCreate(EXPR_IDENT, EXPR_TYPE_UNKNOWN);
634 expr->value.str = $1;
637 | FieldSpec DOT FieldSpec
640 expr = ExprCreate(EXPR_FIELD_REF, EXPR_TYPE_UNKNOWN);
641 expr->value.field.element = $1;
642 expr->value.field.field = $3;
645 | FieldSpec OBRACKET Expr CBRACKET
648 expr = ExprCreate(EXPR_ARRAY_REF, EXPR_TYPE_UNKNOWN);
649 expr->value.array.element = XKB_ATOM_NONE;
650 expr->value.array.field = $1;
651 expr->value.array.entry = $3;
654 | FieldSpec DOT FieldSpec OBRACKET Expr CBRACKET
657 expr = ExprCreate(EXPR_ARRAY_REF, EXPR_TYPE_UNKNOWN);
658 expr->value.array.element = $1;
659 expr->value.array.field = $3;
660 expr->value.array.entry = $5;
668 expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_STRING);
669 expr->value.str = $1;
675 expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_INT);
676 expr->value.ival = $1;
686 expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_KEYNAME);
687 expr->value.keyName = $1;
692 OptKeySymList : KeySymList { $$ = $1; }
696 KeySymList : KeySymList COMMA KeySym
697 { $$ = AppendKeysymList($1, $3); }
698 | KeySymList COMMA KeySyms
699 { $$ = AppendMultiKeysymList($1, $3); }
701 { $$ = CreateKeysymList($1); }
703 { $$ = CreateMultiKeysymList($1); }
706 KeySyms : OBRACE KeySymList CBRACE
710 KeySym : IDENT { $$ = $1; }
711 | SECTION { $$ = strdup("section"); }
714 if ($1 < 10) { /* XK_0 .. XK_9 */
721 snprintf($$, 17, "0x%x", $1);
726 SignedNumber : MINUS Number { $$ = -$2; }
727 | Number { $$ = $1; }
730 Number : FLOAT { $$ = $1; }
731 | INTEGER { $$ = $1; }
734 Float : FLOAT { $$ = 0; }
737 Integer : INTEGER { $$ = $1; }
740 KeyCode : INTEGER { $$ = $1; }
743 Ident : IDENT { $$ = xkb_atom_steal(param->ctx, $1); }
744 | DEFAULT { $$ = xkb_atom_intern_literal(param->ctx, "default"); }
747 String : STRING { $$ = xkb_atom_steal(param->ctx, $1); }
750 OptMapName : MapName { $$ = $1; }
754 MapName : STRING { $$ = $1; }
762 parse(struct xkb_context *ctx, void *scanner, const char *map)
764 struct parser_param param;
766 XkbFile *first = NULL;
768 param.scanner = scanner;
772 * If we got a specific map, we look for it exclusively and return
773 * immediately upon finding it. Otherwise, we need to get the
774 * default map. If we find a map marked as default, we return it
775 * immediately. If there are no maps marked as default, we return
776 * the first map in the file.
779 while ((ret = yyparse(¶m)) == 0 && param.more_maps) {
781 if (streq_not_null(map, param.rtrn->name))
784 FreeXkbFile(param.rtrn);
787 if (param.rtrn->flags & MAP_IS_DEFAULT) {
795 FreeXkbFile(param.rtrn);
808 #define scanner param->scanner