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