diff options
| author | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:07:58 +0200 |
|---|---|---|
| committer | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:07:58 +0200 |
| commit | 967be9e750221ab2ab783f95df79bb26d290a45e (patch) | |
| tree | 6802900a5e975f9f68b169f0f503f040056d6952 /42sh/src/parser/parser_conditionnals.c | |
Diffstat (limited to '42sh/src/parser/parser_conditionnals.c')
| -rw-r--r-- | 42sh/src/parser/parser_conditionnals.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/42sh/src/parser/parser_conditionnals.c b/42sh/src/parser/parser_conditionnals.c new file mode 100644 index 0000000..ef1f67a --- /dev/null +++ b/42sh/src/parser/parser_conditionnals.c @@ -0,0 +1,152 @@ +#include "parser/parser_functions.h" +#include "parser/parser_utils.h" + +struct ast *parse_rule_if(struct lexer *lexer, enum parser_state *state) +{ + struct token next = lexer_peek(lexer); + // Not mandatory because we checked before going in here + if (next.type != TOKEN_IF) + { + QUICK_CLEANUP + } + + struct ast *root = ast_create(AST_IF); + + if (root == NULL) + { + *state = ERROR; + return NULL; + } + + lexer_pop(lexer); + + struct ast *cond = parse_compound_list(lexer, state); + + next = lexer_peek(lexer); + if (error_check(root, state, next)) + { + return NULL; + } + + set_left(root, cond); + + if (next.type != TOKEN_THEN) + { + cleanup(root, state); + return NULL; + } + + lexer_pop(lexer); + + cond = parse_compound_list(lexer, state); + next = lexer_peek(lexer); + if (error_check(root, state, next)) + { + return NULL; + } + + if (cond == NULL) + { + cleanup(root, state); + return NULL; + } + + set_right(root, cond); + + if (next.type != TOKEN_FI) + { + cond = parse_else_clause(lexer, state); + if (cond == NULL) + { + cleanup(root, state); + return NULL; + } + set_i(root, cond, 2); + } + + lexer_pop(lexer); + + return root; +} + +struct ast *parse_else_clause(struct lexer *lexer, enum parser_state *state) +{ + struct token next = lexer_peek(lexer); + struct ast *root = NULL; + + if (next.type == TOKEN_ELSE) + { + lexer_pop(lexer); + + struct ast *cond = parse_compound_list(lexer, state); + + if (cond == NULL) + { + cleanup(root, state); + return NULL; + } + + if (error_check(cond, state, next)) + { + return NULL; + } + + return cond; + } + else if (next.type != TOKEN_ELIF) + { + cleanup(NULL, state); + return NULL; + } + + lexer_pop(lexer); + + // Doesn' it seems stupid to just manually re-creating the IF again? + // Can't I just call parse_if there ? But we won't be following the grammar + // This is a late-game optimization that might not be worth it + root = ast_create(AST_IF); + if (root == NULL) + { + cleanup(root, state); + return NULL; + } + + struct ast *cond = parse_compound_list(lexer, state); + set_left(root, cond); + + if (error_check(root, state, next)) + { + return NULL; + } + + next = lexer_peek(lexer); + + if (next.type != TOKEN_THEN) + { + cleanup(root, state); + return NULL; + } + + lexer_pop(lexer); + + set_right(root, parse_compound_list(lexer, state)); + + if (error_check(root, state, next)) + { + return NULL; + } + + next = lexer_peek(lexer); + + if (next.type == TOKEN_ELSE || next.type == TOKEN_ELIF) + { + cond = parse_else_clause(lexer, state); + if (error_check(root, state, next)) + { + return NULL; + } + set_i(root, cond, 2); + } + + return root; +} |
