merge parser in dev

This commit is contained in:
matteo 2026-01-29 19:50:42 +01:00
commit 56f0a979a7
5 changed files with 102 additions and 49 deletions

View file

@ -68,7 +68,11 @@ enum token_type
TOKEN_FI, TOKEN_FI,
TOKEN_ELIF, TOKEN_ELIF,
TOKEN_AND, TOKEN_AND,
TOKEN_OR TOKEN_OR,
TOKEN_FOR,
TOKEN_WHILE,
TOKEN_UNTIL,
TOKEN_CASE
}; };
struct token struct token

View file

@ -4,7 +4,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "../lexer/lexer.h"
#include "grammar_basic.h" #include "grammar_basic.h"
// === Static variables // === Static variables
@ -57,6 +56,23 @@ static bool add_first(enum rule rule, enum token_type token)
return true; 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) /* @brief initializes the firsts_map static variable (does not populate it)
* @return true on success, false on error * @return true on success, false on error
*/ */
@ -73,21 +89,6 @@ static bool init_firsts_map(void)
return true; 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 // === Functions
bool grammar_init(void) bool grammar_init(void)
@ -98,46 +99,85 @@ bool grammar_init(void)
return false; return false;
// Populate the firsts map // Populate the firsts map
add_first(RULE_INPUT, TOKEN_WORD); // TODO CHECK ORDER
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);
// If
add_first(RULE_IF, TOKEN_IF); add_first(RULE_IF, TOKEN_IF);
add_first(RULE_COMPOUND_LIST, TOKEN_NEWLINE); // Else clause
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_ELSE);
add_first(RULE_ELSE_CLAUSE, TOKEN_ELIF); 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(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; return true;
} }

View file

@ -41,6 +41,13 @@ enum rule
RULE_ELEMENT, RULE_ELEMENT,
RULE_REDIRECTION, RULE_REDIRECTION,
RULE_PREFIX, RULE_PREFIX,
RULE_FUNCDEC,
RULE_WHILE,
RULE_UNTIL,
RULE_FOR,
RULE_CASE,
RULE_CASE_CLAUSE,
RULE_CASE_ITEM,
NUMBER_OF_RULES NUMBER_OF_RULES
}; };
@ -89,6 +96,7 @@ bool is_first(struct token token, enum rule rule);
* | '\n' * | '\n'
* | EOF * | EOF
* ; * ;
* @first first(list), '\n', EOF
*/ */
struct ast *parse_input(struct lexer_context *ctx); struct ast *parse_input(struct lexer_context *ctx);

View file

@ -167,6 +167,7 @@ struct ast *parse_command(struct lexer_context *ctx)
perror("Syntax error: unexpected token"); perror("Syntax error: unexpected token");
return NULL; return NULL;
} }
return result; return result;
} }

View file

@ -99,7 +99,7 @@ struct ast *parse_if_rule(struct lexer_context *ctx);
struct ast *parse_compound_list(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 * @code else_clause = 'else' compound_list
* | 'elif' compound_list 'then' compound_list [else_clause] * | 'elif' compound_list 'then' compound_list [else_clause]