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