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