feat: final firsts initialization

This commit is contained in:
Guillem George 2026-01-29 19:47:59 +01:00
parent 98d18eef7d
commit 3601c3136f
5 changed files with 104 additions and 50 deletions

View file

@ -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

View file

@ -4,7 +4,6 @@
#include <stdio.h>
#include <stdlib.h>
#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;
}

View file

@ -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);

View file

@ -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)

View file

@ -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]