parser: fix quadratic pointer chasing
[platform/upstream/libxkbcommon.git] / src / xkbcomp / parser.y
1 /************************************************************
2  Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3
4  Permission to use, copy, modify, and distribute this
5  software and its documentation for any purpose and without
6  fee is hereby granted, provided that the above copyright
7  notice appear in all copies and that both that copyright
8  notice and this permission notice appear in supporting
9  documentation, and that the name of Silicon Graphics not be
10  used in advertising or publicity pertaining to distribution
11  of the software without specific prior written permission.
12  Silicon Graphics makes no representation about the suitability
13  of this software for any purpose. It is provided "as is"
14  without any express or implied warranty.
15
16  SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17  SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18  AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19  GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21  DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22  OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23  THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25  ********************************************************/
26
27 /*
28  * The parser should work with reasonably recent versions of either
29  * bison or byacc.  So if you make changes, try to make sure it works
30  * in both!
31  */
32
33 %{
34 #include "xkbcomp/xkbcomp-priv.h"
35 #include "xkbcomp/ast-build.h"
36 #include "xkbcomp/parser-priv.h"
37 #include "scanner-utils.h"
38
39 struct parser_param {
40     struct xkb_context *ctx;
41     struct scanner *scanner;
42     XkbFile *rtrn;
43     bool more_maps;
44 };
45
46 #define parser_err(param, fmt, ...) \
47     scanner_err((param)->scanner, fmt, ##__VA_ARGS__)
48
49 #define parser_warn(param, fmt, ...) \
50     scanner_warn((param)->scanner, fmt, ##__VA_ARGS__)
51
52 static void
53 _xkbcommon_error(struct parser_param *param, const char *msg)
54 {
55     parser_err(param, "%s", msg);
56 }
57
58 static bool
59 resolve_keysym(const char *name, xkb_keysym_t *sym_rtrn)
60 {
61     xkb_keysym_t sym;
62
63     if (!name || istreq(name, "any") || istreq(name, "nosymbol")) {
64         *sym_rtrn = XKB_KEY_NoSymbol;
65         return true;
66     }
67
68     if (istreq(name, "none") || istreq(name, "voidsymbol")) {
69         *sym_rtrn = XKB_KEY_VoidSymbol;
70         return true;
71     }
72
73     sym = xkb_keysym_from_name(name, XKB_KEYSYM_NO_FLAGS);
74     if (sym != XKB_KEY_NoSymbol) {
75         *sym_rtrn = sym;
76         return true;
77     }
78
79     return false;
80 }
81
82 #define param_scanner param->scanner
83 %}
84
85 %pure-parser
86 %lex-param      { struct scanner *param_scanner }
87 %parse-param    { struct parser_param *param }
88
89 %token
90         END_OF_FILE     0
91         ERROR_TOK       255
92         XKB_KEYMAP      1
93         XKB_KEYCODES    2
94         XKB_TYPES       3
95         XKB_SYMBOLS     4
96         XKB_COMPATMAP   5
97         XKB_GEOMETRY    6
98         XKB_SEMANTICS   7
99         XKB_LAYOUT      8
100         INCLUDE         10
101         OVERRIDE        11
102         AUGMENT         12
103         REPLACE         13
104         ALTERNATE       14
105         VIRTUAL_MODS    20
106         TYPE            21
107         INTERPRET       22
108         ACTION_TOK      23
109         KEY             24
110         ALIAS           25
111         GROUP           26
112         MODIFIER_MAP    27
113         INDICATOR       28
114         SHAPE           29
115         KEYS            30
116         ROW             31
117         SECTION         32
118         OVERLAY         33
119         TEXT            34
120         OUTLINE         35
121         SOLID           36
122         LOGO            37
123         VIRTUAL         38
124         EQUALS          40
125         PLUS            41
126         MINUS           42
127         DIVIDE          43
128         TIMES           44
129         OBRACE          45
130         CBRACE          46
131         OPAREN          47
132         CPAREN          48
133         OBRACKET        49
134         CBRACKET        50
135         DOT             51
136         COMMA           52
137         SEMI            53
138         EXCLAM          54
139         INVERT          55
140         STRING          60
141         INTEGER         61
142         FLOAT           62
143         IDENT           63
144         KEYNAME         64
145         PARTIAL         70
146         DEFAULT         71
147         HIDDEN          72
148         ALPHANUMERIC_KEYS       73
149         MODIFIER_KEYS           74
150         KEYPAD_KEYS             75
151         FUNCTION_KEYS           76
152         ALTERNATE_GROUP         77
153
154 %right  EQUALS
155 %left   PLUS MINUS
156 %left   TIMES DIVIDE
157 %left   EXCLAM INVERT
158 %left   OPAREN
159
160 %start  XkbFile
161
162 %union  {
163         int              ival;
164         int64_t          num;
165         enum xkb_file_type file_type;
166         char            *str;
167         xkb_atom_t      atom;
168         enum merge_mode merge;
169         enum xkb_map_flags mapFlags;
170         xkb_keysym_t    keysym;
171         ParseCommon     *any;
172         struct { ParseCommon *head; ParseCommon *last; } anyList;
173         ExprDef         *expr;
174         struct { ExprDef *head; ExprDef *last; } exprList;
175         VarDef          *var;
176         struct { VarDef *head; VarDef *last; } varList;
177         VModDef         *vmod;
178         struct { VModDef *head; VModDef *last; } vmodList;
179         InterpDef       *interp;
180         KeyTypeDef      *keyType;
181         SymbolsDef      *syms;
182         ModMapDef       *modMask;
183         GroupCompatDef  *groupCompat;
184         LedMapDef       *ledMap;
185         LedNameDef      *ledName;
186         KeycodeDef      *keyCode;
187         KeyAliasDef     *keyAlias;
188         void            *geom;
189         XkbFile         *file;
190         struct { XkbFile *head; XkbFile *last; } fileList;
191 }
192
193 %type <num>     INTEGER FLOAT
194 %type <str>     IDENT STRING
195 %type <atom>    KEYNAME
196 %type <num>     KeyCode
197 %type <ival>    Number Integer Float SignedNumber DoodadType
198 %type <merge>   MergeMode OptMergeMode
199 %type <file_type> XkbCompositeType FileType
200 %type <mapFlags> Flag Flags OptFlags
201 %type <str>     MapName OptMapName
202 %type <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                             /*
315                              * TODO: This is needed because of VModDecl, which
316                              * is a list and is "inlined" into the DeclList.
317                              * Should change to avoid the O(N)-append behavior,
318                              * like we do in the other lists.
319                              */
320                             if ($2) {
321                                 if (!$1.head)
322                                     $$.head = $2;
323                                 else
324                                     $$.head = $1.head;
325                                 if (!$1.last)
326                                     $$.last = $2;
327                                 else
328                                     $$.last = $1.last->next = $2;
329                                 while ($$.last->next)
330                                     $$.last = $$.last->next;
331                             }
332                         }
333                 |       { $$.head = $$.last = NULL; }
334                 ;
335
336 Decl            :       OptMergeMode VarDecl
337                         {
338                             $2->merge = $1;
339                             $$ = (ParseCommon *) $2;
340                         }
341                 |       OptMergeMode VModDecl
342                         {
343                             for (VModDef *vmod = $2.head; vmod; vmod = (VModDef *) vmod->common.next)
344                                 vmod->merge = $1;
345                             $$ = (ParseCommon *) $2.head;
346                         }
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(param, "unrecognized keysym \"%s\"", $1);
732                             free($1);
733                         }
734                 |       SECTION { $$ = XKB_KEY_section; }
735                 |       Integer
736                         {
737                             if ($1 < 0) {
738                                 parser_warn(param, "unrecognized keysym \"%d\"", $1);
739                                 $$ = XKB_KEY_NoSymbol;
740                             }
741                             else if ($1 < 10) {      /* XKB_KEY_0 .. XKB_KEY_9 */
742                                 $$ = XKB_KEY_0 + (xkb_keysym_t) $1;
743                             }
744                             else {
745                                 char buf[17];
746                                 snprintf(buf, sizeof(buf), "0x%x", $1);
747                                 if (!resolve_keysym(buf, &$$)) {
748                                     parser_warn(param, "unrecognized keysym \"%s\"", buf);
749                                     $$ = XKB_KEY_NoSymbol;
750                                 }
751                             }
752                         }
753                 ;
754
755 SignedNumber    :       MINUS Number    { $$ = -$2; }
756                 |       Number          { $$ = $1; }
757                 ;
758
759 Number          :       FLOAT   { $$ = $1; }
760                 |       INTEGER { $$ = $1; }
761                 ;
762
763 Float           :       FLOAT   { $$ = 0; }
764                 ;
765
766 Integer         :       INTEGER { $$ = $1; }
767                 ;
768
769 KeyCode         :       INTEGER { $$ = $1; }
770                 ;
771
772 Ident           :       IDENT   { $$ = xkb_atom_intern(param->ctx, $1, strlen($1)); free($1); }
773                 |       DEFAULT { $$ = xkb_atom_intern_literal(param->ctx, "default"); }
774                 ;
775
776 String          :       STRING  { $$ = xkb_atom_intern(param->ctx, $1, strlen($1)); free($1); }
777                 ;
778
779 OptMapName      :       MapName { $$ = $1; }
780                 |               { $$ = NULL; }
781                 ;
782
783 MapName         :       STRING  { $$ = $1; }
784                 ;
785
786 %%
787
788 XkbFile *
789 parse(struct xkb_context *ctx, struct scanner *scanner, const char *map)
790 {
791     int ret;
792     XkbFile *first = NULL;
793     struct parser_param param = {
794         .scanner = scanner,
795         .ctx = ctx,
796         .rtrn = NULL,
797         .more_maps = false,
798     };
799
800     /*
801      * If we got a specific map, we look for it exclusively and return
802      * immediately upon finding it. Otherwise, we need to get the
803      * default map. If we find a map marked as default, we return it
804      * immediately. If there are no maps marked as default, we return
805      * the first map in the file.
806      */
807
808     while ((ret = yyparse(&param)) == 0 && param.more_maps) {
809         if (map) {
810             if (streq_not_null(map, param.rtrn->name))
811                 return param.rtrn;
812             else
813                 FreeXkbFile(param.rtrn);
814         }
815         else {
816             if (param.rtrn->flags & MAP_IS_DEFAULT) {
817                 FreeXkbFile(first);
818                 return param.rtrn;
819             }
820             else if (!first) {
821                 first = param.rtrn;
822             }
823             else {
824                 FreeXkbFile(param.rtrn);
825             }
826         }
827         param.rtrn = NULL;
828     }
829
830     if (ret != 0) {
831         FreeXkbFile(first);
832         return NULL;
833     }
834
835     if (first)
836         log_vrb(ctx, 5,
837                 "No map in include statement, but \"%s\" contains several; "
838                 "Using first defined map, \"%s\"\n",
839                 scanner->file_name, first->name);
840
841     return first;
842 }