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