#define _POSIX_C_SOURCE 200809L #include "grammar_advanced.h" #include #include #include #include "grammar.h" #include "grammar_basic.h" // === Static functions static enum ast_redir_type redir_tok_to_ast_type(enum token_type tok_type) { switch (tok_type) { case TOKEN_REDIR_LEFT: return AST_REDIR_TYPE_LESS; case TOKEN_REDIR_RIGHT: return AST_REDIR_TYPE_GREAT; case TOKEN_REDIR_DOUBLE_RIGHT: return AST_REDIR_TYPE_DGREAT; case TOKEN_REDIR_LEFT_RIGHT: return AST_REDIR_TYPE_LESSGREAT; case TOKEN_REDIR_LEFT_AMP: return AST_REDIR_TYPE_LESSAND; case TOKEN_REDIR_RIGHT_AMP: return AST_REDIR_TYPE_GREATAND; case TOKEN_REDIR_RIGHT_PIPE: return AST_REDIR_TYPE_CLOBBER; default: return AST_REDIR_TYPE_NULL; } } /* * @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 token *token = PEEK_TOKEN(); int io_number = -1; if (token->type == TOKEN_IONUMBER) { io_number = atoi(token->data); POP_TOKEN(); token = PEEK_TOKEN(); } if (!is_token_redir(token)) { perror("Syntax error: expected a redirection token but got something " "else"); return NULL; } enum ast_redir_type redir_type = redir_tok_to_ast_type(token->type); POP_TOKEN(); token = PEEK_TOKEN(); if (token->type != TOKEN_WORD) { perror("Syntax error: expected a word after redirection"); return NULL; } char *target = strdup(token->data); POP_TOKEN(); return ast_create_redir(target, io_number, redir_type); } struct ast *parse_prefix(struct lexer_context *ctx) { struct token *token = PEEK_TOKEN(); if (token->type == TOKEN_ASSIGNMENT_WORD) { token = POP_TOKEN(); return ast_create_assignment(token->data, false); } else if (is_first(*token, RULE_REDIRECTION)) return parse_redirection(ctx); else { perror("Syntax error: expected a prefix (redirection or assignment)"); return NULL; } } // TODO NOT IMPLEMENTED struct ast *parse_funcdec(struct lexer_context *ctx) { (void)ctx; perror("Error: usage of a not implemented function (parse_funcdec)"); return NULL; } struct ast *parse_for(struct lexer_context *ctx) { (void)ctx; perror("Error: usage of a not implemented function (parse_for)"); return NULL; } struct ast *parse_while(struct lexer_context *ctx) { struct token *token = PEEK_TOKEN(); // 'while' if (token->type != TOKEN_WHILE) { perror( "Internal error: expected a TOKEN_WHILE but got a different type"); return NULL; } POP_TOKEN(); return parse_loop(ctx, true); } struct ast *parse_until(struct lexer_context *ctx) { struct token *token = PEEK_TOKEN(); // 'while' if (token->type != TOKEN_UNTIL) { perror( "Internal error: expected a TOKEN_WHILE but got a different type"); return NULL; } POP_TOKEN(); return parse_loop(ctx, true); }