merge parser into dev with ast loops

This commit is contained in:
Matteo Flebus 2026-01-30 19:57:36 +01:00
commit 4d271981df
10 changed files with 343 additions and 26 deletions

View file

@ -26,6 +26,29 @@ static enum ast_and_or_type and_or_tok_to_ast(enum token_type tok_type)
}
}
/* @brief: frees command_elements and redirections lists (helper func)
* @return: NULL
*/
static void *err_simple_command(struct list *command_elements,
struct list *redirections)
{
list_deep_destroy(command_elements);
list_deep_destroy(redirections);
return NULL;
}
/* @brief: frees all the arguments. (helper func)
* @return: NULL.
*/
static void *err_if_rule(struct ast **cond, struct ast **then_clause,
struct ast **else_clause)
{
ast_free(cond);
ast_free(then_clause);
ast_free(else_clause);
return NULL;
}
// === Functions
struct ast *parse_list(struct lexer_context *ctx)
@ -73,16 +96,11 @@ struct ast *parse_and_or(struct lexer_context *ctx)
while (token->type == TOKEN_AND || token->type == TOKEN_OR)
{
// Set left part
// Build AST (left part)
enum ast_and_or_type type = and_or_tok_to_ast(token->type);
struct ast *left = result;
// eat and_or token
token = POP_TOKEN();
// Set type
enum ast_and_or_type type = and_or_tok_to_ast(token->type);
POP_TOKEN();
token = PEEK_TOKEN();
// Skip newlines
@ -94,6 +112,12 @@ struct ast *parse_and_or(struct lexer_context *ctx)
// Right part
struct ast *right = parse_pipeline(ctx);
if (right == NULL)
{
ast_free(&left);
return NULL;
}
token = PEEK_TOKEN();
result = ast_create_and_or(left, right, type);
if (result == NULL)
@ -120,30 +144,33 @@ struct ast *parse_pipeline(struct lexer_context *ctx)
token = PEEK_TOKEN();
}
// command rule
struct ast *left = parse_command(ctx);
token = PEEK_TOKEN();
if (negation)
{
left = ast_create_neg(negation, left);
}
token = PEEK_TOKEN();
// Pipes
while (token->type == TOKEN_PIPE)
{
POP_TOKEN();
token = PEEK_TOKEN();
// skip newlines
token = PEEK_TOKEN();
while (token->type == TOKEN_NEWLINE)
{
POP_TOKEN();
token = PEEK_TOKEN();
}
// command rule
struct ast *right = parse_command(ctx);
token = PEEK_TOKEN();
// Create AST
left = ast_create_pipe(left, right);
token = PEEK_TOKEN();
}
return left;
@ -162,6 +189,11 @@ struct ast *parse_command(struct lexer_context *ctx)
{
result = parse_shell_command(ctx);
}
// WARNING funcdec seems to require a LL(2) parser
else if (is_first(*token, RULE_FUNCDEC))
{
result = parse_funcdec(ctx);
}
else
{
perror("Syntax error: unexpected token");
@ -336,19 +368,41 @@ struct ast *parse_element(struct lexer_context *ctx)
struct ast *parse_shell_command(struct lexer_context *ctx)
{
return parse_if_rule(ctx);
}
struct token *token = PEEK_TOKEN();
struct ast *result = NULL;
/* @brief: frees all the arguments. (helper func)
* @return: NULL.
*/
static void *err_if_rule(struct ast **cond, struct ast **then_clause,
struct ast **else_clause)
{
ast_free(cond);
ast_free(then_clause);
ast_free(else_clause);
return NULL;
// Grouping
// '(' or '{'
if (token->type == TOKEN_LEFT_BRACKET || token->type == TOKEN_LEFT_PAREN)
{
POP_TOKEN();
result = parse_compound_list(ctx);
if (result == NULL)
return NULL;
// ')' or '}'
token = PEEK_TOKEN();
if (token->type == TOKEN_LEFT_BRACKET
|| token->type == TOKEN_LEFT_PAREN)
{
ast_free(&result);
perror("Syntax error: bracket/parenthesis mismatch");
return NULL;
}
POP_TOKEN();
return result;
}
else if (is_first(*token, RULE_IF))
{
return parse_if_rule(ctx);
}
// TODO loops and case
else
{
perror("Syntax error: unexpected token in parse_shell_command");
return NULL;
}
}
struct ast *parse_if_rule(struct lexer_context *ctx)
@ -497,7 +551,6 @@ struct ast *parse_else_clause(struct lexer_context *ctx)
return NULL;
}
// Then clause
struct ast *then_content = parse_compound_list(ctx);
// Eventual else clause (recursive)