diff --git a/src/lexer/lexer_utils.h b/src/lexer/lexer_utils.h index 8fb5219..af64455 100644 --- a/src/lexer/lexer_utils.h +++ b/src/lexer/lexer_utils.h @@ -68,7 +68,11 @@ enum token_type TOKEN_FI, TOKEN_ELIF, TOKEN_AND, - TOKEN_OR + TOKEN_OR, + TOKEN_FOR, + TOKEN_WHILE, + TOKEN_UNTIL, + TOKEN_CASE }; struct token diff --git a/src/parser/grammar.c b/src/parser/grammar.c index 95f1bd2..d0258bf 100644 --- a/src/parser/grammar.c +++ b/src/parser/grammar.c @@ -4,7 +4,6 @@ #include #include -#include "../lexer/lexer.h" #include "grammar_basic.h" // === Static variables @@ -57,6 +56,23 @@ static bool add_first(enum rule rule, enum token_type token) return true; } +/* @brief Add a list of tokens to a rule's firsts (in firsts_map) + * + * @arg rule the rule to which add a first + * @arg tokens_list the list of tokens to add to the rule's firsts + * @return true on success, false on error + */ +static bool add_firsts(enum rule rule, struct firsts_list *tokens_list) +{ + for (size_t i = 0; i < tokens_list->list_length; i++) + { + bool res = add_first(rule, tokens_list->tokens[i]); + if (!res) + return false; + } + return true; +} + /* @brief initializes the firsts_map static variable (does not populate it) * @return true on success, false on error */ @@ -73,21 +89,6 @@ static bool init_firsts_map(void) return true; } -/* @brief: add all the redirection token_types to the first of [rule]. - * this also contains IONUMBER - */ -static void add_first_redir(enum rule rule) -{ - add_first(rule, TOKEN_IONUMBER); - add_first(rule, TOKEN_REDIR_LEFT); - add_first(rule, TOKEN_REDIR_RIGHT); - add_first(rule, TOKEN_REDIR_LEFT_RIGHT); - add_first(rule, TOKEN_REDIR_DOUBLE_RIGHT); - add_first(rule, TOKEN_REDIR_LEFT_AMP); - add_first(rule, TOKEN_REDIR_RIGHT_AMP); - add_first(rule, TOKEN_REDIR_RIGHT_PIPE); -} - // === Functions bool grammar_init(void) @@ -98,46 +99,85 @@ bool grammar_init(void) return false; // Populate the firsts map - add_first(RULE_INPUT, TOKEN_WORD); - add_first(RULE_INPUT, TOKEN_IF); - add_first(RULE_COMMAND, TOKEN_NEGATION); - add_first(RULE_INPUT, TOKEN_NEWLINE); - add_first(RULE_INPUT, TOKEN_EOF); - - add_first(RULE_LIST, TOKEN_WORD); - add_first(RULE_LIST, TOKEN_IF); - add_first(RULE_LIST, TOKEN_NEGATION); - - add_first(RULE_AND_OR, TOKEN_WORD); - add_first(RULE_AND_OR, TOKEN_IF); - add_first(RULE_AND_OR, TOKEN_NEGATION); - - add_first(RULE_PIPELINE, TOKEN_WORD); - add_first(RULE_PIPELINE, TOKEN_IF); - add_first(RULE_PIPELINE, TOKEN_NEGATION); - - add_first(RULE_COMMAND, TOKEN_WORD); - add_first(RULE_COMMAND, TOKEN_IF); - - add_first(RULE_SIMPLE_COMMAND, TOKEN_WORD); - - add_first(RULE_SHELL_COMMAND, TOKEN_IF); + // TODO CHECK ORDER + // If add_first(RULE_IF, TOKEN_IF); - add_first(RULE_COMPOUND_LIST, TOKEN_NEWLINE); - add_first(RULE_COMPOUND_LIST, TOKEN_WORD); - add_first(RULE_COMPOUND_LIST, TOKEN_IF); - + // Else clause add_first(RULE_ELSE_CLAUSE, TOKEN_ELSE); add_first(RULE_ELSE_CLAUSE, TOKEN_ELIF); + // For + add_first(RULE_FOR, TOKEN_FOR); + + // While + add_first(RULE_WHILE, TOKEN_WHILE); + + // Until + add_first(RULE_WHILE, TOKEN_UNTIL); + + // Case + add_first(RULE_CASE, TOKEN_CASE); + + // Case item + add_first(RULE_CASE_ITEM, TOKEN_LEFT_PAREN); + add_first(RULE_CASE_ITEM, TOKEN_WORD); + + // Case clause + add_firsts(RULE_CASE_CLAUSE, first(RULE_CASE_ITEM)); + + // Redirection + add_first(RULE_REDIRECTION, TOKEN_IONUMBER); + add_first(RULE_REDIRECTION, TOKEN_REDIR_LEFT); + add_first(RULE_REDIRECTION, TOKEN_REDIR_RIGHT); + add_first(RULE_REDIRECTION, TOKEN_REDIR_LEFT_RIGHT); + add_first(RULE_REDIRECTION, TOKEN_REDIR_DOUBLE_RIGHT); + add_first(RULE_REDIRECTION, TOKEN_REDIR_LEFT_AMP); + add_first(RULE_REDIRECTION, TOKEN_REDIR_RIGHT_AMP); + add_first(RULE_REDIRECTION, TOKEN_REDIR_RIGHT_PIPE); + // %RIP Matteo 30/01/2026 + + // Element add_first(RULE_ELEMENT, TOKEN_WORD); - add_first_redir(RULE_ELEMENT); + add_firsts(RULE_ELEMENT, first(RULE_REDIRECTION)); - add_first_redir(RULE_REDIRECTION); + // Prefix + add_first(RULE_PREFIX, TOKEN_ASSIGNMENT_WORD); + add_firsts(RULE_PREFIX, first(RULE_REDIRECTION)); - add_first_redir(RULE_PREFIX); + // Shell command + add_firsts(RULE_SHELL_COMMAND, first(RULE_IF)); + + // Simple command + add_firsts(RULE_SIMPLE_COMMAND, first(RULE_PREFIX)); + + // Funcdec + add_first(RULE_FUNCDEC, TOKEN_WORD); + + // Command + add_firsts(RULE_COMMAND, first(RULE_SIMPLE_COMMAND)); + add_firsts(RULE_COMMAND, first(RULE_SHELL_COMMAND)); + add_firsts(RULE_COMMAND, first(RULE_FUNCDEC)); + + // Pipeline + add_first(RULE_PIPELINE, TOKEN_WORD); + add_firsts(RULE_PIPELINE, first(RULE_COMMAND)); + + // And Or + add_firsts(RULE_AND_OR, first(RULE_PIPELINE)); + + // Compound list + add_first(RULE_COMPOUND_LIST, TOKEN_NEWLINE); + add_firsts(RULE_COMPOUND_LIST, first(RULE_AND_OR)); + + // List + add_firsts(RULE_LIST, first(RULE_AND_OR)); + + // Input + add_first(RULE_INPUT, TOKEN_NEWLINE); + add_first(RULE_INPUT, TOKEN_EOF); + add_firsts(RULE_INPUT, first(RULE_LIST)); return true; } diff --git a/src/parser/grammar.h b/src/parser/grammar.h index 3c77747..663d37b 100644 --- a/src/parser/grammar.h +++ b/src/parser/grammar.h @@ -41,6 +41,13 @@ enum rule RULE_ELEMENT, RULE_REDIRECTION, RULE_PREFIX, + RULE_FUNCDEC, + RULE_WHILE, + RULE_UNTIL, + RULE_FOR, + RULE_CASE, + RULE_CASE_CLAUSE, + RULE_CASE_ITEM, NUMBER_OF_RULES }; @@ -89,6 +96,7 @@ bool is_first(struct token token, enum rule rule); * | '\n' * | EOF * ; + * @first first(list), '\n', EOF */ struct ast *parse_input(struct lexer_context *ctx); diff --git a/src/parser/grammar_basic.c b/src/parser/grammar_basic.c index 598c70a..9b4add2 100644 --- a/src/parser/grammar_basic.c +++ b/src/parser/grammar_basic.c @@ -160,13 +160,15 @@ struct ast *parse_command(struct lexer_context *ctx) } else if (is_first(*token, RULE_SHELL_COMMAND)) { - parse_shell_command(ctx); + result = parse_shell_command(ctx); } else { perror("Syntax error: unexpected token"); return NULL; } + + return result; } /* @brief: frees command_elements and redirections lists (helper func) diff --git a/src/parser/grammar_basic.h b/src/parser/grammar_basic.h index 5ef6a56..46f7b4f 100644 --- a/src/parser/grammar_basic.h +++ b/src/parser/grammar_basic.h @@ -99,7 +99,7 @@ struct ast *parse_if_rule(struct lexer_context *ctx); struct ast *parse_compound_list(struct lexer_context *ctx); /* - * @brief + * @brief parses an else clause rule (inside if) * * @code else_clause = 'else' compound_list * | 'elif' compound_list 'then' compound_list [else_clause]