aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--include/ast.h28
-rw-r--r--include/env.h23
-rw-r--r--include/minishell.h13
-rw-r--r--include/token.h14
-rw-r--r--src/collect_redirs.c99
-rw-r--r--src/free_node.c23
-rw-r--r--src/free_token.c23
-rw-r--r--src/new_node.c27
-rw-r--r--src/parse_cmd.c52
-rw-r--r--src/parser.c84
-rw-r--r--src/print_ast.c59
-rw-r--r--src/repl.c17
-rw-r--r--src/tokenizer.c4
14 files changed, 383 insertions, 86 deletions
diff --git a/Makefile b/Makefile
index 4ac27f7..827c317 100644
--- a/Makefile
+++ b/Makefile
@@ -12,7 +12,8 @@ HEADERS = -I include -I $(LIB_DIR)/libft
VPATH := src
SRC := main.c debug_tools.c init.c signal_handling.c repl.c new_token.c \
- free_token.c new_node.c free_node.c tokenizer.c
+ free_token.c new_node.c free_node.c tokenizer.c parser.c \
+ parse_cmd.c collect_redirs.c print_ast.c
OBJ_DIR := _obj
OBJ := $(addprefix $(OBJ_DIR)/, $(SRC:%.c=%.o))
diff --git a/include/ast.h b/include/ast.h
index e6ad25d..cd2f9c9 100644
--- a/include/ast.h
+++ b/include/ast.h
@@ -6,32 +6,20 @@
/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/27 11:48:27 by dkaiser #+# #+# */
-/* Updated: 2024/06/28 14:56:55 by dkaiser ### ########.fr */
+/* Updated: 2024/08/11 12:20:56 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
-#include "stdlib.h"
#include "debug_tools.h"
-
-typedef struct s_sequence
-{
- struct s_node **nodes;
-} t_sequence;
+#include "stdlib.h"
enum e_node_type
{
- ASSIGN_NODE,
PIPE_NODE,
CMD_NODE,
STRING_NODE
};
-typedef struct s_assign
-{
- char *var;
- char *value;
-} t_assign;
-
typedef struct s_pipe
{
struct s_node *left;
@@ -40,10 +28,10 @@ typedef struct s_pipe
enum e_redirection_type
{
- INPUT_FILE,
- INPUT_LIMITER,
- OUTPUT_OVERRIDE,
- OUTPUT_APPEND
+ INPUT_FILE = 1,
+ INPUT_LIMITER = 2,
+ OUTPUT_OVERRIDE = 4,
+ OUTPUT_APPEND = 8
};
typedef struct s_redirection
@@ -60,7 +48,6 @@ typedef struct s_cmd
union u_node_content
{
- struct s_assign assign;
struct s_pipe pipe;
struct s_cmd cmd;
char *string;
@@ -73,7 +60,8 @@ typedef struct s_node
} t_node;
t_node *new_node(int type);
-t_node *new_assign_node(char *var, char *value);
t_node *new_pipe_node(t_node *left, t_node *right);
t_node *new_cmd_node(char **args, t_redirection redirs[2]);
t_node *new_string_node(char *string);
+
+void free_node(t_node *node);
diff --git a/include/env.h b/include/env.h
index 1ea6f2e..f3d3c75 100644
--- a/include/env.h
+++ b/include/env.h
@@ -6,18 +6,19 @@
/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/08/08 16:53:39 by dkaiser #+# #+# */
-/* Updated: 2024/08/08 17:05:11 by dkaiser ### ########.fr */
+/* Updated: 2024/09/13 16:26:16 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
-typedef struct s_env {
- char *name;
- char *value;
- struct s_env *next;
-} t_env;
+typedef struct s_env
+{
+ char *name;
+ char *value;
+ struct s_env *next;
+} t_env;
-char *env_get(t_env *env, char *name);
-void env_export(t_env *env, char *name, char *value);
-void env_unset(t_env *env, char *name);
-char **env_to_strlst(t_env *env);
-t_env **env_from_strlst(char **lst);
+char *env_get(t_env *env, char *name);
+void env_export(t_env *env, char *name, char *value);
+void env_unset(t_env *env, char *name);
+char **env_to_strlst(t_env *env);
+t_env **env_from_strlst(char **lst);
diff --git a/include/minishell.h b/include/minishell.h
index c108d93..6997b15 100644
--- a/include/minishell.h
+++ b/include/minishell.h
@@ -6,7 +6,7 @@
/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/22 17:14:49 by dkaiser #+# #+# */
-/* Updated: 2024/08/08 17:10:12 by dkaiser ### ########.fr */
+/* Updated: 2024/08/11 12:22:07 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
@@ -26,9 +26,14 @@
# include <termios.h>
# include <unistd.h>
-int init(void);
-int init_signal_handling(void);
+int init(void);
+int init_signal_handling(void);
-void repl(const char *prompt);
+void repl(const char *prompt);
+t_list *parse(t_token *tokens);
+t_node *parse_cmd(t_token *tokens);
+t_redirection *collect_redirs(t_token **tokens);
+
+void print_ast(t_node *ast);
#endif
diff --git a/include/token.h b/include/token.h
index 80ace03..54a65f2 100644
--- a/include/token.h
+++ b/include/token.h
@@ -6,7 +6,7 @@
/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/27 13:27:18 by dkaiser #+# #+# */
-/* Updated: 2024/08/11 13:46:22 by chuhlig ### ########.fr */
+/* Updated: 2024/08/29 15:26:23 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
@@ -17,10 +17,10 @@
enum e_token_type
{
- STRING_TOKEN,
- PIPE_TOKEN,
- REDIR_TOKEN,
- NEWLINE_TOKEN
+ STRING_TOKEN = 1,
+ PIPE_TOKEN = 2,
+ REDIR_TOKEN = 4,
+ NEWLINE_TOKEN = 8
};
union u_token_content
@@ -45,7 +45,9 @@ t_token *new_redir_token(int type, t_token *previous,
t_token *next);
void free_token(t_token *token);
+void free_token_and_connect(t_token *token);
+void free_tokens(t_token *tokens);
void tokenizer(char *s, t_token **token_list,
char quote_check);
-#endif \ No newline at end of file
+#endif
diff --git a/src/collect_redirs.c b/src/collect_redirs.c
new file mode 100644
index 0000000..9ac1605
--- /dev/null
+++ b/src/collect_redirs.c
@@ -0,0 +1,99 @@
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* collect_redirs.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/08/02 13:49:31 by dkaiser #+# #+# */
+/* Updated: 2024/09/17 19:48:48 by dkaiser ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "minishell.h"
+
+static t_token *collect_redir(t_token **tokens, t_redirection *result,
+ t_token *cur);
+static void collect_and_check_redir(t_token **tokens, t_redirection *result,
+ t_token **cur);
+static void set_redir(t_redirection *redir, int type, char *specifier);
+static int is_output_redir(int i);
+
+t_redirection *collect_redirs(t_token **tokens)
+{
+ t_redirection *result;
+ t_token *cur;
+
+ cur = *tokens;
+ result = malloc(sizeof(t_redirection) * 2);
+ if (result == NULL)
+ return (free_tokens(*tokens), NULL);
+ set_redir(&result[0], 0, NULL);
+ set_redir(&result[1], 0, NULL);
+ while (cur != NULL && cur->next != NULL)
+ {
+ if (cur->type == REDIR_TOKEN && cur->next->type == STRING_TOKEN)
+ collect_and_check_redir(tokens, result, &cur);
+ else if (cur->type == REDIR_TOKEN)
+ return (free(result), NULL);
+ else
+ cur = cur->next;
+ }
+ if (cur && cur->type == REDIR_TOKEN)
+ return (free(result), NULL);
+ return (result);
+}
+
+static void collect_and_check_redir(t_token **tokens, t_redirection *result,
+ t_token **cur)
+{
+ int is_redir_only;
+
+ is_redir_only = 0;
+ if ((*cur)->previous == NULL && (*cur)->next->next == NULL)
+ is_redir_only = 1;
+ *cur = collect_redir(tokens, result, *cur);
+ if (is_redir_only)
+ *tokens = NULL;
+}
+
+static t_token *collect_redir(t_token **tokens, t_redirection *result,
+ t_token *cur)
+{
+ set_redir(&result[is_output_redir(cur->content.redir_type)],
+ cur->content.redir_type, cur->next->content.string);
+ cur = cur->next;
+ free_token_and_connect(cur->previous);
+ if (cur->next != NULL)
+ {
+ if (cur->previous == NULL)
+ *tokens = cur->next;
+ cur = cur->next;
+ free_token_and_connect(cur->previous);
+ }
+ else
+ {
+ free_token(cur);
+ return (NULL);
+ }
+ return (cur);
+}
+
+static void set_redir(t_redirection *redir, int type, char *specifier)
+{
+ redir->type = type;
+ redir->specifier = specifier;
+}
+
+static int is_output_redir(int i)
+{
+ if (i & (INPUT_FILE | INPUT_LIMITER))
+ return (0);
+ else if (i & (OUTPUT_APPEND | OUTPUT_OVERRIDE))
+ return (1);
+ else
+ {
+ panic(UNREACHABLE);
+ return (-1);
+ }
+}
diff --git a/src/free_node.c b/src/free_node.c
index 8f32c12..6eae059 100644
--- a/src/free_node.c
+++ b/src/free_node.c
@@ -6,21 +6,18 @@
/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/27 11:41:46 by dkaiser #+# #+# */
-/* Updated: 2024/06/28 14:55:50 by dkaiser ### ########.fr */
+/* Updated: 2024/08/11 12:26:20 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
#include "ast.h"
-static void free_assign_node(t_node *node);
static void free_pipe_node(t_node *node);
static void free_cmd_node(t_node *node);
void free_node(t_node *node)
{
- if (node->type == ASSIGN_NODE)
- free_assign_node(node);
- else if (node->type == PIPE_NODE)
+ if (node->type == PIPE_NODE)
free_pipe_node(node);
else if (node->type == CMD_NODE)
free_cmd_node(node);
@@ -31,12 +28,6 @@ void free_node(t_node *node)
free(node);
}
-static void free_assign_node(t_node *node)
-{
- free(node->content.assign.var);
- free(node->content.assign.value);
-}
-
static void free_pipe_node(t_node *node)
{
free_node(node->content.pipe.left);
@@ -48,12 +39,16 @@ static void free_cmd_node(t_node *node)
int i;
i = 0;
- while (node->content.cmd.args[i] != NULL)
+ while (node->content.cmd.args != NULL && node->content.cmd.args[i] != NULL)
{
free(node->content.cmd.args[i]);
i++;
}
free(node->content.cmd.args);
- free(node->content.cmd.redirs[0].specifier);
- free(node->content.cmd.redirs[1].specifier);
+ if (node->content.cmd.redirs[0].type != 0
+ && node->content.cmd.redirs[0].specifier != NULL)
+ free(node->content.cmd.redirs[0].specifier);
+ if (node->content.cmd.redirs[1].type != 0
+ && node->content.cmd.redirs[0].specifier != NULL)
+ free(node->content.cmd.redirs[1].specifier);
}
diff --git a/src/free_token.c b/src/free_token.c
index 9f5c4e9..9b035ac 100644
--- a/src/free_token.c
+++ b/src/free_token.c
@@ -6,7 +6,7 @@
/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/27 14:38:57 by dkaiser #+# #+# */
-/* Updated: 2024/06/28 14:55:12 by dkaiser ### ########.fr */
+/* Updated: 2024/08/02 14:23:56 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
@@ -14,11 +14,28 @@
void free_token(t_token *token)
{
- if (token->type == STRING_TOKEN)
- free(token->content.string);
if (token->previous != NULL)
token->previous->next = NULL;
if (token->next != NULL)
token->next->previous = NULL;
free(token);
}
+
+void free_token_and_connect(t_token *token)
+{
+ if (token->previous != NULL)
+ token->previous->next = token->next;
+ if (token->next != NULL)
+ token->next->previous = token->previous;
+ free(token);
+}
+
+void free_tokens(t_token *tokens)
+{
+ while (tokens->next != NULL)
+ {
+ tokens = tokens->next;
+ free_token(tokens->previous);
+ }
+ free_token(tokens);
+}
diff --git a/src/new_node.c b/src/new_node.c
index 4cdbf9a..c58d291 100644
--- a/src/new_node.c
+++ b/src/new_node.c
@@ -6,7 +6,7 @@
/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/27 11:21:03 by dkaiser #+# #+# */
-/* Updated: 2024/06/28 15:04:15 by dkaiser ### ########.fr */
+/* Updated: 2024/09/17 18:46:35 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
@@ -23,22 +23,12 @@ t_node *new_node(int type)
return (node);
}
-t_node *new_assign_node(char *var, char *value)
-{
- t_node *node;
-
- node = new_node(ASSIGN_NODE);
- if (node == NULL)
- return (NULL);
- node->content.assign.var = var;
- node->content.assign.value = value;
- return (node);
-}
-
t_node *new_pipe_node(t_node *left, t_node *right)
{
t_node *node;
+ if (left == NULL || right == NULL)
+ return (NULL);
node = new_node(PIPE_NODE);
if (node == NULL)
return (NULL);
@@ -55,9 +45,14 @@ t_node *new_cmd_node(char **args, t_redirection redirs[2])
if (node == NULL)
return (NULL);
node->content.cmd.args = args;
- node->content.cmd.redirs[0] = redirs[0];
- node->content.cmd.redirs[1] = redirs[1];
- return (node);
+ if (redirs != NULL)
+ {
+ node->content.cmd.redirs[0] = redirs[0];
+ node->content.cmd.redirs[1] = redirs[1];
+ free(redirs);
+ return (node);
+ }
+ return (NULL);
}
t_node *new_string_node(char *string)
diff --git a/src/parse_cmd.c b/src/parse_cmd.c
new file mode 100644
index 0000000..2755cae
--- /dev/null
+++ b/src/parse_cmd.c
@@ -0,0 +1,52 @@
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* parse_cmd.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/07/08 15:06:25 by dkaiser #+# #+# */
+/* Updated: 2024/08/11 12:20:06 by dkaiser ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "minishell.h"
+
+static char **collect_args(t_token **tokens);
+
+t_node *parse_cmd(t_token *tokens)
+{
+ char **args;
+ t_redirection *redirs;
+
+ redirs = collect_redirs(&tokens);
+ args = collect_args(&tokens);
+ return (new_cmd_node(args, redirs));
+}
+
+static char **collect_args(t_token **tokens)
+{
+ t_token *cur;
+ char **result;
+ int i;
+
+ cur = *tokens;
+ i = 0;
+ while (cur != NULL && ++i)
+ cur = cur->next;
+ result = malloc(sizeof(char *) * (i + 1));
+ if (result == NULL)
+ return (free_tokens(*tokens), NULL);
+ cur = *tokens;
+ i = 0;
+ while (cur != NULL && cur->type == STRING_TOKEN)
+ {
+ if (cur->previous)
+ free_token(cur->previous);
+ result[i] = cur->content.string;
+ i++;
+ cur = cur->next;
+ }
+ result[i] = NULL;
+ return (result);
+}
diff --git a/src/parser.c b/src/parser.c
new file mode 100644
index 0000000..06c1df7
--- /dev/null
+++ b/src/parser.c
@@ -0,0 +1,84 @@
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* parser.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/06/29 15:53:29 by dkaiser #+# #+# */
+/* Updated: 2024/09/17 19:03:48 by dkaiser ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "libft.h"
+#include "minishell.h"
+#include "token.h"
+
+static t_token *find_token_by_type(t_token *tokens, int type);
+t_token *split_at_first(t_token **tokens, int type);
+static t_node *parse_statement(t_token *tokens);
+
+t_list *parse(t_token *tokens)
+{
+ t_node *result;
+
+ if ((*tokens).type == PIPE_TOKEN)
+ result = NULL;
+ else
+ result = parse_statement(tokens);
+ if (result == NULL)
+ printf("Parsing error.\n");
+ return (ft_lstnew(result));
+}
+
+static t_node *parse_statement(t_token *tokens)
+{
+ t_token *left_side_tokens;
+
+ left_side_tokens = split_at_first(&tokens, PIPE_TOKEN);
+ if (left_side_tokens == NULL)
+ {
+ free_tokens(tokens);
+ return (NULL);
+ }
+ else if (tokens != NULL)
+ {
+ return (new_pipe_node(parse_cmd(left_side_tokens),
+ parse_statement(tokens)));
+ }
+ else
+ {
+ return (parse_cmd(left_side_tokens));
+ }
+}
+
+t_token *split_at_first(t_token **tokens, int type)
+{
+ t_token *split;
+ t_token *result;
+
+ split = find_token_by_type(*tokens, type);
+ if (split == NULL)
+ {
+ result = *tokens;
+ *tokens = NULL;
+ return (result);
+ }
+ result = *tokens;
+ *tokens = split->next;
+ if (result == split)
+ result = NULL;
+ free_token(split);
+ return (result);
+}
+
+static t_token *find_token_by_type(t_token *tokens, int type)
+{
+ while (tokens != NULL)
+ {
+ if (tokens->type == type)
+ return (tokens);
+ tokens = tokens->next;
+ }
+ return (NULL);
+}
diff --git a/src/print_ast.c b/src/print_ast.c
new file mode 100644
index 0000000..d42a67d
--- /dev/null
+++ b/src/print_ast.c
@@ -0,0 +1,59 @@
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* print_ast.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/07/22 15:16:53 by dkaiser #+# #+# */
+/* Updated: 2024/09/17 15:09:04 by dkaiser ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "minishell.h"
+
+static void print_ast_rec(t_node *ast, int indent);
+static void print_cmd_node(t_node *ast, int indent);
+
+void print_ast(t_node *ast)
+{
+ if (DEBUG)
+ {
+ printf("\e[94m[AST]\n");
+ print_ast_rec(ast, 0);
+ printf("\e[0m\n");
+ }
+}
+
+static void print_ast_rec(t_node *ast, int indent)
+{
+ if (!ast)
+ panic("Can't print AST!");
+ else if (ast->type == CMD_NODE)
+ print_cmd_node(ast, indent);
+ else if (ast->type == PIPE_NODE)
+ {
+ printf("\n%*s%s", indent, "", "* PIPE");
+ print_ast_rec(ast->content.pipe.left, indent + 2);
+ print_ast_rec(ast->content.pipe.right, indent + 2);
+ }
+}
+
+static void print_cmd_node(t_node *ast, int indent)
+{
+ int i;
+
+ printf("\n%*s%s", indent, "", "* CMD");
+ i = 0;
+ printf("\n%*sARGS:", indent + 2, "");
+ while (ast->content.cmd.args != NULL && ast->content.cmd.args[i] != NULL)
+ {
+ printf(" '%s'", ast->content.cmd.args[i]);
+ i++;
+ }
+ printf("\n%*sREDIRS:", indent + 2, "");
+ printf("\n%*sIN: %d %s", indent + 4, "", ast->content.cmd.redirs[0].type,
+ ast->content.cmd.redirs[0].specifier);
+ printf("\n%*sOUT: %d %s", indent + 4, "", ast->content.cmd.redirs[1].type,
+ ast->content.cmd.redirs[1].specifier);
+}
diff --git a/src/repl.c b/src/repl.c
index fe9faf3..d590fec 100644
--- a/src/repl.c
+++ b/src/repl.c
@@ -6,7 +6,7 @@
/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/24 16:07:04 by dkaiser #+# #+# */
-/* Updated: 2024/08/11 14:41:29 by chuhlig ### ########.fr */
+/* Updated: 2024/09/13 16:26:35 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
@@ -17,24 +17,21 @@ void repl(const char *prompt)
{
char *input;
t_token *token_list;
- t_token *current;
- t_token *next;
+ t_list *lines;
while (1)
{
input = readline(prompt);
if (input == NULL)
return ;
+ if (input[0] == '\0')
+ continue ;
add_history(input);
token_list = NULL;
- current = token_list;
tokenizer(input, &token_list, '\0');
- while (current != NULL)
- {
- next = current->next;
- free_token(current);
- current = next;
- }
+ lines = parse(token_list);
+ if (lines)
+ print_ast(lines->content);
free(input);
}
}
diff --git a/src/tokenizer.c b/src/tokenizer.c
index a9a86ca..ab8a6ac 100644
--- a/src/tokenizer.c
+++ b/src/tokenizer.c
@@ -6,7 +6,7 @@
/* By: chuhlig <chuhlig@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/06/28 20:55:50 by chuhlig #+# #+# */
-/* Updated: 2024/08/11 14:52:54 by chuhlig ### ########.fr */
+/* Updated: 2024/08/29 15:26:55 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
@@ -111,4 +111,6 @@ void tokenizer(char *s, t_token **token_list, char quote_check)
pos = i + 1;
}
}
+ while ((*token_list)->previous)
+ *token_list = (*token_list)->previous;
}