refactor: removed duplicate code for while/until loops in parser
This commit is contained in:
parent
423793903d
commit
9f967dc9b4
2 changed files with 78 additions and 98 deletions
|
|
@ -9,6 +9,8 @@
|
||||||
#include "grammar.h"
|
#include "grammar.h"
|
||||||
#include "grammar_basic.h"
|
#include "grammar_basic.h"
|
||||||
|
|
||||||
|
// === Static functions
|
||||||
|
|
||||||
static enum ast_redir_type redir_tok_to_ast_type(enum token_type tok_type)
|
static enum ast_redir_type redir_tok_to_ast_type(enum token_type tok_type)
|
||||||
{
|
{
|
||||||
switch (tok_type)
|
switch (tok_type)
|
||||||
|
|
@ -32,6 +34,71 @@ static enum ast_redir_type redir_tok_to_ast_type(enum token_type tok_type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief parses a while/until loop starting with the condition
|
||||||
|
* (after the while/until keyword)
|
||||||
|
* @arg negate_condition Set to true for until loops, false for while loops
|
||||||
|
*/
|
||||||
|
static struct ast *parse_loop(struct lexer_context *ctx, bool negate_condition)
|
||||||
|
{
|
||||||
|
// condition
|
||||||
|
struct ast *condition = parse_compound_list(ctx);
|
||||||
|
if (condition == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (negate_condition)
|
||||||
|
{
|
||||||
|
condition =
|
||||||
|
ast_create_neg(true, condition); // TODO check result (beware to not
|
||||||
|
// exceed the function lines limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct token *token = PEEK_TOKEN();
|
||||||
|
|
||||||
|
// 'do'
|
||||||
|
if (token->type != TOKEN_DO)
|
||||||
|
{
|
||||||
|
ast_free(&condition);
|
||||||
|
perror("Syntax error: expected the 'do' keyowrd but got a different "
|
||||||
|
"token");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
POP_TOKEN();
|
||||||
|
token = PEEK_TOKEN();
|
||||||
|
|
||||||
|
// body
|
||||||
|
struct ast *body = parse_compound_list(ctx);
|
||||||
|
if (body == NULL)
|
||||||
|
{
|
||||||
|
ast_free(&condition);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
token = PEEK_TOKEN();
|
||||||
|
|
||||||
|
// 'done'
|
||||||
|
if (token->type != TOKEN_DONE)
|
||||||
|
{
|
||||||
|
ast_free(&condition);
|
||||||
|
perror("Syntax error: expected the 'done' keyowrd but got a different "
|
||||||
|
"token");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
POP_TOKEN();
|
||||||
|
|
||||||
|
struct ast *result = ast_create_loop(condition, body);
|
||||||
|
if (result == NULL)
|
||||||
|
{
|
||||||
|
ast_free(&condition);
|
||||||
|
ast_free(&body);
|
||||||
|
perror("Internal error: could not create ast node (is your memory full "
|
||||||
|
"?)");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Functions
|
||||||
|
|
||||||
struct ast *parse_redirection(struct lexer_context *ctx)
|
struct ast *parse_redirection(struct lexer_context *ctx)
|
||||||
{
|
{
|
||||||
struct token *token = PEEK_TOKEN();
|
struct token *token = PEEK_TOKEN();
|
||||||
|
|
@ -110,53 +177,7 @@ struct ast *parse_while(struct lexer_context *ctx)
|
||||||
}
|
}
|
||||||
POP_TOKEN();
|
POP_TOKEN();
|
||||||
|
|
||||||
// condition
|
return parse_loop(ctx, true);
|
||||||
struct ast *condition = parse_compound_list(ctx);
|
|
||||||
if (condition == NULL)
|
|
||||||
return NULL;
|
|
||||||
token = PEEK_TOKEN();
|
|
||||||
|
|
||||||
// 'do'
|
|
||||||
if (token->type != TOKEN_DO)
|
|
||||||
{
|
|
||||||
ast_free(&condition);
|
|
||||||
perror("Syntax error: expected the 'do' keyowrd but got a different "
|
|
||||||
"token");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
POP_TOKEN();
|
|
||||||
token = PEEK_TOKEN();
|
|
||||||
|
|
||||||
// body
|
|
||||||
struct ast *body = parse_compound_list(ctx);
|
|
||||||
if (body == NULL)
|
|
||||||
{
|
|
||||||
ast_free(&condition);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
token = PEEK_TOKEN();
|
|
||||||
|
|
||||||
// 'done'
|
|
||||||
if (token->type != TOKEN_DONE)
|
|
||||||
{
|
|
||||||
ast_free(&condition);
|
|
||||||
perror("Syntax error: expected the 'done' keyowrd but got a different "
|
|
||||||
"token");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
POP_TOKEN();
|
|
||||||
|
|
||||||
struct ast *result = ast_create_loop(condition, body);
|
|
||||||
if (result == NULL)
|
|
||||||
{
|
|
||||||
ast_free(&condition);
|
|
||||||
ast_free(&body);
|
|
||||||
perror("Internal error: could not create ast node (is your memory full "
|
|
||||||
"?)");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ast *parse_until(struct lexer_context *ctx)
|
struct ast *parse_until(struct lexer_context *ctx)
|
||||||
|
|
@ -172,54 +193,5 @@ struct ast *parse_until(struct lexer_context *ctx)
|
||||||
}
|
}
|
||||||
POP_TOKEN();
|
POP_TOKEN();
|
||||||
|
|
||||||
// condition
|
return parse_loop(ctx, true);
|
||||||
struct ast *condition = parse_compound_list(ctx);
|
|
||||||
if (condition == NULL)
|
|
||||||
return NULL;
|
|
||||||
condition =
|
|
||||||
ast_create_neg(true, condition); // TODO check result (beware to not
|
|
||||||
// exceed function lines limit)
|
|
||||||
token = PEEK_TOKEN();
|
|
||||||
|
|
||||||
// 'do'
|
|
||||||
if (token->type != TOKEN_DO)
|
|
||||||
{
|
|
||||||
ast_free(&condition);
|
|
||||||
perror("Syntax error: expected the 'do' keyowrd but got a different "
|
|
||||||
"token");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
POP_TOKEN();
|
|
||||||
token = PEEK_TOKEN();
|
|
||||||
|
|
||||||
// body
|
|
||||||
struct ast *body = parse_compound_list(ctx);
|
|
||||||
if (body == NULL)
|
|
||||||
{
|
|
||||||
ast_free(&condition);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
token = PEEK_TOKEN();
|
|
||||||
|
|
||||||
// 'done'
|
|
||||||
if (token->type != TOKEN_DONE)
|
|
||||||
{
|
|
||||||
ast_free(&condition);
|
|
||||||
perror("Syntax error: expected the 'done' keyowrd but got a different "
|
|
||||||
"token");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
POP_TOKEN();
|
|
||||||
|
|
||||||
struct ast *result = ast_create_loop(condition, body);
|
|
||||||
if (result == NULL)
|
|
||||||
{
|
|
||||||
ast_free(&condition);
|
|
||||||
ast_free(&body);
|
|
||||||
perror("Internal error: could not create ast node (is your memory full "
|
|
||||||
"?)");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -349,7 +349,15 @@ struct ast *parse_shell_command(struct lexer_context *ctx)
|
||||||
{
|
{
|
||||||
return parse_if_rule(ctx);
|
return parse_if_rule(ctx);
|
||||||
}
|
}
|
||||||
// TODO loops and case
|
else if (is_first(*token, RULE_WHILE))
|
||||||
|
{
|
||||||
|
return parse_while(ctx);
|
||||||
|
}
|
||||||
|
else if (is_first(*token, RULE_UNTIL))
|
||||||
|
{
|
||||||
|
return parse_until(ctx);
|
||||||
|
}
|
||||||
|
// TODO for and case
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
perror("Syntax error: unexpected token in parse_shell_command");
|
perror("Syntax error: unexpected token in parse_shell_command");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue