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