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