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