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