1 /************************************************************ 2 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 3 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. 15 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. 24 25 ********************************************************/ 26 27 /* 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 30 * in both! 31 */ 32 33 %{ 34 #include "xkbcomp-priv.h" 35 #include "ast-build.h" 36 #include "parser-priv.h" 37 #include "scanner-utils.h" 38 39 struct parser_param { 40 struct xkb_context *ctx; 41 struct scanner *scanner; 42 XkbFile *rtrn; 43 bool more_maps; 44 }; 45 46 #define parser_err(param, fmt, ...) \ 47 scanner_err((param)->scanner, fmt, ##__VA_ARGS__) 48 49 #define parser_warn(param, fmt, ...) \ 50 scanner_warn((param)->scanner, fmt, ##__VA_ARGS__) 51 52 static void 53 _xkbcommon_error(struct parser_param *param, const char *msg) 54 { 55 parser_err(param, "%s", msg); 56 } 57 58 static bool 59 resolve_keysym(const char *name, xkb_keysym_t *sym_rtrn) 60 { 61 xkb_keysym_t sym; 62 63 if (!name || istreq(name, "any") || istreq(name, "nosymbol")) { 64 *sym_rtrn = XKB_KEY_NoSymbol; 65 return true; 66 } 67 68 if (istreq(name, "none") || istreq(name, "voidsymbol")) { 69 *sym_rtrn = XKB_KEY_VoidSymbol; 70 return true; 71 } 72 73 sym = xkb_keysym_from_name(name, XKB_KEYSYM_NO_FLAGS); 74 if (sym != XKB_KEY_NoSymbol) { 75 *sym_rtrn = sym; 76 return true; 77 } 78 79 return false; 80 } 81 82 #define param_scanner param->scanner 83 %} 84 85 %pure-parser 86 %lex-param { struct scanner *param_scanner } 87 %parse-param { struct parser_param *param } 88 89 %token 90 END_OF_FILE 0 91 ERROR_TOK 255 92 XKB_KEYMAP 1 93 XKB_KEYCODES 2 94 XKB_TYPES 3 95 XKB_SYMBOLS 4 96 XKB_COMPATMAP 5 97 XKB_GEOMETRY 6 98 XKB_SEMANTICS 7 99 XKB_LAYOUT 8 100 INCLUDE 10 101 OVERRIDE 11 102 AUGMENT 12 103 REPLACE 13 104 ALTERNATE 14 105 VIRTUAL_MODS 20 106 TYPE 21 107 INTERPRET 22 108 ACTION_TOK 23 109 KEY 24 110 ALIAS 25 111 GROUP 26 112 MODIFIER_MAP 27 113 INDICATOR 28 114 SHAPE 29 115 KEYS 30 116 ROW 31 117 SECTION 32 118 OVERLAY 33 119 TEXT 34 120 OUTLINE 35 121 SOLID 36 122 LOGO 37 123 VIRTUAL 38 124 EQUALS 40 125 PLUS 41 126 MINUS 42 127 DIVIDE 43 128 TIMES 44 129 OBRACE 45 130 CBRACE 46 131 OPAREN 47 132 CPAREN 48 133 OBRACKET 49 134 CBRACKET 50 135 DOT 51 136 COMMA 52 137 SEMI 53 138 EXCLAM 54 139 INVERT 55 140 STRING 60 141 INTEGER 61 142 FLOAT 62 143 IDENT 63 144 KEYNAME 64 145 PARTIAL 70 146 DEFAULT 71 147 HIDDEN 72 148 ALPHANUMERIC_KEYS 73 149 MODIFIER_KEYS 74 150 KEYPAD_KEYS 75 151 FUNCTION_KEYS 76 152 ALTERNATE_GROUP 77 153 154 %right EQUALS 155 %left PLUS MINUS 156 %left TIMES DIVIDE 157 %left EXCLAM INVERT 158 %left OPAREN 159 160 %start XkbFile 161 162 %union { 163 int ival; 164 int64_t num; 165 enum xkb_file_type file_type; 166 char *str; 167 xkb_atom_t atom; 168 enum merge_mode merge; 169 enum xkb_map_flags mapFlags; 170 xkb_keysym_t keysym; 171 ParseCommon *any; 172 ExprDef *expr; 173 VarDef *var; 174 VModDef *vmod; 175 InterpDef *interp; 176 KeyTypeDef *keyType; 177 SymbolsDef *syms; 178 ModMapDef *modMask; 179 GroupCompatDef *groupCompat; 180 LedMapDef *ledMap; 181 LedNameDef *ledName; 182 KeycodeDef *keyCode; 183 KeyAliasDef *keyAlias; 184 void *geom; 185 XkbFile *file; 186 } 187 188 %type <num> INTEGER FLOAT 189 %type <str> IDENT STRING 190 %type <atom> KEYNAME 191 %type <num> KeyCode 192 %type <ival> Number Integer Float SignedNumber DoodadType 193 %type <merge> MergeMode OptMergeMode 194 %type <file_type> XkbCompositeType FileType 195 %type <mapFlags> Flag Flags OptFlags 196 %type <str> MapName OptMapName 197 %type <atom> FieldSpec Ident Element String 198 %type <keysym> KeySym 199 %type <any> DeclList Decl 200 %type <expr> OptExprList ExprList Expr Term Lhs Terminal ArrayInit KeySyms 201 %type <expr> OptKeySymList KeySymList Action ActionList Coord CoordList 202 %type <var> VarDecl VarDeclList SymbolsBody SymbolsVarDecl 203 %type <vmod> VModDecl VModDefList VModDef 204 %type <interp> InterpretDecl InterpretMatch 205 %type <keyType> KeyTypeDecl 206 %type <syms> SymbolsDecl 207 %type <modMask> ModMapDecl 208 %type <groupCompat> GroupCompatDecl 209 %type <ledMap> LedMapDecl 210 %type <ledName> LedNameDecl 211 %type <keyCode> KeyNameDecl 212 %type <keyAlias> KeyAliasDecl 213 %type <geom> ShapeDecl SectionDecl SectionBody SectionBodyItem RowBody RowBodyItem 214 %type <geom> Keys Key OverlayDecl OverlayKeyList OverlayKey OutlineList OutlineInList 215 %type <geom> DoodadDecl 216 %type <file> XkbFile XkbMapConfigList XkbMapConfig 217 %type <file> XkbCompositeMap 218 219 %destructor { FreeStmt((ParseCommon *) $$); } 220 <any> <expr> <var> <vmod> <interp> <keyType> <syms> <modMask> <groupCompat> 221 <ledMap> <ledName> <keyCode> <keyAlias> 222 /* The destructor also runs on the start symbol when the parser *succeeds*. 223 * The `if` here catches this case. */ 224 %destructor { if (!param->rtrn) FreeXkbFile($$); } <file> 225 %destructor { free($$); } <str> 226 227 %% 228 229 /* 230 * An actual file may contain more than one map. However, if we do things 231 * in the normal yacc way, i.e. aggregate all of the maps into a list and 232 * let the caller find the map it wants, we end up scanning and parsing a 233 * lot of unneeded maps (in the end we always just need one). 234 * Instead of doing that, we make yyparse return one map at a time, and 235 * then call it repeatedly until we find the map we need. Once we find it, 236 * we don't need to parse everything that follows in the file. 237 * This does mean that if we e.g. always use the first map, the file may 238 * contain complete garbage after that. But it's worth it. 239 */ 240 241 XkbFile : XkbCompositeMap 242 { $$ = param->rtrn = $1; param->more_maps = true; } 243 | XkbMapConfig 244 { $$ = param->rtrn = $1; param->more_maps = true; YYACCEPT; } 245 | END_OF_FILE 246 { $$ = param->rtrn = NULL; param->more_maps = false; } 247 ; 248 249 XkbCompositeMap : OptFlags XkbCompositeType OptMapName OBRACE 250 XkbMapConfigList 251 CBRACE SEMI 252 { $$ = XkbFileCreate($2, $3, (ParseCommon *) $5, $1); } 253 ; 254 255 XkbCompositeType: XKB_KEYMAP { $$ = FILE_TYPE_KEYMAP; } 256 | XKB_SEMANTICS { $$ = FILE_TYPE_KEYMAP; } 257 | XKB_LAYOUT { $$ = FILE_TYPE_KEYMAP; } 258 ; 259 260 XkbMapConfigList : XkbMapConfigList XkbMapConfig 261 { 262 if (!$2) 263 $$ = $1; 264 else 265 $$ = (XkbFile *) AppendStmt((ParseCommon *) $1, 266 (ParseCommon *) $2); 267 } 268 | XkbMapConfig 269 { $$ = $1; } 270 ; 271 272 XkbMapConfig : OptFlags FileType OptMapName OBRACE 273 DeclList 274 CBRACE SEMI 275 { 276 if ($2 == FILE_TYPE_GEOMETRY) { 277 free($3); 278 FreeStmt($5); 279 $$ = NULL; 280 } 281 else { 282 $$ = XkbFileCreate($2, $3, $5, $1); 283 } 284 } 285 ; 286 287 FileType : XKB_KEYCODES { $$ = FILE_TYPE_KEYCODES; } 288 | XKB_TYPES { $$ = FILE_TYPE_TYPES; } 289 | XKB_COMPATMAP { $$ = FILE_TYPE_COMPAT; } 290 | XKB_SYMBOLS { $$ = FILE_TYPE_SYMBOLS; } 291 | XKB_GEOMETRY { $$ = FILE_TYPE_GEOMETRY; } 292 ; 293 294 OptFlags : Flags { $$ = $1; } 295 | { $$ = 0; } 296 ; 297 298 Flags : Flags Flag { $$ = ($1 | $2); } 299 | Flag { $$ = $1; } 300 ; 301 302 Flag : PARTIAL { $$ = MAP_IS_PARTIAL; } 303 | DEFAULT { $$ = MAP_IS_DEFAULT; } 304 | HIDDEN { $$ = MAP_IS_HIDDEN; } 305 | ALPHANUMERIC_KEYS { $$ = MAP_HAS_ALPHANUMERIC; } 306 | MODIFIER_KEYS { $$ = MAP_HAS_MODIFIER; } 307 | KEYPAD_KEYS { $$ = MAP_HAS_KEYPAD; } 308 | FUNCTION_KEYS { $$ = MAP_HAS_FN; } 309 | ALTERNATE_GROUP { $$ = MAP_IS_ALTGR; } 310 ; 311 312 DeclList : DeclList Decl 313 { $$ = AppendStmt($1, $2); } 314 | { $$ = NULL; } 315 ; 316 317 Decl : OptMergeMode VarDecl 318 { 319 $2->merge = $1; 320 $$ = (ParseCommon *) $2; 321 } 322 | OptMergeMode VModDecl 323 { 324 $2->merge = $1; 325 $$ = (ParseCommon *) $2; 326 } 327 | OptMergeMode InterpretDecl 328 { 329 $2->merge = $1; 330 $$ = (ParseCommon *) $2; 331 } 332 | OptMergeMode KeyNameDecl 333 { 334 $2->merge = $1; 335 $$ = (ParseCommon *) $2; 336 } 337 | OptMergeMode KeyAliasDecl 338 { 339 $2->merge = $1; 340 $$ = (ParseCommon *) $2; 341 } 342 | OptMergeMode KeyTypeDecl 343 { 344 $2->merge = $1; 345 $$ = (ParseCommon *) $2; 346 } 347 | OptMergeMode SymbolsDecl 348 { 349 $2->merge = $1; 350 $$ = (ParseCommon *) $2; 351 } 352 | OptMergeMode ModMapDecl 353 { 354 $2->merge = $1; 355 $$ = (ParseCommon *) $2; 356 } 357 | OptMergeMode GroupCompatDecl 358 { 359 $2->merge = $1; 360 $$ = (ParseCommon *) $2; 361 } 362 | OptMergeMode LedMapDecl 363 { 364 $2->merge = $1; 365 $$ = (ParseCommon *) $2; 366 } 367 | OptMergeMode LedNameDecl 368 { 369 $2->merge = $1; 370 $$ = (ParseCommon *) $2; 371 } 372 | OptMergeMode ShapeDecl { $$ = NULL; } 373 | OptMergeMode SectionDecl { $$ = NULL; } 374 | OptMergeMode DoodadDecl { $$ = NULL; } 375 | MergeMode STRING 376 { 377 $$ = (ParseCommon *) IncludeCreate(param->ctx, $2, $1); 378 free($2); 379 } 380 ; 381 382 VarDecl : Lhs EQUALS Expr SEMI 383 { $$ = VarCreate($1, $3); } 384 | Ident SEMI 385 { $$ = BoolVarCreate($1, true); } 386 | EXCLAM Ident SEMI 387 { $$ = BoolVarCreate($2, false); } 388 ; 389 390 KeyNameDecl : KEYNAME EQUALS KeyCode SEMI 391 { $$ = KeycodeCreate($1, $3); } 392 ; 393 394 KeyAliasDecl : ALIAS KEYNAME EQUALS KEYNAME SEMI 395 { $$ = KeyAliasCreate($2, $4); } 396 ; 397 398 VModDecl : VIRTUAL_MODS VModDefList SEMI 399 { $$ = $2; } 400 ; 401 402 VModDefList : VModDefList COMMA VModDef 403 { $$ = (VModDef *) AppendStmt((ParseCommon *) $1, 404 (ParseCommon *) $3); } 405 | VModDef 406 { $$ = $1; } 407 ; 408 409 VModDef : Ident 410 { $$ = VModCreate($1, NULL); } 411 | Ident EQUALS Expr 412 { $$ = VModCreate($1, $3); } 413 ; 414 415 InterpretDecl : INTERPRET InterpretMatch OBRACE 416 VarDeclList 417 CBRACE SEMI 418 { $2->def = $4; $$ = $2; } 419 ; 420 421 InterpretMatch : KeySym PLUS Expr 422 { $$ = InterpCreate($1, $3); } 423 | KeySym 424 { $$ = InterpCreate($1, NULL); } 425 ; 426 427 VarDeclList : VarDeclList VarDecl 428 { $$ = (VarDef *) AppendStmt((ParseCommon *) $1, 429 (ParseCommon *) $2); } 430 | VarDecl 431 { $$ = $1; } 432 ; 433 434 KeyTypeDecl : TYPE String OBRACE 435 VarDeclList 436 CBRACE SEMI 437 { $$ = KeyTypeCreate($2, $4); } 438 ; 439 440 SymbolsDecl : KEY KEYNAME OBRACE 441 SymbolsBody 442 CBRACE SEMI 443 { $$ = SymbolsCreate($2, $4); } 444 ; 445 446 SymbolsBody : SymbolsBody COMMA SymbolsVarDecl 447 { $$ = (VarDef *) AppendStmt((ParseCommon *) $1, 448 (ParseCommon *) $3); } 449 | SymbolsVarDecl 450 { $$ = $1; } 451 | { $$ = NULL; } 452 ; 453 454 SymbolsVarDecl : Lhs EQUALS Expr { $$ = VarCreate($1, $3); } 455 | Lhs EQUALS ArrayInit { $$ = VarCreate($1, $3); } 456 | Ident { $$ = BoolVarCreate($1, true); } 457 | EXCLAM Ident { $$ = BoolVarCreate($2, false); } 458 | ArrayInit { $$ = VarCreate(NULL, $1); } 459 ; 460 461 ArrayInit : OBRACKET OptKeySymList CBRACKET 462 { $$ = $2; } 463 | OBRACKET ActionList CBRACKET 464 { $$ = ExprCreateUnary(EXPR_ACTION_LIST, EXPR_TYPE_ACTION, $2); } 465 ; 466 467 GroupCompatDecl : GROUP Integer EQUALS Expr SEMI 468 { $$ = GroupCompatCreate($2, $4); } 469 ; 470 471 ModMapDecl : MODIFIER_MAP Ident OBRACE ExprList CBRACE SEMI 472 { $$ = ModMapCreate($2, $4); } 473 ; 474 475 LedMapDecl: INDICATOR String OBRACE VarDeclList CBRACE SEMI 476 { $$ = LedMapCreate($2, $4); } 477 ; 478 479 LedNameDecl: INDICATOR Integer EQUALS Expr SEMI 480 { $$ = LedNameCreate($2, $4, false); } 481 | VIRTUAL INDICATOR Integer EQUALS Expr SEMI 482 { $$ = LedNameCreate($3, $5, true); } 483 ; 484 485 ShapeDecl : SHAPE String OBRACE OutlineList CBRACE SEMI 486 { $$ = NULL; } 487 | SHAPE String OBRACE CoordList CBRACE SEMI 488 { (void) $4; $$ = NULL; } 489 ; 490 491 SectionDecl : SECTION String OBRACE SectionBody CBRACE SEMI 492 { $$ = NULL; } 493 ; 494 495 SectionBody : SectionBody SectionBodyItem { $$ = NULL;} 496 | SectionBodyItem { $$ = NULL; } 497 ; 498 499 SectionBodyItem : ROW OBRACE RowBody CBRACE SEMI 500 { $$ = NULL; } 501 | VarDecl 502 { FreeStmt((ParseCommon *) $1); $$ = NULL; } 503 | DoodadDecl 504 { $$ = NULL; } 505 | LedMapDecl 506 { FreeStmt((ParseCommon *) $1); $$ = NULL; } 507 | OverlayDecl 508 { $$ = NULL; } 509 ; 510 511 RowBody : RowBody RowBodyItem { $$ = NULL;} 512 | RowBodyItem { $$ = NULL; } 513 ; 514 515 RowBodyItem : KEYS OBRACE Keys CBRACE SEMI { $$ = NULL; } 516 | VarDecl 517 { FreeStmt((ParseCommon *) $1); $$ = NULL; } 518 ; 519 520 Keys : Keys COMMA Key { $$ = NULL; } 521 | Key { $$ = NULL; } 522 ; 523 524 Key : KEYNAME 525 { $$ = NULL; } 526 | OBRACE ExprList CBRACE 527 { FreeStmt((ParseCommon *) $2); $$ = NULL; } 528 ; 529 530 OverlayDecl : OVERLAY String OBRACE OverlayKeyList CBRACE SEMI 531 { $$ = NULL; } 532 ; 533 534 OverlayKeyList : OverlayKeyList COMMA OverlayKey { $$ = NULL; } 535 | OverlayKey { $$ = NULL; } 536 ; 537 538 OverlayKey : KEYNAME EQUALS KEYNAME { $$ = NULL; } 539 ; 540 541 OutlineList : OutlineList COMMA OutlineInList 542 { $$ = NULL;} 543 | OutlineInList 544 { $$ = NULL; } 545 ; 546 547 OutlineInList : OBRACE CoordList CBRACE 548 { (void) $2; $$ = NULL; } 549 | Ident EQUALS OBRACE CoordList CBRACE 550 { (void) $4; $$ = NULL; } 551 | Ident EQUALS Expr 552 { FreeStmt((ParseCommon *) $3); $$ = NULL; } 553 ; 554 555 CoordList : CoordList COMMA Coord 556 { (void) $1; (void) $3; $$ = NULL; } 557 | Coord 558 { (void) $1; $$ = NULL; } 559 ; 560 561 Coord : OBRACKET SignedNumber COMMA SignedNumber CBRACKET 562 { $$ = NULL; } 563 ; 564 565 DoodadDecl : DoodadType String OBRACE VarDeclList CBRACE SEMI 566 { FreeStmt((ParseCommon *) $4); $$ = NULL; } 567 ; 568 569 DoodadType : TEXT { $$ = 0; } 570 | OUTLINE { $$ = 0; } 571 | SOLID { $$ = 0; } 572 | LOGO { $$ = 0; } 573 ; 574 575 FieldSpec : Ident { $$ = $1; } 576 | Element { $$ = $1; } 577 ; 578 579 Element : ACTION_TOK 580 { $$ = xkb_atom_intern_literal(param->ctx, "action"); } 581 | INTERPRET 582 { $$ = xkb_atom_intern_literal(param->ctx, "interpret"); } 583 | TYPE 584 { $$ = xkb_atom_intern_literal(param->ctx, "type"); } 585 | KEY 586 { $$ = xkb_atom_intern_literal(param->ctx, "key"); } 587 | GROUP 588 { $$ = xkb_atom_intern_literal(param->ctx, "group"); } 589 | MODIFIER_MAP 590 {$$ = xkb_atom_intern_literal(param->ctx, "modifier_map");} 591 | INDICATOR 592 { $$ = xkb_atom_intern_literal(param->ctx, "indicator"); } 593 | SHAPE 594 { $$ = XKB_ATOM_NONE; } 595 | ROW 596 { $$ = XKB_ATOM_NONE; } 597 | SECTION 598 { $$ = XKB_ATOM_NONE; } 599 | TEXT 600 { $$ = XKB_ATOM_NONE; } 601 ; 602 603 OptMergeMode : MergeMode { $$ = $1; } 604 | { $$ = MERGE_DEFAULT; } 605 ; 606 607 MergeMode : INCLUDE { $$ = MERGE_DEFAULT; } 608 | AUGMENT { $$ = MERGE_AUGMENT; } 609 | OVERRIDE { $$ = MERGE_OVERRIDE; } 610 | REPLACE { $$ = MERGE_REPLACE; } 611 | ALTERNATE 612 { 613 /* 614 * This used to be MERGE_ALT_FORM. This functionality was 615 * unused and has been removed. 616 */ 617 $$ = MERGE_DEFAULT; 618 } 619 ; 620 621 OptExprList : ExprList { $$ = $1; } 622 | { $$ = NULL; } 623 ; 624 625 ExprList : ExprList COMMA Expr 626 { $$ = (ExprDef *) AppendStmt((ParseCommon *) $1, 627 (ParseCommon *) $3); } 628 | Expr 629 { $$ = $1; } 630 ; 631 632 Expr : Expr DIVIDE Expr 633 { $$ = ExprCreateBinary(EXPR_DIVIDE, $1, $3); } 634 | Expr PLUS Expr 635 { $$ = ExprCreateBinary(EXPR_ADD, $1, $3); } 636 | Expr MINUS Expr 637 { $$ = ExprCreateBinary(EXPR_SUBTRACT, $1, $3); } 638 | Expr TIMES Expr 639 { $$ = ExprCreateBinary(EXPR_MULTIPLY, $1, $3); } 640 | Lhs EQUALS Expr 641 { $$ = ExprCreateBinary(EXPR_ASSIGN, $1, $3); } 642 | Term 643 { $$ = $1; } 644 ; 645 646 Term : MINUS Term 647 { $$ = ExprCreateUnary(EXPR_NEGATE, $2->expr.value_type, $2); } 648 | PLUS Term 649 { $$ = ExprCreateUnary(EXPR_UNARY_PLUS, $2->expr.value_type, $2); } 650 | EXCLAM Term 651 { $$ = ExprCreateUnary(EXPR_NOT, EXPR_TYPE_BOOLEAN, $2); } 652 | INVERT Term 653 { $$ = ExprCreateUnary(EXPR_INVERT, $2->expr.value_type, $2); } 654 | Lhs 655 { $$ = $1; } 656 | FieldSpec OPAREN OptExprList CPAREN %prec OPAREN 657 { $$ = ExprCreateAction($1, $3); } 658 | Terminal 659 { $$ = $1; } 660 | OPAREN Expr CPAREN 661 { $$ = $2; } 662 ; 663 664 ActionList : ActionList COMMA Action 665 { $$ = (ExprDef *) AppendStmt((ParseCommon *) $1, 666 (ParseCommon *) $3); } 667 | Action 668 { $$ = $1; } 669 ; 670 671 Action : FieldSpec OPAREN OptExprList CPAREN 672 { $$ = ExprCreateAction($1, $3); } 673 ; 674 675 Lhs : FieldSpec 676 { $$ = ExprCreateIdent($1); } 677 | FieldSpec DOT FieldSpec 678 { $$ = ExprCreateFieldRef($1, $3); } 679 | FieldSpec OBRACKET Expr CBRACKET 680 { $$ = ExprCreateArrayRef(XKB_ATOM_NONE, $1, $3); } 681 | FieldSpec DOT FieldSpec OBRACKET Expr CBRACKET 682 { $$ = ExprCreateArrayRef($1, $3, $5); } 683 ; 684 685 Terminal : String 686 { $$ = ExprCreateString($1); } 687 | Integer 688 { $$ = ExprCreateInteger($1); } 689 | Float 690 { $$ = NULL; } 691 | KEYNAME 692 { $$ = ExprCreateKeyName($1); } 693 ; 694 695 OptKeySymList : KeySymList { $$ = $1; } 696 | { $$ = NULL; } 697 ; 698 699 KeySymList : KeySymList COMMA KeySym 700 { $$ = ExprAppendKeysymList($1, $3); } 701 | KeySymList COMMA KeySyms 702 { $$ = ExprAppendMultiKeysymList($1, $3); } 703 | KeySym 704 { $$ = ExprCreateKeysymList($1); } 705 | KeySyms 706 { $$ = ExprCreateMultiKeysymList($1); } 707 ; 708 709 KeySyms : OBRACE KeySymList CBRACE 710 { $$ = $2; } 711 ; 712 713 KeySym : IDENT 714 { 715 if (!resolve_keysym($1, &$$)) 716 parser_warn(param, "unrecognized keysym \"%s\"", $1); 717 free($1); 718 } 719 | SECTION { $$ = XKB_KEY_section; } 720 | Integer 721 { 722 if ($1 < 0) { 723 parser_warn(param, "unrecognized keysym \"%d\"", $1); 724 $$ = XKB_KEY_NoSymbol; 725 } 726 else if ($1 < 10) { /* XKB_KEY_0 .. XKB_KEY_9 */ 727 $$ = XKB_KEY_0 + (xkb_keysym_t) $1; 728 } 729 else { 730 char buf[17]; 731 snprintf(buf, sizeof(buf), "0x%x", $1); 732 if (!resolve_keysym(buf, &$$)) { 733 parser_warn(param, "unrecognized keysym \"%s\"", buf); 734 $$ = XKB_KEY_NoSymbol; 735 } 736 } 737 } 738 ; 739 740 SignedNumber : MINUS Number { $$ = -$2; } 741 | Number { $$ = $1; } 742 ; 743 744 Number : FLOAT { $$ = $1; } 745 | INTEGER { $$ = $1; } 746 ; 747 748 Float : FLOAT { $$ = 0; } 749 ; 750 751 Integer : INTEGER { $$ = $1; } 752 ; 753 754 KeyCode : INTEGER { $$ = $1; } 755 ; 756 757 Ident : IDENT { $$ = xkb_atom_steal(param->ctx, $1); } 758 | DEFAULT { $$ = xkb_atom_intern_literal(param->ctx, "default"); } 759 ; 760 761 String : STRING { $$ = xkb_atom_steal(param->ctx, $1); } 762 ; 763 764 OptMapName : MapName { $$ = $1; } 765 | { $$ = NULL; } 766 ; 767 768 MapName : STRING { $$ = $1; } 769 ; 770 771 %% 772 773 XkbFile * 774 parse(struct xkb_context *ctx, struct scanner *scanner, const char *map) 775 { 776 int ret; 777 XkbFile *first = NULL; 778 struct parser_param param = { 779 .scanner = scanner, 780 .ctx = ctx, 781 .rtrn = NULL, 782 }; 783 784 /* 785 * If we got a specific map, we look for it exclusively and return 786 * immediately upon finding it. Otherwise, we need to get the 787 * default map. If we find a map marked as default, we return it 788 * immediately. If there are no maps marked as default, we return 789 * the first map in the file. 790 */ 791 792 while ((ret = yyparse(¶m)) == 0 && param.more_maps) { 793 if (map) { 794 if (streq_not_null(map, param.rtrn->name)) 795 return param.rtrn; 796 else 797 FreeXkbFile(param.rtrn); 798 } 799 else { 800 if (param.rtrn->flags & MAP_IS_DEFAULT) { 801 FreeXkbFile(first); 802 return param.rtrn; 803 } 804 else if (!first) { 805 first = param.rtrn; 806 } 807 else { 808 FreeXkbFile(param.rtrn); 809 } 810 } 811 param.rtrn = NULL; 812 } 813 814 if (ret != 0) { 815 FreeXkbFile(first); 816 return NULL; 817 } 818 819 if (first) 820 log_vrb(ctx, 5, 821 "No map in include statement, but \"%s\" contains several; " 822 "Using first defined map, \"%s\"\n", 823 scanner->file_name, first->name); 824 825 return first; 826 } 827