| /************************************************************ |
| Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. |
| |
| Permission to use, copy, modify, and distribute this |
| software and its documentation for any purpose and without |
| fee is hereby granted, provided that the above copyright |
| notice appear in all copies and that both that copyright |
| notice and this permission notice appear in supporting |
| documentation, and that the name of Silicon Graphics not be |
| used in advertising or publicity pertaining to distribution |
| of the software without specific prior written permission. |
| Silicon Graphics makes no representation about the suitability |
| of this software for any purpose. It is provided "as is" |
| without any express or implied warranty. |
| |
| SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS |
| SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY |
| AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON |
| GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL |
| DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, |
| DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE |
| OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH |
| THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| |
| ********************************************************/ |
| |
| /* |
| * The parser should work with reasonably recent versions of either |
| * bison or byacc. So if you make changes, try to make sure it works |
| * in both! |
| */ |
| |
| %{ |
| #include "config.h" |
| |
| #include "xkbcomp/xkbcomp-priv.h" |
| #include "xkbcomp/ast-build.h" |
| #include "xkbcomp/parser-priv.h" |
| #include "scanner-utils.h" |
| |
| struct parser_param { |
| struct xkb_context *ctx; |
| struct scanner *scanner; |
| XkbFile *rtrn; |
| bool more_maps; |
| }; |
| |
| #define parser_err(param, fmt, ...) \ |
| scanner_err((param)->scanner, fmt, ##__VA_ARGS__) |
| |
| #define parser_warn(param, fmt, ...) \ |
| scanner_warn((param)->scanner, fmt, ##__VA_ARGS__) |
| |
| static void |
| _xkbcommon_error(struct parser_param *param, const char *msg) |
| { |
| parser_err(param, "%s", msg); |
| } |
| |
| static bool |
| resolve_keysym(const char *name, xkb_keysym_t *sym_rtrn) |
| { |
| xkb_keysym_t sym; |
| |
| if (!name || istreq(name, "any") || istreq(name, "nosymbol")) { |
| *sym_rtrn = XKB_KEY_NoSymbol; |
| return true; |
| } |
| |
| if (istreq(name, "none") || istreq(name, "voidsymbol")) { |
| *sym_rtrn = XKB_KEY_VoidSymbol; |
| return true; |
| } |
| |
| sym = xkb_keysym_from_name(name, XKB_KEYSYM_NO_FLAGS); |
| if (sym != XKB_KEY_NoSymbol) { |
| *sym_rtrn = sym; |
| return true; |
| } |
| |
| return false; |
| } |
| |
| #define param_scanner param->scanner |
| %} |
| |
| %pure-parser |
| %lex-param { struct scanner *param_scanner } |
| %parse-param { struct parser_param *param } |
| |
| %token |
| END_OF_FILE 0 |
| ERROR_TOK 255 |
| XKB_KEYMAP 1 |
| XKB_KEYCODES 2 |
| XKB_TYPES 3 |
| XKB_SYMBOLS 4 |
| XKB_COMPATMAP 5 |
| XKB_GEOMETRY 6 |
| XKB_SEMANTICS 7 |
| XKB_LAYOUT 8 |
| INCLUDE 10 |
| OVERRIDE 11 |
| AUGMENT 12 |
| REPLACE 13 |
| ALTERNATE 14 |
| VIRTUAL_MODS 20 |
| TYPE 21 |
| INTERPRET 22 |
| ACTION_TOK 23 |
| KEY 24 |
| ALIAS 25 |
| GROUP 26 |
| MODIFIER_MAP 27 |
| INDICATOR 28 |
| SHAPE 29 |
| KEYS 30 |
| ROW 31 |
| SECTION 32 |
| OVERLAY 33 |
| TEXT 34 |
| OUTLINE 35 |
| SOLID 36 |
| LOGO 37 |
| VIRTUAL 38 |
| EQUALS 40 |
| PLUS 41 |
| MINUS 42 |
| DIVIDE 43 |
| TIMES 44 |
| OBRACE 45 |
| CBRACE 46 |
| OPAREN 47 |
| CPAREN 48 |
| OBRACKET 49 |
| CBRACKET 50 |
| DOT 51 |
| COMMA 52 |
| SEMI 53 |
| EXCLAM 54 |
| INVERT 55 |
| STRING 60 |
| INTEGER 61 |
| FLOAT 62 |
| IDENT 63 |
| KEYNAME 64 |
| PARTIAL 70 |
| DEFAULT 71 |
| HIDDEN 72 |
| ALPHANUMERIC_KEYS 73 |
| MODIFIER_KEYS 74 |
| KEYPAD_KEYS 75 |
| FUNCTION_KEYS 76 |
| ALTERNATE_GROUP 77 |
| |
| %right EQUALS |
| %left PLUS MINUS |
| %left TIMES DIVIDE |
| %left EXCLAM INVERT |
| %left OPAREN |
| |
| %start XkbFile |
| |
| %union { |
| int64_t num; |
| enum xkb_file_type file_type; |
| char *str; |
| xkb_atom_t atom; |
| enum merge_mode merge; |
| enum xkb_map_flags mapFlags; |
| xkb_keysym_t keysym; |
| ParseCommon *any; |
| struct { ParseCommon *head; ParseCommon *last; } anyList; |
| ExprDef *expr; |
| struct { ExprDef *head; ExprDef *last; } exprList; |
| VarDef *var; |
| struct { VarDef *head; VarDef *last; } varList; |
| VModDef *vmod; |
| struct { VModDef *head; VModDef *last; } vmodList; |
| InterpDef *interp; |
| KeyTypeDef *keyType; |
| SymbolsDef *syms; |
| ModMapDef *modMask; |
| GroupCompatDef *groupCompat; |
| LedMapDef *ledMap; |
| LedNameDef *ledName; |
| KeycodeDef *keyCode; |
| KeyAliasDef *keyAlias; |
| void *geom; |
| XkbFile *file; |
| struct { XkbFile *head; XkbFile *last; } fileList; |
| } |
| |
| %type <num> INTEGER FLOAT |
| %type <str> IDENT STRING |
| %type <atom> KEYNAME |
| %type <num> KeyCode Number Integer Float SignedNumber DoodadType |
| %type <merge> MergeMode OptMergeMode |
| %type <file_type> XkbCompositeType FileType |
| %type <mapFlags> Flag Flags OptFlags |
| %type <str> MapName OptMapName |
| %type <atom> FieldSpec Ident Element String |
| %type <keysym> KeySym |
| %type <any> Decl |
| %type <anyList> DeclList |
| %type <expr> Expr Term Lhs Terminal ArrayInit KeySyms |
| %type <expr> OptKeySymList KeySymList Action Coord CoordList |
| %type <exprList> OptExprList ExprList ActionList |
| %type <var> VarDecl SymbolsVarDecl |
| %type <varList> VarDeclList SymbolsBody |
| %type <vmod> VModDef |
| %type <vmodList> VModDefList VModDecl |
| %type <interp> InterpretDecl InterpretMatch |
| %type <keyType> KeyTypeDecl |
| %type <syms> SymbolsDecl |
| %type <modMask> ModMapDecl |
| %type <groupCompat> GroupCompatDecl |
| %type <ledMap> LedMapDecl |
| %type <ledName> LedNameDecl |
| %type <keyCode> KeyNameDecl |
| %type <keyAlias> KeyAliasDecl |
| %type <geom> ShapeDecl SectionDecl SectionBody SectionBodyItem RowBody RowBodyItem |
| %type <geom> Keys Key OverlayDecl OverlayKeyList OverlayKey OutlineList OutlineInList |
| %type <geom> DoodadDecl |
| %type <file> XkbFile XkbMapConfig |
| %type <fileList> XkbMapConfigList |
| %type <file> XkbCompositeMap |
| |
| %destructor { FreeStmt((ParseCommon *) $$); } |
| <any> <expr> <var> <vmod> <interp> <keyType> <syms> <modMask> <groupCompat> |
| <ledMap> <ledName> <keyCode> <keyAlias> |
| %destructor { FreeStmt((ParseCommon *) $$.head); } |
| <anyList> <exprList> <varList> <vmodList> |
| /* The destructor also runs on the start symbol when the parser *succeeds*. |
| * The `if` here catches this case. */ |
| %destructor { if (!param->rtrn) FreeXkbFile($$); } <file> |
| %destructor { FreeXkbFile($$.head); } <fileList> |
| %destructor { free($$); } <str> |
| |
| %% |
| |
| /* |
| * An actual file may contain more than one map. However, if we do things |
| * in the normal yacc way, i.e. aggregate all of the maps into a list and |
| * let the caller find the map it wants, we end up scanning and parsing a |
| * lot of unneeded maps (in the end we always just need one). |
| * Instead of doing that, we make yyparse return one map at a time, and |
| * then call it repeatedly until we find the map we need. Once we find it, |
| * we don't need to parse everything that follows in the file. |
| * This does mean that if we e.g. always use the first map, the file may |
| * contain complete garbage after that. But it's worth it. |
| */ |
| |
| XkbFile : XkbCompositeMap |
| { $$ = param->rtrn = $1; param->more_maps = !!param->rtrn; } |
| | XkbMapConfig |
| { $$ = param->rtrn = $1; param->more_maps = !!param->rtrn; YYACCEPT; } |
| | END_OF_FILE |
| { $$ = param->rtrn = NULL; param->more_maps = false; } |
| ; |
| |
| XkbCompositeMap : OptFlags XkbCompositeType OptMapName OBRACE |
| XkbMapConfigList |
| CBRACE SEMI |
| { $$ = XkbFileCreate($2, $3, (ParseCommon *) $5.head, $1); } |
| ; |
| |
| XkbCompositeType: XKB_KEYMAP { $$ = FILE_TYPE_KEYMAP; } |
| | XKB_SEMANTICS { $$ = FILE_TYPE_KEYMAP; } |
| | XKB_LAYOUT { $$ = FILE_TYPE_KEYMAP; } |
| ; |
| |
| XkbMapConfigList : XkbMapConfigList XkbMapConfig |
| { $$.head = $1.head; $$.last->common.next = &$2->common; $$.last = $2; } |
| | XkbMapConfig |
| { $$.head = $$.last = $1; } |
| ; |
| |
| XkbMapConfig : OptFlags FileType OptMapName OBRACE |
| DeclList |
| CBRACE SEMI |
| { |
| $$ = XkbFileCreate($2, $3, $5.head, $1); |
| } |
| ; |
| |
| FileType : XKB_KEYCODES { $$ = FILE_TYPE_KEYCODES; } |
| | XKB_TYPES { $$ = FILE_TYPE_TYPES; } |
| | XKB_COMPATMAP { $$ = FILE_TYPE_COMPAT; } |
| | XKB_SYMBOLS { $$ = FILE_TYPE_SYMBOLS; } |
| | XKB_GEOMETRY { $$ = FILE_TYPE_GEOMETRY; } |
| ; |
| |
| OptFlags : Flags { $$ = $1; } |
| | { $$ = 0; } |
| ; |
| |
| Flags : Flags Flag { $$ = ($1 | $2); } |
| | Flag { $$ = $1; } |
| ; |
| |
| Flag : PARTIAL { $$ = MAP_IS_PARTIAL; } |
| | DEFAULT { $$ = MAP_IS_DEFAULT; } |
| | HIDDEN { $$ = MAP_IS_HIDDEN; } |
| | ALPHANUMERIC_KEYS { $$ = MAP_HAS_ALPHANUMERIC; } |
| | MODIFIER_KEYS { $$ = MAP_HAS_MODIFIER; } |
| | KEYPAD_KEYS { $$ = MAP_HAS_KEYPAD; } |
| | FUNCTION_KEYS { $$ = MAP_HAS_FN; } |
| | ALTERNATE_GROUP { $$ = MAP_IS_ALTGR; } |
| ; |
| |
| DeclList : DeclList Decl |
| { |
| if ($2) { |
| if ($1.head) { |
| $$.head = $1.head; $1.last->next = $2; $$.last = $2; |
| } else { |
| $$.head = $$.last = $2; |
| } |
| } |
| } |
| /* |
| * VModDecl is "inlined" directly into DeclList, i.e. |
| * each VModDef in the VModDecl is a separate Decl in |
| * the File. |
| */ |
| | DeclList OptMergeMode VModDecl |
| { |
| for (VModDef *vmod = $3.head; vmod; vmod = (VModDef *) vmod->common.next) |
| vmod->merge = $2; |
| if ($1.head) { |
| $$.head = $1.head; $1.last->next = &$3.head->common; $$.last = &$3.last->common; |
| } else { |
| $$.head = &$3.head->common; $$.last = &$3.last->common; |
| } |
| } |
| | { $$.head = $$.last = NULL; } |
| ; |
| |
| Decl : OptMergeMode VarDecl |
| { |
| $2->merge = $1; |
| $$ = (ParseCommon *) $2; |
| } |
| /* OptMergeMode VModDecl - see above. */ |
| | OptMergeMode InterpretDecl |
| { |
| $2->merge = $1; |
| $$ = (ParseCommon *) $2; |
| } |
| | OptMergeMode KeyNameDecl |
| { |
| $2->merge = $1; |
| $$ = (ParseCommon *) $2; |
| } |
| | OptMergeMode KeyAliasDecl |
| { |
| $2->merge = $1; |
| $$ = (ParseCommon *) $2; |
| } |
| | OptMergeMode KeyTypeDecl |
| { |
| $2->merge = $1; |
| $$ = (ParseCommon *) $2; |
| } |
| | OptMergeMode SymbolsDecl |
| { |
| $2->merge = $1; |
| $$ = (ParseCommon *) $2; |
| } |
| | OptMergeMode ModMapDecl |
| { |
| $2->merge = $1; |
| $$ = (ParseCommon *) $2; |
| } |
| | OptMergeMode GroupCompatDecl |
| { |
| $2->merge = $1; |
| $$ = (ParseCommon *) $2; |
| } |
| | OptMergeMode LedMapDecl |
| { |
| $2->merge = $1; |
| $$ = (ParseCommon *) $2; |
| } |
| | OptMergeMode LedNameDecl |
| { |
| $2->merge = $1; |
| $$ = (ParseCommon *) $2; |
| } |
| | OptMergeMode ShapeDecl { $$ = NULL; } |
| | OptMergeMode SectionDecl { $$ = NULL; } |
| | OptMergeMode DoodadDecl { $$ = NULL; } |
| | MergeMode STRING |
| { |
| $$ = (ParseCommon *) IncludeCreate(param->ctx, $2, $1); |
| free($2); |
| } |
| ; |
| |
| VarDecl : Lhs EQUALS Expr SEMI |
| { $$ = VarCreate($1, $3); } |
| | Ident SEMI |
| { $$ = BoolVarCreate($1, true); } |
| | EXCLAM Ident SEMI |
| { $$ = BoolVarCreate($2, false); } |
| ; |
| |
| KeyNameDecl : KEYNAME EQUALS KeyCode SEMI |
| { $$ = KeycodeCreate($1, $3); } |
| ; |
| |
| KeyAliasDecl : ALIAS KEYNAME EQUALS KEYNAME SEMI |
| { $$ = KeyAliasCreate($2, $4); } |
| ; |
| |
| VModDecl : VIRTUAL_MODS VModDefList SEMI |
| { $$ = $2; } |
| ; |
| |
| VModDefList : VModDefList COMMA VModDef |
| { $$.head = $1.head; $$.last->common.next = &$3->common; $$.last = $3; } |
| | VModDef |
| { $$.head = $$.last = $1; } |
| ; |
| |
| VModDef : Ident |
| { $$ = VModCreate($1, NULL); } |
| | Ident EQUALS Expr |
| { $$ = VModCreate($1, $3); } |
| ; |
| |
| InterpretDecl : INTERPRET InterpretMatch OBRACE |
| VarDeclList |
| CBRACE SEMI |
| { $2->def = $4.head; $$ = $2; } |
| ; |
| |
| InterpretMatch : KeySym PLUS Expr |
| { $$ = InterpCreate($1, $3); } |
| | KeySym |
| { $$ = InterpCreate($1, NULL); } |
| ; |
| |
| VarDeclList : VarDeclList VarDecl |
| { $$.head = $1.head; $$.last->common.next = &$2->common; $$.last = $2; } |
| | VarDecl |
| { $$.head = $$.last = $1; } |
| ; |
| |
| KeyTypeDecl : TYPE String OBRACE |
| VarDeclList |
| CBRACE SEMI |
| { $$ = KeyTypeCreate($2, $4.head); } |
| ; |
| |
| SymbolsDecl : KEY KEYNAME OBRACE |
| SymbolsBody |
| CBRACE SEMI |
| { $$ = SymbolsCreate($2, $4.head); } |
| ; |
| |
| SymbolsBody : SymbolsBody COMMA SymbolsVarDecl |
| { $$.head = $1.head; $$.last->common.next = &$3->common; $$.last = $3; } |
| | SymbolsVarDecl |
| { $$.head = $$.last = $1; } |
| | { $$.head = $$.last = NULL; } |
| ; |
| |
| SymbolsVarDecl : Lhs EQUALS Expr { $$ = VarCreate($1, $3); } |
| | Lhs EQUALS ArrayInit { $$ = VarCreate($1, $3); } |
| | Ident { $$ = BoolVarCreate($1, true); } |
| | EXCLAM Ident { $$ = BoolVarCreate($2, false); } |
| | ArrayInit { $$ = VarCreate(NULL, $1); } |
| ; |
| |
| ArrayInit : OBRACKET OptKeySymList CBRACKET |
| { $$ = $2; } |
| | OBRACKET ActionList CBRACKET |
| { $$ = ExprCreateActionList($2.head); } |
| ; |
| |
| GroupCompatDecl : GROUP Integer EQUALS Expr SEMI |
| { $$ = GroupCompatCreate($2, $4); } |
| ; |
| |
| ModMapDecl : MODIFIER_MAP Ident OBRACE ExprList CBRACE SEMI |
| { $$ = ModMapCreate($2, $4.head); } |
| ; |
| |
| LedMapDecl: INDICATOR String OBRACE VarDeclList CBRACE SEMI |
| { $$ = LedMapCreate($2, $4.head); } |
| ; |
| |
| LedNameDecl: INDICATOR Integer EQUALS Expr SEMI |
| { $$ = LedNameCreate($2, $4, false); } |
| | VIRTUAL INDICATOR Integer EQUALS Expr SEMI |
| { $$ = LedNameCreate($3, $5, true); } |
| ; |
| |
| ShapeDecl : SHAPE String OBRACE OutlineList CBRACE SEMI |
| { $$ = NULL; } |
| | SHAPE String OBRACE CoordList CBRACE SEMI |
| { (void) $4; $$ = NULL; } |
| ; |
| |
| SectionDecl : SECTION String OBRACE SectionBody CBRACE SEMI |
| { $$ = NULL; } |
| ; |
| |
| SectionBody : SectionBody SectionBodyItem { $$ = NULL;} |
| | SectionBodyItem { $$ = NULL; } |
| ; |
| |
| SectionBodyItem : ROW OBRACE RowBody CBRACE SEMI |
| { $$ = NULL; } |
| | VarDecl |
| { FreeStmt((ParseCommon *) $1); $$ = NULL; } |
| | DoodadDecl |
| { $$ = NULL; } |
| | LedMapDecl |
| { FreeStmt((ParseCommon *) $1); $$ = NULL; } |
| | OverlayDecl |
| { $$ = NULL; } |
| ; |
| |
| RowBody : RowBody RowBodyItem { $$ = NULL;} |
| | RowBodyItem { $$ = NULL; } |
| ; |
| |
| RowBodyItem : KEYS OBRACE Keys CBRACE SEMI { $$ = NULL; } |
| | VarDecl |
| { FreeStmt((ParseCommon *) $1); $$ = NULL; } |
| ; |
| |
| Keys : Keys COMMA Key { $$ = NULL; } |
| | Key { $$ = NULL; } |
| ; |
| |
| Key : KEYNAME |
| { $$ = NULL; } |
| | OBRACE ExprList CBRACE |
| { FreeStmt((ParseCommon *) $2.head); $$ = NULL; } |
| ; |
| |
| OverlayDecl : OVERLAY String OBRACE OverlayKeyList CBRACE SEMI |
| { $$ = NULL; } |
| ; |
| |
| OverlayKeyList : OverlayKeyList COMMA OverlayKey { $$ = NULL; } |
| | OverlayKey { $$ = NULL; } |
| ; |
| |
| OverlayKey : KEYNAME EQUALS KEYNAME { $$ = NULL; } |
| ; |
| |
| OutlineList : OutlineList COMMA OutlineInList |
| { $$ = NULL;} |
| | OutlineInList |
| { $$ = NULL; } |
| ; |
| |
| OutlineInList : OBRACE CoordList CBRACE |
| { (void) $2; $$ = NULL; } |
| | Ident EQUALS OBRACE CoordList CBRACE |
| { (void) $4; $$ = NULL; } |
| | Ident EQUALS Expr |
| { FreeStmt((ParseCommon *) $3); $$ = NULL; } |
| ; |
| |
| CoordList : CoordList COMMA Coord |
| { (void) $1; (void) $3; $$ = NULL; } |
| | Coord |
| { (void) $1; $$ = NULL; } |
| ; |
| |
| Coord : OBRACKET SignedNumber COMMA SignedNumber CBRACKET |
| { $$ = NULL; } |
| ; |
| |
| DoodadDecl : DoodadType String OBRACE VarDeclList CBRACE SEMI |
| { FreeStmt((ParseCommon *) $4.head); $$ = NULL; } |
| ; |
| |
| DoodadType : TEXT { $$ = 0; } |
| | OUTLINE { $$ = 0; } |
| | SOLID { $$ = 0; } |
| | LOGO { $$ = 0; } |
| ; |
| |
| FieldSpec : Ident { $$ = $1; } |
| | Element { $$ = $1; } |
| ; |
| |
| Element : ACTION_TOK |
| { $$ = xkb_atom_intern_literal(param->ctx, "action"); } |
| | INTERPRET |
| { $$ = xkb_atom_intern_literal(param->ctx, "interpret"); } |
| | TYPE |
| { $$ = xkb_atom_intern_literal(param->ctx, "type"); } |
| | KEY |
| { $$ = xkb_atom_intern_literal(param->ctx, "key"); } |
| | GROUP |
| { $$ = xkb_atom_intern_literal(param->ctx, "group"); } |
| | MODIFIER_MAP |
| {$$ = xkb_atom_intern_literal(param->ctx, "modifier_map");} |
| | INDICATOR |
| { $$ = xkb_atom_intern_literal(param->ctx, "indicator"); } |
| | SHAPE |
| { $$ = xkb_atom_intern_literal(param->ctx, "shape"); } |
| | ROW |
| { $$ = xkb_atom_intern_literal(param->ctx, "row"); } |
| | SECTION |
| { $$ = xkb_atom_intern_literal(param->ctx, "section"); } |
| | TEXT |
| { $$ = xkb_atom_intern_literal(param->ctx, "text"); } |
| ; |
| |
| OptMergeMode : MergeMode { $$ = $1; } |
| | { $$ = MERGE_DEFAULT; } |
| ; |
| |
| MergeMode : INCLUDE { $$ = MERGE_DEFAULT; } |
| | AUGMENT { $$ = MERGE_AUGMENT; } |
| | OVERRIDE { $$ = MERGE_OVERRIDE; } |
| | REPLACE { $$ = MERGE_REPLACE; } |
| | ALTERNATE |
| { |
| /* |
| * This used to be MERGE_ALT_FORM. This functionality was |
| * unused and has been removed. |
| */ |
| $$ = MERGE_DEFAULT; |
| } |
| ; |
| |
| OptExprList : ExprList { $$ = $1; } |
| | { $$.head = $$.last = NULL; } |
| ; |
| |
| ExprList : ExprList COMMA Expr |
| { $$.head = $1.head; $$.last->common.next = &$3->common; $$.last = $3; } |
| | Expr |
| { $$.head = $$.last = $1; } |
| ; |
| |
| Expr : Expr DIVIDE Expr |
| { $$ = ExprCreateBinary(EXPR_DIVIDE, $1, $3); } |
| | Expr PLUS Expr |
| { $$ = ExprCreateBinary(EXPR_ADD, $1, $3); } |
| | Expr MINUS Expr |
| { $$ = ExprCreateBinary(EXPR_SUBTRACT, $1, $3); } |
| | Expr TIMES Expr |
| { $$ = ExprCreateBinary(EXPR_MULTIPLY, $1, $3); } |
| | Lhs EQUALS Expr |
| { $$ = ExprCreateBinary(EXPR_ASSIGN, $1, $3); } |
| | Term |
| { $$ = $1; } |
| ; |
| |
| Term : MINUS Term |
| { $$ = ExprCreateUnary(EXPR_NEGATE, $2->expr.value_type, $2); } |
| | PLUS Term |
| { $$ = ExprCreateUnary(EXPR_UNARY_PLUS, $2->expr.value_type, $2); } |
| | EXCLAM Term |
| { $$ = ExprCreateUnary(EXPR_NOT, EXPR_TYPE_BOOLEAN, $2); } |
| | INVERT Term |
| { $$ = ExprCreateUnary(EXPR_INVERT, $2->expr.value_type, $2); } |
| | Lhs |
| { $$ = $1; } |
| | FieldSpec OPAREN OptExprList CPAREN %prec OPAREN |
| { $$ = ExprCreateAction($1, $3.head); } |
| | Terminal |
| { $$ = $1; } |
| | OPAREN Expr CPAREN |
| { $$ = $2; } |
| ; |
| |
| ActionList : ActionList COMMA Action |
| { $$.head = $1.head; $$.last->common.next = &$3->common; $$.last = $3; } |
| | Action |
| { $$.head = $$.last = $1; } |
| ; |
| |
| Action : FieldSpec OPAREN OptExprList CPAREN |
| { $$ = ExprCreateAction($1, $3.head); } |
| ; |
| |
| Lhs : FieldSpec |
| { $$ = ExprCreateIdent($1); } |
| | FieldSpec DOT FieldSpec |
| { $$ = ExprCreateFieldRef($1, $3); } |
| | FieldSpec OBRACKET Expr CBRACKET |
| { $$ = ExprCreateArrayRef(XKB_ATOM_NONE, $1, $3); } |
| | FieldSpec DOT FieldSpec OBRACKET Expr CBRACKET |
| { $$ = ExprCreateArrayRef($1, $3, $5); } |
| ; |
| |
| Terminal : String |
| { $$ = ExprCreateString($1); } |
| | Integer |
| { $$ = ExprCreateInteger($1); } |
| | Float |
| { $$ = ExprCreateFloat(/* Discard $1 */); } |
| | KEYNAME |
| { $$ = ExprCreateKeyName($1); } |
| ; |
| |
| OptKeySymList : KeySymList { $$ = $1; } |
| | { $$ = NULL; } |
| ; |
| |
| KeySymList : KeySymList COMMA KeySym |
| { $$ = ExprAppendKeysymList($1, $3); } |
| | KeySymList COMMA KeySyms |
| { $$ = ExprAppendMultiKeysymList($1, $3); } |
| | KeySym |
| { $$ = ExprCreateKeysymList($1); } |
| | KeySyms |
| { $$ = ExprCreateMultiKeysymList($1); } |
| ; |
| |
| KeySyms : OBRACE KeySymList CBRACE |
| { $$ = $2; } |
| ; |
| |
| KeySym : IDENT |
| { |
| if (!resolve_keysym($1, &$$)) { |
| parser_warn(param, "unrecognized keysym \"%s\"", $1); |
| $$ = XKB_KEY_NoSymbol; |
| } |
| free($1); |
| } |
| | SECTION { $$ = XKB_KEY_section; } |
| | Integer |
| { |
| if ($1 < 0) { |
| parser_warn(param, "unrecognized keysym \"%"PRId64"\"", $1); |
| $$ = XKB_KEY_NoSymbol; |
| } |
| else if ($1 < 10) { /* XKB_KEY_0 .. XKB_KEY_9 */ |
| $$ = XKB_KEY_0 + (xkb_keysym_t) $1; |
| } |
| else { |
| char buf[32]; |
| snprintf(buf, sizeof(buf), "0x%"PRIx64, $1); |
| if (!resolve_keysym(buf, &$$)) { |
| parser_warn(param, "unrecognized keysym \"%s\"", buf); |
| $$ = XKB_KEY_NoSymbol; |
| } |
| } |
| } |
| ; |
| |
| SignedNumber : MINUS Number { $$ = -$2; } |
| | Number { $$ = $1; } |
| ; |
| |
| Number : FLOAT { $$ = $1; } |
| | INTEGER { $$ = $1; } |
| ; |
| |
| Float : FLOAT { $$ = 0; } |
| ; |
| |
| Integer : INTEGER { $$ = $1; } |
| ; |
| |
| KeyCode : INTEGER { $$ = $1; } |
| ; |
| |
| Ident : IDENT { $$ = xkb_atom_intern(param->ctx, $1, strlen($1)); free($1); } |
| | DEFAULT { $$ = xkb_atom_intern_literal(param->ctx, "default"); } |
| ; |
| |
| String : STRING { $$ = xkb_atom_intern(param->ctx, $1, strlen($1)); free($1); } |
| ; |
| |
| OptMapName : MapName { $$ = $1; } |
| | { $$ = NULL; } |
| ; |
| |
| MapName : STRING { $$ = $1; } |
| ; |
| |
| %% |
| |
| XkbFile * |
| parse(struct xkb_context *ctx, struct scanner *scanner, const char *map) |
| { |
| int ret; |
| XkbFile *first = NULL; |
| struct parser_param param = { |
| .scanner = scanner, |
| .ctx = ctx, |
| .rtrn = NULL, |
| .more_maps = false, |
| }; |
| |
| /* |
| * If we got a specific map, we look for it exclusively and return |
| * immediately upon finding it. Otherwise, we need to get the |
| * default map. If we find a map marked as default, we return it |
| * immediately. If there are no maps marked as default, we return |
| * the first map in the file. |
| */ |
| |
| while ((ret = yyparse(¶m)) == 0 && param.more_maps) { |
| if (map) { |
| if (streq_not_null(map, param.rtrn->name)) |
| return param.rtrn; |
| else |
| FreeXkbFile(param.rtrn); |
| } |
| else { |
| if (param.rtrn->flags & MAP_IS_DEFAULT) { |
| FreeXkbFile(first); |
| return param.rtrn; |
| } |
| else if (!first) { |
| first = param.rtrn; |
| } |
| else { |
| FreeXkbFile(param.rtrn); |
| } |
| } |
| param.rtrn = NULL; |
| } |
| |
| if (ret != 0) { |
| FreeXkbFile(first); |
| return NULL; |
| } |
| |
| if (first) |
| log_vrb(ctx, 5, |
| "No map in include statement, but \"%s\" contains several; " |
| "Using first defined map, \"%s\"\n", |
| scanner->file_name, first->name); |
| |
| return first; |
| } |