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