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 #include "xkbcomp-priv.h"
29 #include "ast-build.h"
30 #include "parser-priv.h"
33 struct xkb_context *ctx;
40 _xkbcommon_error(struct YYLTYPE *loc, struct parser_param *param, const char *msg)
42 scanner_error(loc, param->scanner, msg);
45 #define scanner param->scanner
48 %name-prefix "_xkbcommon_"
51 %lex-param { struct scanner *scanner }
52 %parse-param { struct parser_param *param }
131 enum xkb_file_type file_type;
134 enum merge_mode merge;
135 enum xkb_map_flags mapFlags;
144 GroupCompatDef *groupCompat;
148 KeyAliasDef *keyAlias;
153 %type <num> INTEGER FLOAT
154 %type <str> IDENT STRING
157 %type <ival> Number Integer Float SignedNumber
158 %type <merge> MergeMode OptMergeMode
159 %type <file_type> XkbCompositeType FileType
160 %type <uval> DoodadType
161 %type <mapFlags> Flag Flags OptFlags
162 %type <str> MapName OptMapName KeySym
163 %type <sval> FieldSpec Ident Element String
164 %type <any> DeclList Decl
165 %type <expr> OptExprList ExprList Expr Term Lhs Terminal ArrayInit KeySyms
166 %type <expr> OptKeySymList KeySymList Action ActionList Coord CoordList
167 %type <var> VarDecl VarDeclList SymbolsBody SymbolsVarDecl
168 %type <vmod> VModDecl VModDefList VModDef
169 %type <interp> InterpretDecl InterpretMatch
170 %type <keyType> KeyTypeDecl
171 %type <syms> SymbolsDecl
172 %type <modMask> ModMapDecl
173 %type <groupCompat> GroupCompatDecl
174 %type <ledMap> LedMapDecl
175 %type <ledName> LedNameDecl
176 %type <keyCode> KeyNameDecl
177 %type <keyAlias> KeyAliasDecl
178 %type <geom> ShapeDecl SectionDecl SectionBody SectionBodyItem RowBody RowBodyItem
179 %type <geom> Keys Key OverlayDecl OverlayKeyList OverlayKey OutlineList OutlineInList
180 %type <geom> DoodadDecl
181 %type <file> XkbFile XkbMapConfigList XkbMapConfig
182 %type <file> XkbCompositeMap
187 * An actual file may contain more than one map. However, if we do things
188 * in the normal yacc way, i.e. aggregate all of the maps into a list and
189 * let the caller find the map it wants, we end up scanning and parsing a
190 * lot of unneeded maps (in the end we always just need one).
191 * Instead of doing that, we make yyparse return one map at a time, and
192 * then call it repeatedly until we find the map we need. Once we find it,
193 * we don't need to parse everything that follows in the file.
194 * This does mean that if we e.g. always use the first map, the file may
195 * contain complete garbage after that. But it's worth it.
198 XkbFile : XkbCompositeMap
199 { $$ = param->rtrn = $1; param->more_maps = true; }
201 { $$ = param->rtrn = $1; param->more_maps = true; YYACCEPT; }
203 { $$ = param->rtrn = NULL; param->more_maps = false; }
206 XkbCompositeMap : OptFlags XkbCompositeType OptMapName OBRACE
209 { $$ = XkbFileCreate(param->ctx, $2, $3, &$5->common, $1); }
212 XkbCompositeType: XKB_KEYMAP { $$ = FILE_TYPE_KEYMAP; }
213 | XKB_SEMANTICS { $$ = FILE_TYPE_KEYMAP; }
214 | XKB_LAYOUT { $$ = FILE_TYPE_KEYMAP; }
217 XkbMapConfigList : XkbMapConfigList XkbMapConfig
222 $$ = (XkbFile *)AppendStmt(&$1->common, &$2->common);
228 XkbMapConfig : OptFlags FileType OptMapName OBRACE
232 if ($2 == FILE_TYPE_GEOMETRY) {
238 $$ = XkbFileCreate(param->ctx, $2, $3, $5, $1);
243 FileType : XKB_KEYCODES { $$ = FILE_TYPE_KEYCODES; }
244 | XKB_TYPES { $$ = FILE_TYPE_TYPES; }
245 | XKB_COMPATMAP { $$ = FILE_TYPE_COMPAT; }
246 | XKB_SYMBOLS { $$ = FILE_TYPE_SYMBOLS; }
247 | XKB_GEOMETRY { $$ = FILE_TYPE_GEOMETRY; }
250 OptFlags : Flags { $$ = $1; }
254 Flags : Flags Flag { $$ = ($1 | $2); }
258 Flag : PARTIAL { $$ = MAP_IS_PARTIAL; }
259 | DEFAULT { $$ = MAP_IS_DEFAULT; }
260 | HIDDEN { $$ = MAP_IS_HIDDEN; }
261 | ALPHANUMERIC_KEYS { $$ = MAP_HAS_ALPHANUMERIC; }
262 | MODIFIER_KEYS { $$ = MAP_HAS_MODIFIER; }
263 | KEYPAD_KEYS { $$ = MAP_HAS_KEYPAD; }
264 | FUNCTION_KEYS { $$ = MAP_HAS_FN; }
265 | ALTERNATE_GROUP { $$ = MAP_IS_ALTGR; }
268 DeclList : DeclList Decl
269 { $$ = AppendStmt($1, $2); }
273 Decl : OptMergeMode VarDecl
278 | OptMergeMode VModDecl
283 | OptMergeMode InterpretDecl
288 | OptMergeMode KeyNameDecl
293 | OptMergeMode KeyAliasDecl
298 | OptMergeMode KeyTypeDecl
303 | OptMergeMode SymbolsDecl
308 | OptMergeMode ModMapDecl
313 | OptMergeMode GroupCompatDecl
318 | OptMergeMode LedMapDecl
323 | OptMergeMode LedNameDecl
328 | OptMergeMode ShapeDecl { $$ = NULL; }
329 | OptMergeMode SectionDecl { $$ = NULL; }
330 | OptMergeMode DoodadDecl { $$ = NULL; }
333 $$ = &IncludeCreate(param->ctx, $2, $1)->common;
338 VarDecl : Lhs EQUALS Expr SEMI
339 { $$ = VarCreate($1, $3); }
341 { $$ = BoolVarCreate($1, 1); }
343 { $$ = BoolVarCreate($2, 0); }
346 KeyNameDecl : KEYNAME EQUALS KeyCode SEMI
347 { $$ = KeycodeCreate($1, $3); }
350 KeyAliasDecl : ALIAS KEYNAME EQUALS KEYNAME SEMI
351 { $$ = KeyAliasCreate($2, $4); }
354 VModDecl : VIRTUAL_MODS VModDefList SEMI
358 VModDefList : VModDefList COMMA VModDef
359 { $$ = (VModDef *)AppendStmt(&$1->common, &$3->common); }
365 { $$ = VModCreate($1, NULL); }
367 { $$ = VModCreate($1, $3); }
370 InterpretDecl : INTERPRET InterpretMatch OBRACE
373 { $2->def = $4; $$ = $2; }
376 InterpretMatch : KeySym PLUS Expr
377 { $$ = InterpCreate($1, $3); }
379 { $$ = InterpCreate($1, NULL); }
382 VarDeclList : VarDeclList VarDecl
383 { $$ = (VarDef *)AppendStmt(&$1->common, &$2->common); }
388 KeyTypeDecl : TYPE String OBRACE
391 { $$ = KeyTypeCreate($2, $4); }
394 SymbolsDecl : KEY KEYNAME OBRACE
397 { $$ = SymbolsCreate($2, (ExprDef *)$4); }
400 SymbolsBody : SymbolsBody COMMA SymbolsVarDecl
401 { $$ = (VarDef *)AppendStmt(&$1->common, &$3->common); }
407 SymbolsVarDecl : Lhs EQUALS Expr { $$ = VarCreate($1, $3); }
408 | Lhs EQUALS ArrayInit { $$ = VarCreate($1, $3); }
409 | Ident { $$ = BoolVarCreate($1, 1); }
410 | EXCLAM Ident { $$ = BoolVarCreate($2, 0); }
411 | ArrayInit { $$ = VarCreate(NULL, $1); }
414 ArrayInit : OBRACKET OptKeySymList CBRACKET
416 | OBRACKET ActionList CBRACKET
417 { $$ = ExprCreateUnary(EXPR_ACTION_LIST, EXPR_TYPE_ACTION, $2); }
420 GroupCompatDecl : GROUP Integer EQUALS Expr SEMI
421 { $$ = GroupCompatCreate($2, $4); }
424 ModMapDecl : MODIFIER_MAP Ident OBRACE ExprList CBRACE SEMI
425 { $$ = ModMapCreate($2, $4); }
428 LedMapDecl: INDICATOR String OBRACE VarDeclList CBRACE SEMI
429 { $$ = LedMapCreate($2, $4); }
432 LedNameDecl: INDICATOR Integer EQUALS Expr SEMI
433 { $$ = LedNameCreate($2, $4, false); }
434 | VIRTUAL INDICATOR Integer EQUALS Expr SEMI
435 { $$ = LedNameCreate($3, $5, true); }
438 ShapeDecl : SHAPE String OBRACE OutlineList CBRACE SEMI
440 | SHAPE String OBRACE CoordList CBRACE SEMI
444 SectionDecl : SECTION String OBRACE SectionBody CBRACE SEMI
448 SectionBody : SectionBody SectionBodyItem { $$ = NULL;}
449 | SectionBodyItem { $$ = NULL; }
452 SectionBodyItem : ROW OBRACE RowBody CBRACE SEMI
455 { FreeStmt(&$1->common); $$ = NULL; }
459 { FreeStmt(&$1->common); $$ = NULL; }
464 RowBody : RowBody RowBodyItem { $$ = NULL;}
465 | RowBodyItem { $$ = NULL; }
468 RowBodyItem : KEYS OBRACE Keys CBRACE SEMI { $$ = NULL; }
470 { FreeStmt(&$1->common); $$ = NULL; }
473 Keys : Keys COMMA Key { $$ = NULL; }
479 | OBRACE ExprList CBRACE
480 { FreeStmt(&$2->common); $$ = NULL; }
483 OverlayDecl : OVERLAY String OBRACE OverlayKeyList CBRACE SEMI
487 OverlayKeyList : OverlayKeyList COMMA OverlayKey { $$ = NULL; }
488 | OverlayKey { $$ = NULL; }
491 OverlayKey : KEYNAME EQUALS KEYNAME { $$ = NULL; }
494 OutlineList : OutlineList COMMA OutlineInList
500 OutlineInList : OBRACE CoordList CBRACE
502 | Ident EQUALS OBRACE CoordList CBRACE
505 { FreeStmt(&$3->common); $$ = NULL; }
508 CoordList : CoordList COMMA Coord
514 Coord : OBRACKET SignedNumber COMMA SignedNumber CBRACKET
518 DoodadDecl : DoodadType String OBRACE VarDeclList CBRACE SEMI
519 { FreeStmt(&$4->common); $$ = NULL; }
522 DoodadType : TEXT { $$ = 0; }
523 | OUTLINE { $$ = 0; }
528 FieldSpec : Ident { $$ = $1; }
529 | Element { $$ = $1; }
533 { $$ = xkb_atom_intern(param->ctx, "action"); }
535 { $$ = xkb_atom_intern(param->ctx, "interpret"); }
537 { $$ = xkb_atom_intern(param->ctx, "type"); }
539 { $$ = xkb_atom_intern(param->ctx, "key"); }
541 { $$ = xkb_atom_intern(param->ctx, "group"); }
543 {$$ = xkb_atom_intern(param->ctx, "modifier_map");}
545 { $$ = xkb_atom_intern(param->ctx, "indicator"); }
547 { $$ = XKB_ATOM_NONE; }
549 { $$ = XKB_ATOM_NONE; }
551 { $$ = XKB_ATOM_NONE; }
553 { $$ = XKB_ATOM_NONE; }
556 OptMergeMode : MergeMode { $$ = $1; }
557 | { $$ = MERGE_DEFAULT; }
560 MergeMode : INCLUDE { $$ = MERGE_DEFAULT; }
561 | AUGMENT { $$ = MERGE_AUGMENT; }
562 | OVERRIDE { $$ = MERGE_OVERRIDE; }
563 | REPLACE { $$ = MERGE_REPLACE; }
567 * This used to be MERGE_ALT_FORM. This functionality was
568 * unused and has been removed.
574 OptExprList : ExprList { $$ = $1; }
578 ExprList : ExprList COMMA Expr
579 { $$ = (ExprDef *)AppendStmt(&$1->common, &$3->common); }
584 Expr : Expr DIVIDE Expr
585 { $$ = ExprCreateBinary(EXPR_DIVIDE, $1, $3); }
587 { $$ = ExprCreateBinary(EXPR_ADD, $1, $3); }
589 { $$ = ExprCreateBinary(EXPR_SUBTRACT, $1, $3); }
591 { $$ = ExprCreateBinary(EXPR_MULTIPLY, $1, $3); }
593 { $$ = ExprCreateBinary(EXPR_ASSIGN, $1, $3); }
599 { $$ = ExprCreateUnary(EXPR_NEGATE, $2->value_type, $2); }
601 { $$ = ExprCreateUnary(EXPR_UNARY_PLUS, $2->value_type, $2); }
603 { $$ = ExprCreateUnary(EXPR_NOT, EXPR_TYPE_BOOLEAN, $2); }
605 { $$ = ExprCreateUnary(EXPR_INVERT, $2->value_type, $2); }
608 | FieldSpec OPAREN OptExprList CPAREN %prec OPAREN
609 { $$ = ActionCreate($1, $3); }
616 ActionList : ActionList COMMA Action
617 { $$ = (ExprDef *)AppendStmt(&$1->common, &$3->common); }
622 Action : FieldSpec OPAREN OptExprList CPAREN
623 { $$ = ActionCreate($1, $3); }
629 expr = ExprCreate(EXPR_IDENT, EXPR_TYPE_UNKNOWN);
630 expr->value.str = $1;
633 | FieldSpec DOT FieldSpec
636 expr = ExprCreate(EXPR_FIELD_REF, EXPR_TYPE_UNKNOWN);
637 expr->value.field.element = $1;
638 expr->value.field.field = $3;
641 | FieldSpec OBRACKET Expr CBRACKET
644 expr = ExprCreate(EXPR_ARRAY_REF, EXPR_TYPE_UNKNOWN);
645 expr->value.array.element = XKB_ATOM_NONE;
646 expr->value.array.field = $1;
647 expr->value.array.entry = $3;
650 | FieldSpec DOT FieldSpec OBRACKET Expr CBRACKET
653 expr = ExprCreate(EXPR_ARRAY_REF, EXPR_TYPE_UNKNOWN);
654 expr->value.array.element = $1;
655 expr->value.array.field = $3;
656 expr->value.array.entry = $5;
664 expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_STRING);
665 expr->value.str = $1;
671 expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_INT);
672 expr->value.ival = $1;
682 expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_KEYNAME);
683 expr->value.keyName = $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
706 KeySym : IDENT { $$ = $1; }
707 | SECTION { $$ = strdup("section"); }
710 if ($1 < 10) { /* XK_0 .. XK_9 */
717 snprintf($$, 17, "0x%x", $1);
722 SignedNumber : MINUS Number { $$ = -$2; }
723 | Number { $$ = $1; }
726 Number : FLOAT { $$ = $1; }
727 | INTEGER { $$ = $1; }
730 Float : FLOAT { $$ = 0; }
733 Integer : INTEGER { $$ = $1; }
736 KeyCode : INTEGER { $$ = $1; }
739 Ident : IDENT { $$ = xkb_atom_steal(param->ctx, $1); }
740 | DEFAULT { $$ = xkb_atom_intern(param->ctx, "default"); }
743 String : STRING { $$ = xkb_atom_steal(param->ctx, $1); }
746 OptMapName : MapName { $$ = $1; }
750 MapName : STRING { $$ = $1; }
758 parse(struct xkb_context *ctx, void *scanner, const char *map)
760 struct parser_param param;
762 XkbFile *first = NULL;
764 param.scanner = scanner;
768 * If we got a specific map, we look for it exclusively and return
769 * immediately upon finding it. Otherwise, we need to get the
770 * default map. If we find a map marked as default, we return it
771 * immediately. If there are no maps marked as default, we return
772 * the first map in the file.
775 while ((ret = yyparse(¶m)) == 0 && param.more_maps) {
777 if (streq_not_null(map, param.rtrn->name))
780 FreeXkbFile(param.rtrn);
783 if (param.rtrn->flags & MAP_IS_DEFAULT) {
791 FreeXkbFile(param.rtrn);