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