aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Cabergs <me@cacharle.xyz>2020-10-10 09:21:54 +0200
committerCharles Cabergs <me@cacharle.xyz>2020-10-10 09:21:54 +0200
commit0e3db10c626f54a6c6aa94aa59648782e8602c02 (patch)
tree7052de4dede546c7819192cdbc7aaa7250005329
parent5f908033e68f6f3e03f2c38f4c396a0eab77ed05 (diff)
downloadminishell-0e3db10c626f54a6c6aa94aa59648782e8602c02.tar.gz
minishell-0e3db10c626f54a6c6aa94aa59648782e8602c02.tar.bz2
minishell-0e3db10c626f54a6c6aa94aa59648782e8602c02.zip
Norming parser
-rw-r--r--include/parser.h23
-rw-r--r--src/parser/expr.c127
-rw-r--r--src/parser/parsed.c27
-rw-r--r--src/parser/parsed_error.c43
-rw-r--r--src/parser/parser.c187
5 files changed, 220 insertions, 187 deletions
diff --git a/include/parser.h b/include/parser.h
index 4bf79df..c2d2381 100644
--- a/include/parser.h
+++ b/include/parser.h
@@ -6,7 +6,7 @@
/* By: cacharle <cacharle@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2020/02/28 09:00:00 by cacharle #+# #+# */
-/* Updated: 2020/10/10 07:37:55 by cacharle ### ########.fr */
+/* Updated: 2020/10/10 09:20:53 by cacharle ### ########.fr */
/* */
/* ************************************************************************** */
@@ -98,10 +98,6 @@ typedef struct s_ast
t_ast *ast_new(enum e_ast tag);
void ast_destroy(t_ast *ast);
-/*
-** parsed.c
-*/
-
typedef struct s_parsed
{
bool syntax_error;
@@ -109,11 +105,21 @@ typedef struct s_parsed
t_tok_lst *rest;
} t_parsed;
+/*
+** parsed.c
+*/
+
t_parsed *parsed_new(t_ast *ast, t_tok_lst *rest);
+void parsed_destroy(t_parsed *parsed);
+
+/*
+** parsed_error.c
+*/
+
t_parsed *parsed_error(const char *format, ...);
t_parsed *parsed_expected(void);
t_parsed *parsed_unexpected(char *content);
-void parsed_destroy(t_parsed *parsed);
+bool parsed_err(t_parsed *parsed);
/*
** parse.c
@@ -121,6 +127,11 @@ void parsed_destroy(t_parsed *parsed);
t_parsed *parse(t_tok_lst *input);
t_parsed *parse_op(t_tok_lst *input);
+
+/*
+** parse.c
+*/
+
t_parsed *parse_expr(t_tok_lst *input);
t_parsed *parse_cmd(t_tok_lst *input);
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 <me@cacharle.xyz> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* 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 <me@cacharle.xyz> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <me@cacharle.xyz> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* 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 <nahaddac@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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)
{