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 }
170 enum xkb_file_type file_type;
173 enum merge_mode merge;
174 enum xkb_map_flags mapFlags;
184 GroupCompatDef *groupCompat;
188 KeyAliasDef *keyAlias;
193 %type <num> INTEGER FLOAT
194 %type <str> IDENT STRING
197 %type <ival> Number Integer Float SignedNumber DoodadType
198 %type <merge> MergeMode OptMergeMode
199 %type <file_type> XkbCompositeType FileType
200 %type <mapFlags> Flag Flags OptFlags
201 %type <str> MapName OptMapName
202 %type <sval> FieldSpec Ident Element String
203 %type <keysym> KeySym
204 %type <any> DeclList Decl
205 %type <expr> OptExprList ExprList Expr Term Lhs Terminal ArrayInit KeySyms
206 %type <expr> OptKeySymList KeySymList Action ActionList Coord CoordList
207 %type <var> VarDecl VarDeclList SymbolsBody SymbolsVarDecl
208 %type <vmod> VModDecl VModDefList VModDef
209 %type <interp> InterpretDecl InterpretMatch
210 %type <keyType> KeyTypeDecl
211 %type <syms> SymbolsDecl
212 %type <modMask> ModMapDecl
213 %type <groupCompat> GroupCompatDecl
214 %type <ledMap> LedMapDecl
215 %type <ledName> LedNameDecl
216 %type <keyCode> KeyNameDecl
217 %type <keyAlias> KeyAliasDecl
218 %type <geom> ShapeDecl SectionDecl SectionBody SectionBodyItem RowBody RowBodyItem
219 %type <geom> Keys Key OverlayDecl OverlayKeyList OverlayKey OutlineList OutlineInList
220 %type <geom> DoodadDecl
221 %type <file> XkbFile XkbMapConfigList XkbMapConfig
222 %type <file> XkbCompositeMap
227 * An actual file may contain more than one map. However, if we do things
228 * in the normal yacc way, i.e. aggregate all of the maps into a list and
229 * let the caller find the map it wants, we end up scanning and parsing a
230 * lot of unneeded maps (in the end we always just need one).
231 * Instead of doing that, we make yyparse return one map at a time, and
232 * then call it repeatedly until we find the map we need. Once we find it,
233 * we don't need to parse everything that follows in the file.
234 * This does mean that if we e.g. always use the first map, the file may
235 * contain complete garbage after that. But it's worth it.
238 XkbFile : XkbCompositeMap
239 { $$ = param->rtrn = $1; param->more_maps = true; }
241 { $$ = param->rtrn = $1; param->more_maps = true; YYACCEPT; }
243 { $$ = param->rtrn = NULL; param->more_maps = false; }
246 XkbCompositeMap : OptFlags XkbCompositeType OptMapName OBRACE
249 { $$ = XkbFileCreate(param->ctx, $2, $3, &$5->common, $1); }
252 XkbCompositeType: XKB_KEYMAP { $$ = FILE_TYPE_KEYMAP; }
253 | XKB_SEMANTICS { $$ = FILE_TYPE_KEYMAP; }
254 | XKB_LAYOUT { $$ = FILE_TYPE_KEYMAP; }
257 XkbMapConfigList : XkbMapConfigList XkbMapConfig
262 $$ = (XkbFile *)AppendStmt(&$1->common, &$2->common);
268 XkbMapConfig : OptFlags FileType OptMapName OBRACE
272 if ($2 == FILE_TYPE_GEOMETRY) {
278 $$ = XkbFileCreate(param->ctx, $2, $3, $5, $1);
283 FileType : XKB_KEYCODES { $$ = FILE_TYPE_KEYCODES; }
284 | XKB_TYPES { $$ = FILE_TYPE_TYPES; }
285 | XKB_COMPATMAP { $$ = FILE_TYPE_COMPAT; }
286 | XKB_SYMBOLS { $$ = FILE_TYPE_SYMBOLS; }
287 | XKB_GEOMETRY { $$ = FILE_TYPE_GEOMETRY; }
290 OptFlags : Flags { $$ = $1; }
294 Flags : Flags Flag { $$ = ($1 | $2); }
298 Flag : PARTIAL { $$ = MAP_IS_PARTIAL; }
299 | DEFAULT { $$ = MAP_IS_DEFAULT; }
300 | HIDDEN { $$ = MAP_IS_HIDDEN; }
301 | ALPHANUMERIC_KEYS { $$ = MAP_HAS_ALPHANUMERIC; }
302 | MODIFIER_KEYS { $$ = MAP_HAS_MODIFIER; }
303 | KEYPAD_KEYS { $$ = MAP_HAS_KEYPAD; }
304 | FUNCTION_KEYS { $$ = MAP_HAS_FN; }
305 | ALTERNATE_GROUP { $$ = MAP_IS_ALTGR; }
308 DeclList : DeclList Decl
309 { $$ = AppendStmt($1, $2); }
313 Decl : OptMergeMode VarDecl
318 | OptMergeMode VModDecl
323 | OptMergeMode InterpretDecl
328 | OptMergeMode KeyNameDecl
333 | OptMergeMode KeyAliasDecl
338 | OptMergeMode KeyTypeDecl
343 | OptMergeMode SymbolsDecl
348 | OptMergeMode ModMapDecl
353 | OptMergeMode GroupCompatDecl
358 | OptMergeMode LedMapDecl
363 | OptMergeMode LedNameDecl
368 | OptMergeMode ShapeDecl { $$ = NULL; }
369 | OptMergeMode SectionDecl { $$ = NULL; }
370 | OptMergeMode DoodadDecl { $$ = NULL; }
373 $$ = &IncludeCreate(param->ctx, $2, $1)->common;
378 VarDecl : Lhs EQUALS Expr SEMI
379 { $$ = VarCreate($1, $3); }
381 { $$ = BoolVarCreate($1, true); }
383 { $$ = BoolVarCreate($2, false); }
386 KeyNameDecl : KEYNAME EQUALS KeyCode SEMI
387 { $$ = KeycodeCreate($1, $3); }
390 KeyAliasDecl : ALIAS KEYNAME EQUALS KEYNAME SEMI
391 { $$ = KeyAliasCreate($2, $4); }
394 VModDecl : VIRTUAL_MODS VModDefList SEMI
398 VModDefList : VModDefList COMMA VModDef
399 { $$ = (VModDef *)AppendStmt(&$1->common, &$3->common); }
405 { $$ = VModCreate($1, NULL); }
407 { $$ = VModCreate($1, $3); }
410 InterpretDecl : INTERPRET InterpretMatch OBRACE
413 { $2->def = $4; $$ = $2; }
416 InterpretMatch : KeySym PLUS Expr
417 { $$ = InterpCreate($1, $3); }
419 { $$ = InterpCreate($1, NULL); }
422 VarDeclList : VarDeclList VarDecl
423 { $$ = (VarDef *)AppendStmt(&$1->common, &$2->common); }
428 KeyTypeDecl : TYPE String OBRACE
431 { $$ = KeyTypeCreate($2, $4); }
434 SymbolsDecl : KEY KEYNAME OBRACE
437 { $$ = SymbolsCreate($2, $4); }
440 SymbolsBody : SymbolsBody COMMA SymbolsVarDecl
441 { $$ = (VarDef *)AppendStmt(&$1->common, &$3->common); }
447 SymbolsVarDecl : Lhs EQUALS Expr { $$ = VarCreate($1, $3); }
448 | Lhs EQUALS ArrayInit { $$ = VarCreate($1, $3); }
449 | Ident { $$ = BoolVarCreate($1, true); }
450 | EXCLAM Ident { $$ = BoolVarCreate($2, false); }
451 | ArrayInit { $$ = VarCreate(NULL, $1); }
454 ArrayInit : OBRACKET OptKeySymList CBRACKET
456 | OBRACKET ActionList CBRACKET
457 { $$ = ExprCreateUnary(EXPR_ACTION_LIST, EXPR_TYPE_ACTION, $2); }
460 GroupCompatDecl : GROUP Integer EQUALS Expr SEMI
461 { $$ = GroupCompatCreate($2, $4); }
464 ModMapDecl : MODIFIER_MAP Ident OBRACE ExprList CBRACE SEMI
465 { $$ = ModMapCreate($2, $4); }
468 LedMapDecl: INDICATOR String OBRACE VarDeclList CBRACE SEMI
469 { $$ = LedMapCreate($2, $4); }
472 LedNameDecl: INDICATOR Integer EQUALS Expr SEMI
473 { $$ = LedNameCreate($2, $4, false); }
474 | VIRTUAL INDICATOR Integer EQUALS Expr SEMI
475 { $$ = LedNameCreate($3, $5, true); }
478 ShapeDecl : SHAPE String OBRACE OutlineList CBRACE SEMI
480 | SHAPE String OBRACE CoordList CBRACE SEMI
484 SectionDecl : SECTION String OBRACE SectionBody CBRACE SEMI
488 SectionBody : SectionBody SectionBodyItem { $$ = NULL;}
489 | SectionBodyItem { $$ = NULL; }
492 SectionBodyItem : ROW OBRACE RowBody CBRACE SEMI
495 { FreeStmt(&$1->common); $$ = NULL; }
499 { FreeStmt(&$1->common); $$ = NULL; }
504 RowBody : RowBody RowBodyItem { $$ = NULL;}
505 | RowBodyItem { $$ = NULL; }
508 RowBodyItem : KEYS OBRACE Keys CBRACE SEMI { $$ = NULL; }
510 { FreeStmt(&$1->common); $$ = NULL; }
513 Keys : Keys COMMA Key { $$ = NULL; }
519 | OBRACE ExprList CBRACE
520 { FreeStmt(&$2->common); $$ = NULL; }
523 OverlayDecl : OVERLAY String OBRACE OverlayKeyList CBRACE SEMI
527 OverlayKeyList : OverlayKeyList COMMA OverlayKey { $$ = NULL; }
528 | OverlayKey { $$ = NULL; }
531 OverlayKey : KEYNAME EQUALS KEYNAME { $$ = NULL; }
534 OutlineList : OutlineList COMMA OutlineInList
540 OutlineInList : OBRACE CoordList CBRACE
542 | Ident EQUALS OBRACE CoordList CBRACE
545 { FreeStmt(&$3->common); $$ = NULL; }
548 CoordList : CoordList COMMA Coord
554 Coord : OBRACKET SignedNumber COMMA SignedNumber CBRACKET
558 DoodadDecl : DoodadType String OBRACE VarDeclList CBRACE SEMI
559 { FreeStmt(&$4->common); $$ = NULL; }
562 DoodadType : TEXT { $$ = 0; }
563 | OUTLINE { $$ = 0; }
568 FieldSpec : Ident { $$ = $1; }
569 | Element { $$ = $1; }
573 { $$ = xkb_atom_intern_literal(param->ctx, "action"); }
575 { $$ = xkb_atom_intern_literal(param->ctx, "interpret"); }
577 { $$ = xkb_atom_intern_literal(param->ctx, "type"); }
579 { $$ = xkb_atom_intern_literal(param->ctx, "key"); }
581 { $$ = xkb_atom_intern_literal(param->ctx, "group"); }
583 {$$ = xkb_atom_intern_literal(param->ctx, "modifier_map");}
585 { $$ = xkb_atom_intern_literal(param->ctx, "indicator"); }
587 { $$ = XKB_ATOM_NONE; }
589 { $$ = XKB_ATOM_NONE; }
591 { $$ = XKB_ATOM_NONE; }
593 { $$ = XKB_ATOM_NONE; }
596 OptMergeMode : MergeMode { $$ = $1; }
597 | { $$ = MERGE_DEFAULT; }
600 MergeMode : INCLUDE { $$ = MERGE_DEFAULT; }
601 | AUGMENT { $$ = MERGE_AUGMENT; }
602 | OVERRIDE { $$ = MERGE_OVERRIDE; }
603 | REPLACE { $$ = MERGE_REPLACE; }
607 * This used to be MERGE_ALT_FORM. This functionality was
608 * unused and has been removed.
614 OptExprList : ExprList { $$ = $1; }
618 ExprList : ExprList COMMA Expr
619 { $$ = (ExprDef *)AppendStmt(&$1->common, &$3->common); }
624 Expr : Expr DIVIDE Expr
625 { $$ = ExprCreateBinary(EXPR_DIVIDE, $1, $3); }
627 { $$ = ExprCreateBinary(EXPR_ADD, $1, $3); }
629 { $$ = ExprCreateBinary(EXPR_SUBTRACT, $1, $3); }
631 { $$ = ExprCreateBinary(EXPR_MULTIPLY, $1, $3); }
633 { $$ = ExprCreateBinary(EXPR_ASSIGN, $1, $3); }
639 { $$ = ExprCreateUnary(EXPR_NEGATE, $2->expr.value_type, $2); }
641 { $$ = ExprCreateUnary(EXPR_UNARY_PLUS, $2->expr.value_type, $2); }
643 { $$ = ExprCreateUnary(EXPR_NOT, EXPR_TYPE_BOOLEAN, $2); }
645 { $$ = ExprCreateUnary(EXPR_INVERT, $2->expr.value_type, $2); }
648 | FieldSpec OPAREN OptExprList CPAREN %prec OPAREN
649 { $$ = ExprCreateAction($1, $3); }
656 ActionList : ActionList COMMA Action
657 { $$ = (ExprDef *)AppendStmt(&$1->common, &$3->common); }
662 Action : FieldSpec OPAREN OptExprList CPAREN
663 { $$ = ExprCreateAction($1, $3); }
667 { $$ = ExprCreateIdent($1); }
668 | FieldSpec DOT FieldSpec
669 { $$ = ExprCreateFieldRef($1, $3); }
670 | FieldSpec OBRACKET Expr CBRACKET
671 { $$ = ExprCreateArrayRef(XKB_ATOM_NONE, $1, $3); }
672 | FieldSpec DOT FieldSpec OBRACKET Expr CBRACKET
673 { $$ = ExprCreateArrayRef($1, $3, $5); }
677 { $$ = ExprCreateString($1); }
679 { $$ = ExprCreateInteger($1); }
683 { $$ = ExprCreateKeyName($1); }
686 OptKeySymList : KeySymList { $$ = $1; }
690 KeySymList : KeySymList COMMA KeySym
691 { $$ = ExprAppendKeysymList($1, $3); }
692 | KeySymList COMMA KeySyms
693 { $$ = ExprAppendMultiKeysymList($1, $3); }
695 { $$ = ExprCreateKeysymList($1); }
697 { $$ = ExprCreateMultiKeysymList($1); }
700 KeySyms : OBRACE KeySymList CBRACE
706 if (!resolve_keysym($1, &$$))
707 parser_warn(param, "unrecognized keysym");
710 | SECTION { $$ = XKB_KEY_section; }
714 parser_warn(param, "unrecognized keysym");
715 $$ = XKB_KEY_NoSymbol;
717 else if ($1 < 10) { /* XKB_KEY_0 .. XKB_KEY_9 */
718 $$ = XKB_KEY_0 + (xkb_keysym_t) $1;
722 snprintf(buf, sizeof(buf), "0x%x", $1);
723 if (!resolve_keysym(buf, &$$)) {
724 parser_warn(param, "unrecognized keysym");
725 $$ = XKB_KEY_NoSymbol;
731 SignedNumber : MINUS Number { $$ = -$2; }
732 | Number { $$ = $1; }
735 Number : FLOAT { $$ = $1; }
736 | INTEGER { $$ = $1; }
739 Float : FLOAT { $$ = 0; }
742 Integer : INTEGER { $$ = $1; }
745 KeyCode : INTEGER { $$ = $1; }
748 Ident : IDENT { $$ = xkb_atom_steal(param->ctx, $1); }
749 | DEFAULT { $$ = xkb_atom_intern_literal(param->ctx, "default"); }
752 String : STRING { $$ = xkb_atom_steal(param->ctx, $1); }
755 OptMapName : MapName { $$ = $1; }
759 MapName : STRING { $$ = $1; }
767 parse(struct xkb_context *ctx, void *scanner, const char *map)
770 XkbFile *first = NULL;
771 struct parser_param param = {
777 * If we got a specific map, we look for it exclusively and return
778 * immediately upon finding it. Otherwise, we need to get the
779 * default map. If we find a map marked as default, we return it
780 * immediately. If there are no maps marked as default, we return
781 * the first map in the file.
784 while ((ret = yyparse(¶m)) == 0 && param.more_maps) {
786 if (streq_not_null(map, param.rtrn->name))
789 FreeXkbFile(param.rtrn);
792 if (param.rtrn->flags & MAP_IS_DEFAULT) {
800 FreeXkbFile(param.rtrn);
813 #define scanner param->scanner