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