feat: finished the new firsts system and began supporting redirections

This commit is contained in:
Gu://em_ 2026-01-24 16:13:16 +01:00
parent 32f56beb6b
commit 3ee4a0b9ca
4 changed files with 134 additions and 44 deletions

View file

@ -13,30 +13,13 @@ static struct firsts_list *firsts_map = NULL;
// === Static functions
/* @brief get the first accepted tokens of a rule
*
* @arg r the rule
* @return the accepted tokens as a firsts_list struct
*/
static struct firsts_list *first(enum rule r)
{
if (firsts_map == NULL || firsts_map[r].tokens == NULL)
{
puts("Internal error: attempted to get the firsts of a rule without "
"properly initializing the firsts map");
return NULL;
}
return &firsts_map[r];
}
/* @brief Add a token to a rule's firsts (in firsts_map)
*
* @arg rule the rule to which add a first
* @arg token the token to add to the rule's firsts
* @return true on success, false on error
*/
static bool add_first(enum rule rule, struct token token)
static bool add_first(enum rule rule, enum token_type token)
{
struct firsts_list *item = &firsts_map[rule];
if (item->tokens != NULL)
@ -44,20 +27,20 @@ static bool add_first(enum rule rule, struct token token)
// Check for duplicates
for (size_t i = 0; i < item->list_length; i++)
{
if (item->tokens[i].type == token.type)
if (item->tokens[i] == token)
return true;
}
// Append
item->list_length++;
item->tokens = realloc(
item->tokens, (item->list_length) * sizeof(struct firsts_list));
item->tokens, (item->list_length) * sizeof(enum token_type));
}
else
{
// Create entry
item->tokens =
calloc(item->list_length + 1, sizeof(struct firsts_list));
item->list_length = 1;
item->tokens = calloc(1, sizeof(enum token_type));
}
// Check for alloc error
@ -100,7 +83,45 @@ bool grammar_init(void)
return false;
// Populate the firsts map
// TODO
add_first(RULE_INPUT, TOKEN_WORD);
add_first(RULE_INPUT, TOKEN_IF);
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_AND_OR, TOKEN_WORD);
add_first(RULE_AND_OR, TOKEN_IF);
add_first(RULE_PIPELINE, TOKEN_WORD);
add_first(RULE_PIPELINE, TOKEN_IF);
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);
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);
add_first(RULE_ELSE_CLAUSE, TOKEN_ELSE);
add_first(RULE_ELSE_CLAUSE, TOKEN_ELIF);
add_first(RULE_ELEMENT, TOKEN_WORD);
add_first(RULE_ELEMENT, TOKEN_IONUMBER);
add_first(RULE_ELEMENT, TOKEN_REDIRECTION);
add_first(RULE_REDIRECTION, TOKEN_IONUMBER);
add_first(RULE_REDIRECTION, TOKEN_REDIRECTION);
add_first(RULE_PREFIX, TOKEN_IONUMBER);
add_first(RULE_PREFIX, TOKEN_REDIRECTION);
return true;
}
@ -119,6 +140,30 @@ void grammar_close(void)
firsts_map = NULL;
}
struct firsts_list *first(enum rule rule)
{
if (firsts_map == NULL || firsts_map[rule].tokens == NULL)
{
puts("Internal error: attempted to get the firsts of a rule without "
"properly initializing the firsts map");
return NULL;
}
return &firsts_map[rule];
}
bool is_first(struct token token, enum rule rule)
{
struct firsts_list *firsts = &firsts_map[rule];
for (size_t i = 0; i < firsts->list_length; i++)
{
if (firsts->tokens[i] == token.type)
return true;
}
return false;
}
struct ast *parse_input(struct lexer_context *ctx)
{
return parse_list(ctx);