MiniDevil As beautiful as a shell
parser_redir.c
Go to the documentation of this file.
1 /* ************************************************************************** */
2 /* */
3 /* ::: :::::::: */
4 /* parser_redir.c :+: :+: :+: */
5 /* +:+ +:+ +:+ */
6 /* By: baelgadi <baelgadi@student.42.fr> +#+ +:+ +#+ */
7 /* +#+#+#+#+#+ +#+ */
8 /* Created: 2025/12/10 20:11:44 by zotaj-di #+# #+# */
9 /* Updated: 2026/03/04 09:00:07 by baelgadi ### ########.fr */
10 /* */
11 /* ************************************************************************** */
12 
13 #include "parser.h"
14 #include "ast.h"
15 #include "libft.h"
16 
24 {
25  if (type == TOKEN_REDIR_IN)
26  return (NODE_REDIR_IN);
27  if (type == TOKEN_REDIR_OUT)
28  return (NODE_REDIR_OUT);
29  if (type == TOKEN_APPEND)
30  return (NODE_REDIR_APPEND);
31  if (type == TOKEN_HEREDOC)
32  return (NODE_REDIR_HEREDOC);
33  return (NODE_COMMAND);
34 }
35 
44 static t_ast *parse_one_redirection(t_token **tokens, t_ast *cmd)
45 {
46  t_node_type type;
47  char *file;
48  int quoted;
49  t_ast *node;
50 
51  type = get_redir_node_type((*tokens)->type);
52  *tokens = (*tokens)->next;
53  if (!*tokens || (*tokens)->type != TOKEN_WORD)
54  {
55  free_ast(cmd);
56  return (NULL);
57  }
58  file = join_connected_delim(tokens, &quoted);
59  if (!file)
60  {
61  free_ast(cmd);
62  return (NULL);
63  }
64  node = create_redir_node(type, file, cmd, quoted);
65  if (!node)
66  free(file);
67  return (node);
68 }
69 
80 static void collect_and_merge_remaining_args(t_ast *cmd, t_token **tokens)
81 {
82  char **new_args;
83  char **merged;
84  int new_argc;
85  int i;
86 
87  new_args = collect_args(tokens, &new_argc);
88  if (!new_args)
89  return ;
90  merged = malloc(sizeof(char *) * (cmd->data.cmd.argc + new_argc + 1));
91  if (!merged)
92  {
93  ft_free_strarray(new_args);
94  return ;
95  }
96  i = -1;
97  while (++i < cmd->data.cmd.argc)
98  merged[i] = cmd->data.cmd.args[i];
99  i = -1;
100  while (++i < new_argc)
101  merged[cmd->data.cmd.argc + i] = new_args[i];
102  merged[cmd->data.cmd.argc + new_argc] = NULL;
103  free(cmd->data.cmd.args);
104  free(new_args);
105  cmd->data.cmd.args = merged;
106  cmd->data.cmd.argc += new_argc;
107 }
108 
116 {
117  while (node && node->type >= NODE_REDIR_IN
118  && node->type <= NODE_REDIR_HEREDOC)
119  node = node->data.redir.cmd;
120  return (node);
121 }
122 
135 {
136  t_ast *cmd;
137  t_ast *cmd_node;
138 
139  if (!tokens || !*tokens)
140  return (NULL);
141  cmd = parse_simple_command(tokens);
142  while (*tokens && is_redirection((*tokens)->type))
143  {
144  cmd = parse_one_redirection(tokens, cmd);
145  if (!cmd)
146  return (NULL);
147  cmd_node = get_command_node(cmd);
148  if (cmd_node)
149  collect_and_merge_remaining_args(cmd_node, tokens);
150  }
151  return (reverse_redir_chain(cmd));
152 }
t_ast * create_redir_node(t_node_type type, char *file, t_ast *cmd, int quoted)
Create a redirection AST node.
Definition: ast.c:71
AST node creation and destruction prototypes.
void free_ast(t_ast *node)
Recursively free an entire AST tree.
Definition: ast_utils.c:46
Parser entry point & sub parser prototypes.
t_ast * parse_simple_command(t_token **tokens)
Parse a simple command from consecutive word tokens.
Definition: parser_cmd.c:117
char ** collect_args(t_token **tokens, int *argc)
Collect consecutive word tokens into an arguments array.
Definition: parser_cmd.c:88
int is_redirection(t_token_type type)
Check if a token type is a redirection operator.
static t_ast * get_command_node(t_ast *node)
Extract the innermost command from a redirection chain.
Definition: parser_redir.c:115
static void collect_and_merge_remaining_args(t_ast *cmd, t_token **tokens)
Collect trailing WORD tokens and merge them into a command's args.
Definition: parser_redir.c:80
static t_ast * parse_one_redirection(t_token **tokens, t_ast *cmd)
Parse a single redirection token and the following WORD (filename)
Definition: parser_redir.c:44
t_ast * parse_command(t_token **tokens)
Parse a command with all its redirections.
Definition: parser_redir.c:134
static t_node_type get_redir_node_type(t_token_type type)
Convert a token type to the corresponding AST redirection node type.
Definition: parser_redir.c:23
char * join_connected_delim(t_token **tokens, int *quoted)
Join connected tokens in a single string.
t_ast * reverse_redir_chain(t_ast *node)
Reverse a redirection chain for left to right execution order.
t_token_type
Token types produced by Lexer.
Definition: structs.h:24
@ TOKEN_REDIR_OUT
Definition: structs.h:28
@ TOKEN_WORD
Definition: structs.h:25
@ TOKEN_HEREDOC
Definition: structs.h:30
@ TOKEN_REDIR_IN
Definition: structs.h:27
@ TOKEN_APPEND
Definition: structs.h:29
t_node_type
AST node types.
Definition: structs.h:51
@ NODE_REDIR_HEREDOC
Definition: structs.h:57
@ NODE_REDIR_APPEND
Definition: structs.h:56
@ NODE_COMMAND
Definition: structs.h:52
@ NODE_REDIR_OUT
Definition: structs.h:55
@ NODE_REDIR_IN
Definition: structs.h:54
AST node (union based ↑)
Definition: structs.h:151
t_ast_data data
cmd, redir or binary data
Definition: structs.h:153
t_node_type type
To determine which union member to pick.
Definition: structs.h:152
char ** args
NULL terminated args array.
Definition: structs.h:103
int argc
Number of arguments.
Definition: structs.h:104
struct s_ast * cmd
Command subtree.
Definition: structs.h:113
Lexer token (singly linked list)
Definition: structs.h:71
t_token_type type
Token type (word, pipe, redir)
Definition: structs.h:72
struct s_token * next
Next token.
Definition: structs.h:76
t_cmd_node cmd
Definition: structs.h:141
t_redir_node redir
Definition: structs.h:142