diff options
author | koekeishiya <aasvi93@hotmail.com> | 2017-08-07 20:23:44 +0200 |
---|---|---|
committer | koekeishiya <aasvi93@hotmail.com> | 2017-08-07 20:23:44 +0200 |
commit | d69056799a399058005b4950751397a31110de4a (patch) | |
tree | 1dee43a2f247094c58d1263cee8c8477b893e376 /src/parse.c | |
download | skhd-d69056799a399058005b4950751397a31110de4a.tar.gz skhd-d69056799a399058005b4950751397a31110de4a.zip |
v0.0.1
Diffstat (limited to 'src/parse.c')
-rw-r--r-- | src/parse.c | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/src/parse.c b/src/parse.c new file mode 100644 index 0000000..bac0215 --- /dev/null +++ b/src/parse.c @@ -0,0 +1,270 @@ +#include "parse.h" +#include "tokenize.h" +#include "locale.h" +#include "hotkey.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#define internal static + +internal char * +read_file(const char *file) +{ + unsigned length; + char *buffer = NULL; + FILE *handle = fopen(file, "r"); + + if(handle) + { + fseek(handle, 0, SEEK_END); + length = ftell(handle); + fseek(handle, 0, SEEK_SET); + buffer = malloc(length + 1); + fread(buffer, length, 1, handle); + buffer[length] = '\0'; + fclose(handle); + } + + return buffer; +} + +internal char * +copy_string_count(char *s, int length) +{ + char *result = malloc(length + 1); + memcpy(result, s, length); + result[length] = '\0'; + return result; +} + +internal uint32_t +keycode_from_hex(char *hex) +{ + uint32_t result; + sscanf(hex, "%x", &result); + return result; +} + +internal char * +parse_command(struct parser *parser) +{ + struct token command = parser_previous(parser); + char *result = copy_string_count(command.text, command.length); + printf("\tcmd: '%s'\n", result); + return result; +} + +internal uint32_t +parse_key_hex(struct parser *parser) +{ + struct token key = parser_previous(parser); + char *hex = copy_string_count(key.text, key.length); + uint32_t keycode = keycode_from_hex(hex); + free(hex); + printf("\tkey: '%.*s' (%d)\n", key.length, key.text, keycode); + return keycode; +} + +internal uint32_t +parse_key(struct parser *parser) +{ + uint32_t keycode; + struct token key = parser_previous(parser); + if(key.length == 1) { + keycode = keycode_from_char(*key.text); + } else { + keycode = keycode_from_literal(key.text, key.length); + } + printf("\tkey: '%.*s' (%d)\n", key.length, key.text, keycode); + return keycode; +} + +internal const char *modifier_flags_map[] = +{ + "alt", "lalt", "ralt", + "shift", "lshift", "rshift", + "cmd", "lcmd", "rcmd", + "ctrl", "lctrl", "rctrl", +}; +internal enum hotkey_flag modifier_flags_value[] = +{ + Hotkey_Flag_Alt, Hotkey_Flag_LAlt, Hotkey_Flag_RAlt, + Hotkey_Flag_Shift, Hotkey_Flag_LShift, Hotkey_Flag_RShift, + Hotkey_Flag_Cmd, Hotkey_Flag_LCmd, Hotkey_Flag_RCmd, + Hotkey_Flag_Control, Hotkey_Flag_LControl, Hotkey_Flag_RControl, +}; + +internal uint32_t +parse_modifier(struct parser *parser) +{ + uint32_t flags = 0; + struct token modifier = parser_previous(parser); + + for(int i = 0; i < array_count(modifier_flags_map); ++i) { + if(same_string(modifier.text, modifier.length, modifier_flags_map[i])) { + flags |= modifier_flags_value[i]; + printf("\tmod: '%s'\n", modifier_flags_map[i]); + break; + } + } + + if(parser_match(parser, Token_Plus)) { + if(parser_match(parser, Token_Modifier)) { + flags |= parse_modifier(parser); + } else { + fprintf(stderr, "(#%d:%d) expected token 'Token_Modifier', but got '%.*s'\n", + parser->current_token.line, parser->current_token.cursor, + parser->current_token.length, parser->current_token.text); + parser->error = true; + } + } + + return flags; +} + +internal struct hotkey * +parse_hotkey(struct parser *parser) +{ + struct hotkey *hotkey = malloc(sizeof(struct hotkey)); + int found_modifier; + + printf("(#%d) hotkey :: {\n", parser->current_token.line); + + if(parser_match(parser, Token_Modifier)) { + hotkey->flags = parse_modifier(parser); + if(parser->error) { + return NULL; + } + found_modifier = 1; + } else { + hotkey->flags = found_modifier = 0; + } + + if(found_modifier) { + if(!parser_match(parser, Token_Dash)) { + fprintf(stderr, "(#%d:%d) expected token '-', but got '%.*s'\n", + parser->current_token.line, parser->current_token.cursor, + parser->current_token.length, parser->current_token.text); + parser->error = true; + return NULL; + } + } + + if(parser_match(parser, Token_Key)) { + hotkey->key = parse_key(parser); + } else if(parser_match(parser, Token_Key_Hex)) { + hotkey->key = parse_key_hex(parser); + } else { + fprintf(stderr, "(#%d:%d) expected token 'Token_Key', but got '%.*s'\n", + parser->current_token.line, parser->current_token.cursor, + parser->current_token.length, parser->current_token.text); + parser->error = true; + return NULL; + } + + if(parser_match(parser, Token_Arrow)) { + hotkey->flags |= Hotkey_Flag_Passthrough; + } + + if(parser_match(parser, Token_Command)) { + hotkey->command = parse_command(parser); + } else { + fprintf(stderr, "(#%d:%d) expected token 'Token_Command', but got '%.*s'\n", + parser->current_token.line, parser->current_token.cursor, + parser->current_token.length, parser->current_token.text); + parser->error = true; + return NULL; + } + + printf("}\n"); + + hotkey->next = NULL; + return hotkey; +} + +struct hotkey * +parse_config(struct parser *parser) +{ + struct hotkey hotkeys; + struct hotkey *current_hotkey = &hotkeys; + + while(!parser_eof(parser)) { + if((parser_check(parser, Token_Modifier)) || + (parser_check(parser, Token_Key_Hex)) || + (parser_check(parser, Token_Key))) { + current_hotkey->next = parse_hotkey(parser); + current_hotkey = current_hotkey->next; + } else { + fprintf(stderr, "(#%d:%d) expected token 'Token_Modifier', 'Token_Key_Hex' or 'Token_Key', but got '%.*s'\n", + parser->current_token.line, parser->current_token.cursor, + parser->current_token.length, parser->current_token.text); + parser->error = true; + return NULL; + } + } + + return hotkeys.next; +} + +struct token +parser_peek(struct parser *parser) +{ + return parser->current_token; +} + +struct token +parser_previous(struct parser *parser) +{ + return parser->previous_token; +} + +bool parser_eof(struct parser *parser) +{ + struct token token = parser_peek(parser); + return token.type == Token_EndOfStream; +} + +struct token +parser_advance(struct parser *parser) +{ + if(!parser_eof(parser)) { + parser->previous_token = parser->current_token; + parser->current_token = get_token(&parser->tokenizer); + } + return parser_previous(parser); +} + +bool parser_check(struct parser *parser, enum token_type type) +{ + if(parser_eof(parser)) return 0; + struct token token = parser_peek(parser); + return token.type == type; +} + +bool parser_match(struct parser *parser, enum token_type type) +{ + if(parser_check(parser, type)) { + parser_advance(parser); + return true; + } + return false; +} + +bool parser_init(struct parser *parser, char *file) +{ + memset(parser, 0, sizeof(struct parser)); + char *buffer = read_file(file); + if(buffer) { + tokenizer_init(&parser->tokenizer, buffer); + parser_advance(parser); + return true; + } + return false; +} + +void parser_destroy(struct parser *parser) +{ + free(parser->tokenizer.buffer); +} |