• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
_xkbcommon_error(struct parser_param * param,const char * msg)53 _xkbcommon_error(struct parser_param *param, const char *msg)
54 {
55     parser_err(param, "%s", msg);
56 }
57 
58 static bool
resolve_keysym(const char * name,xkb_keysym_t * sym_rtrn)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(&param)) == 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