From: Lukáš Jiřiště Date: Mon, 29 Jun 2026 19:19:15 +0000 (+0200) Subject: Implement the grammar parsing X-Git-Url: https://git.ljiriste.work/?a=commitdiff_plain;h=afbc23c81ef916ee07418c20052410e9e2a77245;p=KyciFTA Implement the grammar parsing The version of C is updated to 11 for anonymous structs/unions. The grammar is expanded by SLASH for paths and MINUS for easier tokenization. --- diff --git a/Makefile b/Makefile index acc2174..871fe26 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC := gcc -CFLAGS = -std=gnu99 -Wall -Wextra -Werror -Wpedantic +CFLAGS = -std=c11 -Wall -Wextra -Werror -Wpedantic ifneq ("$(wildcard .debug)","") CFLAGS += -g diff --git a/grammar b/grammar index b4e61bf..1b68f9f 100644 --- a/grammar +++ b/grammar @@ -24,10 +24,11 @@ value -> mantisa exponent mantisa -> INT mantisa -> INT DOT INT exponent -> EXP INT +exponent -> EXP MINUS INT classname -> name objectname -> name function_name -> name dynamic_library -> path -path -> WORD path +path -> WORD SLASH path path -> WORD name -> WORD diff --git a/inc/grammar.h b/inc/grammar.h new file mode 100644 index 0000000..4c5b74f --- /dev/null +++ b/inc/grammar.h @@ -0,0 +1,14 @@ +#ifndef GRAMMAR_H +# define GRAMMAR_H + + +// These strings should be regarded as constant +// They are generated by xxd hence this type is forced + +extern unsigned char grammar[]; +extern unsigned int grammar_len; + +extern unsigned char parsing_table[]; +extern unsigned int parsing_table_len; + +#endif //GRAMMAR_H diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..4ed5540 --- /dev/null +++ b/src/main.c @@ -0,0 +1,350 @@ +#include "grammar.h" +#include "libft.h" +#include +#include +#include + +static const char *g_help = + "You need to invoke this command this way:\n" + "\tcommand time step_num input_file\n"; + +typedef double (*t_prob_model)(double); + +typedef enum e_state +{ + WORKING, + FAILURE, +} t_state; + +typedef struct s_atom +{ + char *name; + t_state state; + double fault_prob; + t_prob_model model; +} t_atom; + +typedef enum e_gate_type +{ + AND, + OR, + NOOK, +} t_gate_type; + +typedef struct s_gate +{ + char *name; + t_state state; + t_gate_type type; + t_vec input_objects; +} t_gate; + +typedef union u_object +{ + t_gate gate; + t_atom atom; + struct + { + char *name; + t_state state; + }; +} t_object; + +typedef enum e_single_char_terminal +{ + DOT, + COMMA, + TIMES, + PLUS, + RIGHT_PARA, + LEFT_PARA, + SLASH, + MINUS, + + single_char_terminal_count +} t_single_char_terminal; + +typedef enum e_keyword +{ + EXP = single_char_terminal_count, + FROM, + ATOM, + N_OUT_OF_K, + SYSTEM, + INSTANTIATE, + + keyword_count +} t_keyword; + +typedef enum e_other_terminals +{ + WORD = keyword_count, + INT, + + terminal_count +} t_other_terminals; + + +const char *g_keyword_strings[keyword_count] = { + [MINUS] = "-", + [DOT] = ".", + [COMMA] = ",", + [TIMES] = "*", + [PLUS] = "+", + [RIGHT_PARA] = ")", + [LEFT_PARA] = "(", + [SLASH] = "/", + [EXP] = "e", + [FROM] = "FROM", + [ATOM] = "ATOM", + [N_OUT_OF_K] = "NOOK", + [SYSTEM] = "SYSTEM", + [INSTANTIATE] = "INST", +}; + +const char *g_token_strings[terminal_count] = { + [EXP] = "EXP", + [DOT] = "DOT", + [FROM] = "FROM", + [ATOM] = "ATOM", + [COMMA] = "COMMA", + [N_OUT_OF_K] = "N_OUT_OF_K", + [TIMES] = "TIMES", + [PLUS] = "PLUS", + [RIGHT_PARA] = "RIGHT_PARA", + [LEFT_PARA] = "LEFT_PARA", + [SYSTEM] = "SYSTEM", + [INSTANTIATE] = "INSTANTIATE", + [SLASH] = "SLASH", + [WORD] = "WORD", + [INT] = "INT", + [MINUS] = "MINUS", +}; + +int is_single_char_terminal(char c) +{ + for (t_single_char_terminal t = 0; t < single_char_terminal_count; ++t) + { + if (c == g_keyword_strings[t][0]) + { + return (1); + } + } + return (0); +} + +int is_in_context(char c) +{ + return (c && !ft_isspace(c) && !is_single_char_terminal(c) && !ft_isdigit(c)); +} + +const t_keyword *get_keyword(const char *line, size_t *i) +{ + static t_keyword keyword = 0; + size_t j; + + j = *i; + if (is_single_char_terminal(line[j])) + { + ++j; + } + else + { + while (line[j] && !ft_isspace(line[j]) && !is_single_char_terminal(line[j])) + { + ++j; + } + } + j -= *i; + for (keyword = 0; keyword < keyword_count; ++keyword) + { + if (ft_strncmp(line + *i, g_keyword_strings[keyword], j) == 0) + { + *i += j; + return (&keyword); + } + } + return (NULL); +} + +t_ft_stat add_keyword_token(t_keyword keyword, t_vec *tokens) +{ + t_token new_token; + + new_token.type = ft_strdup(g_token_strings[keyword]); + if (!new_token.type) + { + return (alloc_fail); + } + new_token.str = NULL; + return (ft_vec_append(tokens, &new_token)); +} + +t_ft_stat add_int_token(const char *line, size_t *i, t_vec *tokens) +{ + t_token new_token; + size_t j; + + j = 0; + while (ft_isdigit(line[*i + j])) + { + ++j; + } + new_token.type = ft_strdup(g_token_strings[INT]); + if (!new_token.type) + { + return (alloc_fail); + } + new_token.str = ft_strndup(line + *i, j); + if (!new_token.str) + { + return (alloc_fail); + } + *i += j; + return (ft_vec_append(tokens, &new_token)); +} + +t_ft_stat add_word_token(const char *line, size_t *i, t_vec *tokens) +{ + t_token new_token; + size_t j; + + j = *i; + while (line[j] && !ft_isspace(line[j]) && !is_single_char_terminal(line[j])) + { + ++j; + } + j -= *i; + new_token.type = ft_strdup(g_token_strings[WORD]); + new_token.str = ft_strndup(line + *i, j); + if (!new_token.type || !new_token.str) + { + free(new_token.type); + free(new_token.str); + return (alloc_fail); + } + *i += j; + return (ft_vec_append(tokens, &new_token)); +} + +t_ft_stat tokenize_line(const char *line, t_vec *tokens) +{ + size_t i; + const t_keyword *keyword; + + i = 0; + while (line[i]) + { + if (ft_isspace(line[i])) + { + ++i; + continue ; + } + keyword = get_keyword(line, &i); + if (keyword) + { + if (add_keyword_token(*keyword, tokens)) + { + return (alloc_fail); + } + } + else if (ft_isdigit(line[i])) + { + if (add_int_token(line, &i, tokens)) + { + return (alloc_fail); + } + } + else if (add_word_token(line, &i, tokens)) + { + return (alloc_fail); + } + } + return (success); +} + +t_ft_stat tokenize(const char *file, t_vec *tokens) +{ + int fd; + t_ft_stat res; + char *line; + + fd = open(file, O_RDONLY); + if (fd < 0) + { + return (file_error); + } + line = get_next_line(fd); + while (line) + { + res = tokenize_line(line, tokens); + if (res) + { + free(line); + get_next_line(-1); + close(fd); + return (res); + } + free(line); + line = get_next_line(fd); + } + close(fd); + return (success); +} + +void free_token(void *v_token) +{ + t_token *token; + + token = v_token; + free(token->str); + free(token->type); + return ; +} + +t_parse_tree_node *parse(const char *file) +{ + t_parsing_table table; + t_vec tokens; + t_parse_tree_node *parse_tree; + + ft_parsing_table_init(&table); + if (ft_parsing_table_load_str(&table, (char *) parsing_table, (char *) grammar)) + { + return (NULL); + } + if (ft_vec_init(&tokens, sizeof(t_token))) + { + ft_parsing_table_free(&table); + return (NULL); + } + if (tokenize(file, &tokens)) + { + ft_parsing_table_free(&table); + ft_vec_free(&tokens, free_token); + return (NULL); + } + parse_tree = ft_parse(&tokens, &table); + ft_parsing_table_free(&table); + ft_vec_free(&tokens, free_token); + return (parse_tree); +} + +int main(int argc, char **argv) +{ + t_parse_tree_node *parse_tree; + if (argc != 4) + { + ft_printf(g_help); + return (1); + } + parse_tree = parse(argv[3]); + if (!parse_tree) + { + ft_printf("An error has occured.\n"); + return (1); + } + ft_parse_tree_print(parse_tree); + ft_parse_tree_free(parse_tree); + return (0); +}