feat(parser): parse_command version with prefixes and elements

This commit is contained in:
matteo 2026-01-28 12:11:40 +01:00
parent 9d586402df
commit 51fc8a3330

View file

@ -153,11 +153,11 @@ struct ast *parse_command(struct lexer_context *ctx)
{ {
struct token *token = PEEK_TOKEN(); struct token *token = PEEK_TOKEN();
if (token->type == TOKEN_WORD) if (is_first(*token, RULE_SIMPLE_COMMAND))
{ {
return parse_simple_command(ctx); return parse_simple_command(ctx);
} }
else if (token->type == TOKEN_IF) else if (is_first(*token, RULE_SHELL_COMMAND))
{ {
return parse_shell_command(ctx); return parse_shell_command(ctx);
} }
@ -168,23 +168,54 @@ struct ast *parse_command(struct lexer_context *ctx)
} }
} }
/* @brief: frees command_elements and redirections lists
* @return: NULL
*/
static err_simple_command(struct list *command_elements,
struct list *redirections)
{
list_deep_destroy(command_elements);
list_deep_destroy(redirections);
return NULL;
}
struct ast *parse_simple_command(struct lexer_context *ctx) struct ast *parse_simple_command(struct lexer_context *ctx)
{ {
struct list *command_elements = NULL; struct list *command_elements = NULL;
struct list *redirections = NULL; // list of redirection ASTs struct list *redirections = NULL; // list of redirection ASTs
// WORD bool has_prefix = false;
struct token *token = POP_TOKEN(); struct token *token = PEEK_TOKEN();
if (token->type != TOKEN_WORD) if (is_first(*token, RULE_PREFIX))
{
has_prefix = true;
while (is_first(*token, RULE_PREFIX))
{
struct ast *redir = parse_prefix(ctx);
if (redir == NULL)
{
return err_simple_command(command_elements, redirections);
}
redirections = list_append(redirections, redir);
token = PEEK_TOKEN();
}
}
if (token->type != TOKEN_WORD && !has_prefix)
{ {
perror("Expected a command but got a different token type"); perror("Expected a command but got a different token type");
return NULL; return err_simple_command(command_elements, redirections);
} }
char *command = strdup(token->data);
command_elements = list_append(command_elements, command);
token = PEEK_TOKEN(); // we can have only prefixes askip
if (token->type == TOKEN_WORD)
{
char *command = strdup(token->data);
command_elements = list_append(command_elements, command);
POP_TOKEN();
token = PEEK_TOKEN();
}
// Eventual elements // Eventual elements
while (is_first(*token, RULE_ELEMENT)) while (is_first(*token, RULE_ELEMENT))
{ {
@ -192,16 +223,20 @@ struct ast *parse_simple_command(struct lexer_context *ctx)
struct ast *element = parse_element(ctx); struct ast *element = parse_element(ctx);
if (element == NULL) if (element == NULL)
{ {
list_deep_destroy(command_elements); return err_simple_command(command_elements, redirections);
return NULL;
} }
// Get element type // Get element type
if (ast_is_word(element)) if (ast_is_word(element))
{ {
struct ast_word *element_word = ast_get_word(element); struct ast_word *element_word = ast_get_word(element);
// TODO test this fix for the memory leaks
char *word = strdup(element_word->word);
ast_free(element_word);
command_elements = command_elements =
list_append(command_elements, element_word->word); list_append(command_elements, word);
// end of fix
} }
else if (ast_is_redir(element)) else if (ast_is_redir(element))
{ {
@ -212,9 +247,7 @@ struct ast *parse_simple_command(struct lexer_context *ctx)
{ {
perror("Internal error: unexpected return value from parse_element " perror("Internal error: unexpected return value from parse_element "
"in parse_simple_command"); "in parse_simple_command");
list_deep_destroy(command_elements); return err_simple_command(command_elements, redirections);
list_deep_destroy(redirections);
return NULL;
} }
// Forward // Forward
@ -225,9 +258,7 @@ struct ast *parse_simple_command(struct lexer_context *ctx)
struct ast *result = ast_create_command(command_elements, redirections); struct ast *result = ast_create_command(command_elements, redirections);
if (result == NULL) if (result == NULL)
{ {
list_deep_destroy(command_elements); return err_simple_command(command_elements, redirections);
list_deep_destroy(redirections);
return NULL;
} }
return result; return result;
} }