expr: add 'ident' value to ExprDef union
[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, 1); }
384                 |       EXCLAM Ident SEMI
385                         { $$ = BoolVarCreate($2, 0); }
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, 1); }
452                 |       EXCLAM Ident            { $$ = BoolVarCreate($2, 0); }
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                         {
670                             ExprDef *expr;
671                             expr = ExprCreate(EXPR_IDENT, EXPR_TYPE_UNKNOWN);
672                             expr->value.ident = $1;
673                             $$ = expr;
674                         }
675                 |       FieldSpec DOT FieldSpec
676                         {
677                             ExprDef *expr;
678                             expr = ExprCreate(EXPR_FIELD_REF, EXPR_TYPE_UNKNOWN);
679                             expr->value.field.element = $1;
680                             expr->value.field.field = $3;
681                             $$ = expr;
682                         }
683                 |       FieldSpec OBRACKET Expr CBRACKET
684                         {
685                             ExprDef *expr;
686                             expr = ExprCreate(EXPR_ARRAY_REF, EXPR_TYPE_UNKNOWN);
687                             expr->value.array.element = XKB_ATOM_NONE;
688                             expr->value.array.field = $1;
689                             expr->value.array.entry = $3;
690                             $$ = expr;
691                         }
692                 |       FieldSpec DOT FieldSpec OBRACKET Expr CBRACKET
693                         {
694                             ExprDef *expr;
695                             expr = ExprCreate(EXPR_ARRAY_REF, EXPR_TYPE_UNKNOWN);
696                             expr->value.array.element = $1;
697                             expr->value.array.field = $3;
698                             expr->value.array.entry = $5;
699                             $$ = expr;
700                         }
701                 ;
702
703 Terminal        :       String
704                         {
705                             ExprDef *expr;
706                             expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_STRING);
707                             expr->value.str = $1;
708                             $$ = expr;
709                         }
710                 |       Integer
711                         {
712                             ExprDef *expr;
713                             expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_INT);
714                             expr->value.ival = $1;
715                             $$ = expr;
716                         }
717                 |       Float
718                         {
719                             $$ = NULL;
720                         }
721                 |       KEYNAME
722                         {
723                             ExprDef *expr;
724                             expr = ExprCreate(EXPR_VALUE, EXPR_TYPE_KEYNAME);
725                             expr->value.keyName = $1;
726                             $$ = expr;
727                         }
728                 ;
729
730 OptKeySymList   :       KeySymList      { $$ = $1; }
731                 |                       { $$ = NULL; }
732                 ;
733
734 KeySymList      :       KeySymList COMMA KeySym
735                         { $$ = AppendKeysymList($1, $3); }
736                 |       KeySymList COMMA KeySyms
737                         { $$ = AppendMultiKeysymList($1, $3); }
738                 |       KeySym
739                         { $$ = CreateKeysymList($1); }
740                 |       KeySyms
741                         { $$ = CreateMultiKeysymList($1); }
742                 ;
743
744 KeySyms         :       OBRACE KeySymList CBRACE
745                         { $$ = $2; }
746                 ;
747
748 KeySym          :       IDENT
749                         {
750                             if (!resolve_keysym($1, &$$))
751                                 parser_warn(param, "unrecognized keysym");
752                             free($1);
753                         }
754                 |       SECTION { $$ = XKB_KEY_section; }
755                 |       Integer
756                         {
757                             if ($1 < 10) {      /* XKB_KEY_0 .. XKB_KEY_9 */
758                                 $$ = XKB_KEY_0 + $1;
759                             }
760                             else {
761                                 char buf[17];
762                                 snprintf(buf, sizeof(buf), "0x%x", $1);
763                                 if (!resolve_keysym(buf, &$$))
764                                     parser_warn(param, "unrecognized keysym");
765                             }
766                         }
767                 ;
768
769 SignedNumber    :       MINUS Number    { $$ = -$2; }
770                 |       Number          { $$ = $1; }
771                 ;
772
773 Number          :       FLOAT   { $$ = $1; }
774                 |       INTEGER { $$ = $1; }
775                 ;
776
777 Float           :       FLOAT   { $$ = 0; }
778                 ;
779
780 Integer         :       INTEGER { $$ = $1; }
781                 ;
782
783 KeyCode         :       INTEGER { $$ = $1; }
784                 ;
785
786 Ident           :       IDENT   { $$ = xkb_atom_steal(param->ctx, $1); }
787                 |       DEFAULT { $$ = xkb_atom_intern_literal(param->ctx, "default"); }
788                 ;
789
790 String          :       STRING  { $$ = xkb_atom_steal(param->ctx, $1); }
791                 ;
792
793 OptMapName      :       MapName { $$ = $1; }
794                 |               { $$ = NULL; }
795                 ;
796
797 MapName         :       STRING  { $$ = $1; }
798                 ;
799
800 %%
801
802 #undef scanner
803
804 XkbFile *
805 parse(struct xkb_context *ctx, void *scanner, const char *map)
806 {
807     struct parser_param param;
808     int ret;
809     XkbFile *first = NULL;
810
811     param.scanner = scanner;
812     param.ctx = ctx;
813
814     /*
815      * If we got a specific map, we look for it exclusively and return
816      * immediately upon finding it. Otherwise, we need to get the
817      * default map. If we find a map marked as default, we return it
818      * immediately. If there are no maps marked as default, we return
819      * the first map in the file.
820      */
821
822     while ((ret = yyparse(&param)) == 0 && param.more_maps) {
823         if (map) {
824             if (streq_not_null(map, param.rtrn->name))
825                 return param.rtrn;
826             else
827                 FreeXkbFile(param.rtrn);
828         }
829         else {
830             if (param.rtrn->flags & MAP_IS_DEFAULT) {
831                 FreeXkbFile(first);
832                 return param.rtrn;
833             }
834             else if (!first) {
835                 first = param.rtrn;
836             }
837             else {
838                 FreeXkbFile(param.rtrn);
839             }
840         }
841     }
842
843     if (ret != 0) {
844         FreeXkbFile(first);
845         return NULL;
846     }
847
848     return first;
849 }
850
851 #define scanner param->scanner