From 0e3db10c626f54a6c6aa94aa59648782e8602c02 Mon Sep 17 00:00:00 2001 From: Charles Cabergs Date: Sat, 10 Oct 2020 09:21:54 +0200 Subject: Norming parser --- src/parser/expr.c | 127 +++++++++++++++++++++++++++++++ src/parser/parsed.c | 27 +------ src/parser/parsed_error.c | 43 +++++++++++ src/parser/parser.c | 187 ++++++++-------------------------------------- 4 files changed, 203 insertions(+), 181 deletions(-) create mode 100644 src/parser/expr.c create mode 100644 src/parser/parsed_error.c (limited to 'src') diff --git a/src/parser/expr.c b/src/parser/expr.c new file mode 100644 index 0000000..04aa685 --- /dev/null +++ b/src/parser/expr.c @@ -0,0 +1,127 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* expr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: cacharle +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/10/10 08:42:24 by cacharle #+# #+# */ +/* Updated: 2020/10/10 09:11:10 by cacharle ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" +#include "parser.h" + +/* +** push redirection token +** push while token is str and stick +** push last str token +*/ + +t_parsed *parse_redir(t_tok_lst *input, t_tok_lst **redirs) +{ + t_parsed *ret; + + tok_lst_push_back(redirs, tok_lst_uncons(&input)); + while (input != NULL && input->tag & TAG_IS_STR && input->tag & TAG_STICK && + input->next != NULL && input->next->tag & TAG_IS_STR) + tok_lst_push_back(redirs, tok_lst_uncons(&input)); + if (input == NULL) + return (parsed_unexpected("newline")); + if (!(input->tag & TAG_IS_STR)) + { + ret = parsed_unexpected(input->content); + tok_lst_destroy(&input, free); + return (ret); + } + tok_lst_push_back(redirs, tok_lst_uncons(&input)); + return (parsed_new(NULL, input)); +} + +static t_parsed *st_parse_cmd_body(t_tok_lst *input) +{ + t_ast *ast; + t_parsed *tmp; + + exit_if((ast = ast_new(AST_CMD)) == NULL); + while (input != NULL && + (input->tag & TAG_IS_STR || input->tag & TAG_IS_REDIR)) + { + if (input->tag & TAG_IS_STR) + tok_lst_push_back(&ast->cmd_argv, tok_lst_uncons(&input)); + else if (input->tag & TAG_IS_REDIR) + { + tmp = parse_redir(input, &ast->redirs); + if (parsed_err(tmp)) + { + tok_lst_destroy(&tmp->rest, free); + ast_destroy(ast); + return (tmp); + } + input = tmp->rest; + free(tmp); + } + } + return (parsed_new(ast, input)); +} + +t_parsed *parse_cmd(t_tok_lst *input) +{ + t_parsed *ret; + + if (input->tag & TAG_IS_SEP || input->tag == TAG_PIPE || + input->tag == TAG_PARENT_CLOSE) + { + ret = parsed_unexpected(input->content); + tok_lst_destroy(&input, free); + return (ret); + } + return (st_parse_cmd_body(input)); +} + +static t_parsed *st_parse_parenthesis(t_tok_lst *input) +{ + t_parsed *parsed; + t_parsed *tmp; + t_ast *ast; + + if (parsed_err(parsed = parse_op(input))) + return (parsed); + if ((input = parsed->rest) == NULL || !(input->tag & TAG_PARENT_CLOSE)) + { + ast_destroy(parsed->ast); + free(parsed); + return (parsed_expected()); + } + tok_lst_pop_front(&input, free); + exit_if((ast = ast_new(AST_PARENT)) == NULL); + ast->parent_ast = parsed->ast; + parsed->ast = ast; + while (input != NULL && input->tag & TAG_IS_REDIR) + { + if (parsed_err(tmp = parse_redir(input, &parsed->ast->redirs))) + return (tmp); + input = tmp->rest; + free(tmp); + } + parsed->rest = input; + return (parsed); +} + +/* +** try to parse parenthesis, if fail parse a command. +** parenthesis can be followed by redirections +*/ + +t_parsed *parse_expr(t_tok_lst *input) +{ + if (input->tag & TAG_PARENT_OPEN) + { + tok_lst_pop_front(&input, free); + if (input == NULL) + return (parsed_expected()); + return (st_parse_parenthesis(input)); + } + return (parse_cmd(input)); +} diff --git a/src/parser/parsed.c b/src/parser/parsed.c index 7b82832..4ad21c1 100644 --- a/src/parser/parsed.c +++ b/src/parser/parsed.c @@ -6,7 +6,7 @@ /* By: charles +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/08/27 20:27:42 by charles #+# #+# */ -/* Updated: 2020/10/09 16:00:02 by cacharle ### ########.fr */ +/* Updated: 2020/10/10 09:20:28 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,31 +24,6 @@ t_parsed *parsed_new(t_ast *ast, t_tok_lst *rest) return (ret); } -t_parsed *parsed_error(const char *format, ...) -{ - t_parsed *err; - va_list ap; - - if ((err = parsed_new(NULL, NULL)) == NULL) - return (NULL); - err->syntax_error = true; - va_start(ap, format); - verrorf(format, ap); - va_end(ap); - ft_putchar_fd('\n', STDERR_FILENO); - return (err); -} - -t_parsed *parsed_expected(void) -{ - return (parsed_error("syntax error expected token")); -} - -t_parsed *parsed_unexpected(char *content) -{ - return (parsed_error("syntax error near unexpected token `%s'", content)); -} - void parsed_destroy(t_parsed *parsed) { ast_destroy(parsed->ast); diff --git a/src/parser/parsed_error.c b/src/parser/parsed_error.c new file mode 100644 index 0000000..a38a85c --- /dev/null +++ b/src/parser/parsed_error.c @@ -0,0 +1,43 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parsed_error.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: cacharle +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/10/10 09:20:17 by cacharle #+# #+# */ +/* Updated: 2020/10/10 09:20:30 by cacharle ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser.h" + +t_parsed *parsed_error(const char *format, ...) +{ + t_parsed *err; + va_list ap; + + if ((err = parsed_new(NULL, NULL)) == NULL) + return (NULL); + err->syntax_error = true; + va_start(ap, format); + verrorf(format, ap); + va_end(ap); + ft_putchar_fd('\n', STDERR_FILENO); + return (err); +} + +t_parsed *parsed_expected(void) +{ + return (parsed_error("syntax error expected token")); +} + +t_parsed *parsed_unexpected(char *content) +{ + return (parsed_error("syntax error near unexpected token `%s'", content)); +} + +bool parsed_err(t_parsed *parsed) +{ + return (parsed == NULL || parsed->syntax_error); +} diff --git a/src/parser/parser.c b/src/parser/parser.c index 9493955..a75ad03 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -6,7 +6,7 @@ /* By: nahaddac +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/06/17 18:09:04 by nahaddac #+# #+# */ -/* Updated: 2020/10/09 20:39:47 by charles ### ########.fr */ +/* Updated: 2020/10/10 09:19:32 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -30,68 +30,10 @@ static char *g_sep_str_lookup[] = { [TAG_PARENT_OPEN] = "(", }; -/* -** push redirection token -** push while token is str and stick -** push last str token -*/ - -t_parsed *parse_redir(t_tok_lst *input, t_tok_lst **redirs) +t_parsed *destroy_ret(t_parsed *destroyed, t_parsed *ret) { - t_parsed *ret; - - tok_lst_push_back(redirs, tok_lst_uncons(&input)); - while (input != NULL && input->tag & TAG_IS_STR && - input->tag & TAG_STICK && - input->next != NULL && input->next->tag & TAG_IS_STR) - tok_lst_push_back(redirs, tok_lst_uncons(&input)); - if (input == NULL) - return (parsed_unexpected("newline")); - if (!(input->tag & TAG_IS_STR)) - { - ret = parsed_unexpected(input->content); - tok_lst_destroy(&input, free); - return (ret); - } - tok_lst_push_back(redirs, tok_lst_uncons(&input)); - return (parsed_new(NULL, input)); -} - -t_parsed *parse_cmd(t_tok_lst *input) -{ - t_ast *ast; - t_parsed *tmp; - t_parsed *ret; - - if (input->tag & TAG_IS_SEP || input->tag == TAG_PIPE || - input->tag == TAG_PARENT_CLOSE) - { - ret = parsed_unexpected(input->content); - tok_lst_destroy(&input, free); - return (ret); - } - if ((ast = ast_new(AST_CMD)) == NULL) - return (NULL); - while (input != NULL) - { - if (input->tag & TAG_IS_STR) - tok_lst_push_back(&ast->cmd_argv, tok_lst_uncons(&input)); - else if (input->tag & TAG_IS_REDIR) - { - tmp = parse_redir(input, &ast->redirs); - if (tmp == NULL || tmp->syntax_error) - { - tok_lst_destroy(&tmp->rest, free); - ast_destroy(ast); - return (tmp); - } - input = tmp->rest; - free(tmp); - } - else - break ; - } - return (parsed_new(ast, input)); + parsed_destroy(destroyed); + return (ret); } t_parsed *parse_pipeline(t_tok_lst *input) @@ -102,23 +44,13 @@ t_parsed *parse_pipeline(t_tok_lst *input) t_ast *pipeline_ast; expr = parse_expr(input); - if (expr == NULL || expr->syntax_error || - expr->rest == NULL || expr->rest->tag != TAG_PIPE) + if (parsed_err(expr) || expr->rest == NULL || expr->rest->tag != TAG_PIPE) return (expr); tok_lst_pop_front(&expr->rest, free); if (expr->rest == NULL) - { - ast_destroy(expr->ast); - free(expr); - return (parsed_expected()); - } - tail = parse_pipeline(expr->rest); - if (tail == NULL || tail->syntax_error) - { - ast_destroy(expr->ast); - free(expr); - return (tail); - } + return (destroy_ret(expr, parsed_expected())); + if (parsed_err(tail = parse_pipeline(expr->rest))) + return (destroy_ret(expr, tail)); expr_ast = expr->ast; free(expr); if (tail->ast->tag == AST_CMD || tail->ast->tag == AST_PARENT) @@ -133,106 +65,51 @@ t_parsed *parse_pipeline(t_tok_lst *input) return (tail); } +t_parsed *parse_op_build(t_parsed *left, t_parsed *right, enum e_tok sep_tag) +{ + t_ast *ast; + + exit_if((ast = ast_new(AST_OP)) == NULL); + ast->op.left = left->ast; + ast->op.right = right->ast; + ast->op.sep = sep_tag; + free(left); + left = parsed_new(ast, right->rest); + free(right); + return (left); +} + /* ** parse and operation (| ; && ||) */ t_parsed *parse_op(t_tok_lst *input) { - t_ast *ast; t_parsed *left; t_parsed *right; enum e_tok sep_tag; if (input == NULL) return (NULL); - left = parse_pipeline(input); - if (left == NULL || left->syntax_error) + if (parsed_err(left = parse_pipeline(input))) return (left); - input = left->rest; - if (input == NULL || input->tag & TAG_PARENT_CLOSE) + if ((input = left->rest) == NULL || input->tag & TAG_PARENT_CLOSE) return (left); - sep_tag = input->tag; - if (!(sep_tag & TAG_IS_SEP)) + if (!((sep_tag = input->tag) & TAG_IS_SEP)) { - ast_destroy(left->ast); tok_lst_destroy(&left->rest, free); - free(left); + parsed_destroy(left); return (parsed_unexpected(g_sep_str_lookup[sep_tag])); } tok_lst_pop_front(&input, free); if (input == NULL && sep_tag == TAG_END) - { - left->rest = NULL; - return (left); - } + return ((left->rest = NULL) ? left : left); if (input == NULL) - { - ast_destroy(left->ast); - free(left); - return (parsed_expected()); - } + return (destroy_ret(left, parsed_expected())); right = parse_op(input); - if (right == NULL || right->syntax_error) - { - ast_destroy(left->ast); - free(left); - return (right); - } - if ((ast = ast_new(AST_OP)) == NULL) - return (NULL); - ast->op.left = left->ast; - ast->op.right = right->ast; - ast->op.sep = sep_tag; - free(left); - left = parsed_new(ast, right->rest); - free(right); - return (left); -} - -/* -** try to parse parenthesis, if fail parse a command. -** parenthesis can be followed by redirections -*/ - -t_parsed *parse_expr(t_tok_lst *input) -{ - t_parsed *parsed; - t_parsed *tmp; - t_ast *ast; - - if (input->tag & TAG_PARENT_OPEN) - { - tok_lst_pop_front(&input, free); - if (input == NULL) - return (parsed_expected()); - parsed = parse_op(input); - if (parsed == NULL || parsed->syntax_error) - return (parsed); - input = parsed->rest; - if (input == NULL || !(input->tag & TAG_PARENT_CLOSE)) - { - ast_destroy(parsed->ast); - free(parsed); - return (parsed_expected()); - } - tok_lst_pop_front(&input, free); - if ((ast = ast_new(AST_PARENT)) == NULL) - return (NULL); - ast->parent_ast = parsed->ast; - parsed->ast = ast; - while (input != NULL && input->tag & TAG_IS_REDIR) - { - tmp = parse_redir(input, &parsed->ast->redirs); - if (tmp == NULL || tmp->syntax_error) - return (tmp); - input = tmp->rest; - free(tmp); - } - parsed->rest = input; - return (parsed); - } - return (parse_cmd(input)); + if (parsed_err(right)) + return (destroy_ret(left, right)); + return (parse_op_build(left, right, sep_tag)); } t_parsed *parse(t_tok_lst *input) @@ -243,7 +120,7 @@ t_parsed *parse(t_tok_lst *input) if (input == NULL) return (NULL); parsed = parse_op(input); - if (parsed == NULL || parsed->syntax_error) + if (parsed_err(parsed)) return (parsed); if (parsed->rest != NULL) { -- cgit