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