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