cmdgroup parsing: parse cmdlist surrounded by parentheses

This commit is contained in:
Khaïs COLIN 2025-03-20 12:17:54 +01:00
parent 185a069044
commit 0fbfee7d78
Signed by: logistic-bot
SSH key fingerprint: SHA256:RlpiqKeXpcPFZZ4y9Ou4xi2M8OhRJovIwDlbCaMsuAo
7 changed files with 169 additions and 5 deletions

View file

@ -30,8 +30,9 @@ srcs = \
src/executing/here_doc/strip_newline.c \ src/executing/here_doc/strip_newline.c \
src/ft_errno.c \ src/ft_errno.c \
src/get_command.c \ src/get_command.c \
src/parser/cmdgroup/cmdgroup_builder.c \
src/parser/cmdgroup/cmdgroup.c \ src/parser/cmdgroup/cmdgroup.c \
src/parser/cmdgroup/cmdgroup_builder.c \
src/parser/cmdgroup/paren.c \
src/parser/cmdlist/cmdlist.c \ src/parser/cmdlist/cmdlist.c \
src/parser/cmdlist/cmdlist_builder.c \ src/parser/cmdlist/cmdlist_builder.c \
src/parser/cmdlist/cmdlist_debug.c \ src/parser/cmdlist/cmdlist_debug.c \

View file

@ -6,7 +6,7 @@
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */ /* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/03/11 15:18:02 by khais #+# #+# */ /* Created: 2025/03/11 15:18:02 by khais #+# #+# */
/* Updated: 2025/03/20 12:27:57 by khais ### ########.fr */ /* Updated: 2025/03/20 14:46:25 by khais ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -14,14 +14,25 @@
#include "cmdgroup_builder.h" #include "cmdgroup_builder.h"
#include <stdlib.h> #include <stdlib.h>
#include "libft.h" #include "libft.h"
#include "paren.h"
#include "../../treedrawing.h" #include "../../treedrawing.h"
#include "../../postprocess/redirections/redirection_list.h" #include "../../postprocess/redirections/redirection_list.h"
#include "libft/libft.h" #include "libft/libft.h"
/*
** Recursively parse a cmdgroup
**
** This is responsible for parsing one optional set of parentheses surrounding a
** cmdlist.
**
** If parentheses are present, also parse redirections, which may only occur
** after the closing parenthesis.
*/
t_cmdgroup *cmdgroup_from_wordlist(t_wordlist *wordlist) t_cmdgroup *cmdgroup_from_wordlist(t_wordlist *wordlist)
{ {
t_cmdgroup_builder builder; t_cmdgroup_builder builder;
t_wordlist *words; t_wordlist *words;
t_paren paren;
words = wordlist_copy(wordlist); words = wordlist_copy(wordlist);
if (words == NULL) if (words == NULL)
@ -30,7 +41,11 @@ t_cmdgroup *cmdgroup_from_wordlist(t_wordlist *wordlist)
return (wordlist_destroy(words), NULL); return (wordlist_destroy(words), NULL);
while (builder.error == false && builder.current_word != NULL) while (builder.error == false && builder.current_word != NULL)
{ {
cmdgroup_builder_next_word(&builder, &words); paren = match_paren(builder.current_word->word);
if (paren == PAREN_INVALID)
cmdgroup_builder_next_word(&builder, &words);
else
cmdgroup_builder_paren(&builder, &words, paren);
} }
if (builder.current_wordlist != NULL) if (builder.current_wordlist != NULL)
cmdgroup_builder_delimit(&builder, &words); cmdgroup_builder_delimit(&builder, &words);

View file

@ -6,7 +6,7 @@
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */ /* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/03/20 12:32:14 by khais #+# #+# */ /* Created: 2025/03/20 12:32:14 by khais #+# #+# */
/* Updated: 2025/03/20 12:49:37 by khais ### ########.fr */ /* Updated: 2025/03/20 17:19:55 by khais ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -51,3 +51,23 @@ void cmdgroup_builder_delimit(t_cmdgroup_builder *builder,
builder->current_wordlist = NULL; builder->current_wordlist = NULL;
(void)words; (void)words;
} }
/*
** discard the current word
*/
void cmdgroup_builder_discard_word(t_cmdgroup_builder *builder,
t_wordlist **words)
{
worddesc_destroy(builder->current_word);
builder->current_word = wordlist_pop(words);
}
/*
** Handle encountering a parenthesis token
*/
void cmdgroup_builder_paren(t_cmdgroup_builder *builder,
t_wordlist **words, t_paren paren)
{
cmdgroup_builder_discard_word(builder, words);
(void)paren;
}

View file

@ -6,7 +6,7 @@
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */ /* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/03/20 12:27:20 by khais #+# #+# */ /* Created: 2025/03/20 12:27:20 by khais #+# #+# */
/* Updated: 2025/03/20 12:50:09 by khais ### ########.fr */ /* Updated: 2025/03/20 17:12:52 by khais ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -15,6 +15,7 @@
# include "../wordlist/wordlist.h" # include "../wordlist/wordlist.h"
# include "cmdgroup.h" # include "cmdgroup.h"
# include "paren.h"
typedef struct s_cmdgroup_builder typedef struct s_cmdgroup_builder
{ {
@ -34,6 +35,12 @@ typedef struct s_cmdgroup_builder
** cmdgroup that is being constructed ** cmdgroup that is being constructed
*/ */
t_cmdgroup *cmdgroup; t_cmdgroup *cmdgroup;
/*
** count of parenthesis tokens
**
** +1 for each opening parenthesis, -1 for each closing
*/
int paren;
} t_cmdgroup_builder; } t_cmdgroup_builder;
t_cmdgroup_builder *setup_cmdgroup_builder(t_cmdgroup_builder *builder, t_cmdgroup_builder *setup_cmdgroup_builder(t_cmdgroup_builder *builder,
@ -42,5 +49,7 @@ void cmdgroup_builder_next_word(t_cmdgroup_builder *builder,
t_wordlist **words); t_wordlist **words);
void cmdgroup_builder_delimit(t_cmdgroup_builder *builder, void cmdgroup_builder_delimit(t_cmdgroup_builder *builder,
t_wordlist **words); t_wordlist **words);
void cmdgroup_builder_paren(t_cmdgroup_builder *builder,
t_wordlist **words, t_paren paren);
#endif // CMDGROUP_BUILDER_H #endif // CMDGROUP_BUILDER_H

View file

@ -0,0 +1,23 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* paren.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/03/20 14:48:55 by khais #+# #+# */
/* Updated: 2025/03/20 14:49:46 by khais ### ########.fr */
/* */
/* ************************************************************************** */
#include "paren.h"
#include "libft.h"
t_paren match_paren(char *word)
{
if (ft_strcmp("(", word) == 0)
return (PAREN_OPEN);
if (ft_strcmp(")", word) == 0)
return (PAREN_CLOSE);
return (PAREN_INVALID);
}

View file

@ -0,0 +1,25 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* paren.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/03/20 14:45:48 by khais #+# #+# */
/* Updated: 2025/03/20 14:48:00 by khais ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef PAREN_H
# define PAREN_H
typedef enum e_paren
{
PAREN_INVALID,
PAREN_OPEN,
PAREN_CLOSE,
} t_paren;
t_paren match_paren(char *word);
#endif // PAREN_H

71
test.sh
View file

@ -192,4 +192,75 @@ expecting <<EOF
╰─ (no redirections) ╰─ (no redirections)
EOF EOF
when_run <<EOF "a single command in parentheses is has the parenthesis implicitly removed"
(echo hi)
EOF
# this is how it is handled in bash:
# doing a `ps uf` on bash running `sleep 10`
# \_ bash --norc
# \_ sleep 10
# and `(sleep 10)`
# \_ bash --norc
# \_ sleep 10
# this is exactly the same process graph
expecting <<EOF
╰─ t_cmdgroup
├─ t_cmdlist
│ ├─ num_cmds = 1
│ ╰─ cmd[0]
│ ├─ t_cmdlist_item
│ │ ╰─ t_pipeline
│ │ ├─ num_cmd = 1
│ │ ╰─ cmd[0]
│ │ ╰─ t_simple_cmd
│ │ ├─ words = [echo][hi]
│ │ ╰─ (no redirections)
│ ╰─ t_operator = END
╰─ (no redirections)
EOF
when_run <<EOF "a single cmdlist in parenthesis has the parenthesis implicitly removed"
(echo hi >> append | echo < infile bye && echo hello > outfile)
EOF
expecting <<EOF
╰─ t_cmdgroup
├─ t_cmdlist
│ ├─ num_cmds = 2
│ ├─ cmd[0]
│ │ ├─ t_cmdlist_item
│ │ │ ╰─ t_pipeline
│ │ │ ├─ num_cmd = 2
│ │ │ ├─ cmd[0]
│ │ │ │ ╰─ t_simple_cmd
│ │ │ │ ├─ words = [echo][hi]
│ │ │ │ ╰─ t_redir_list
│ │ │ │ ╰─ redirection[0]
│ │ │ │ ╰─ t_redirection
│ │ │ │ ├─ t_redir_type = REDIR_APPEND
│ │ │ │ ╰─ marker = [append]
│ │ │ ╰─ cmd[1]
│ │ │ ╰─ t_simple_cmd
│ │ │ ├─ words = [echo][bye]
│ │ │ ╰─ t_redir_list
│ │ │ ╰─ redirection[0]
│ │ │ ╰─ t_redirection
│ │ │ ├─ t_redir_type = REDIR_INPUT
│ │ │ ╰─ marker = [infile]
│ │ ╰─ t_operator = AND
│ ╰─ cmd[1]
│ ├─ t_cmdlist_item
│ │ ╰─ t_pipeline
│ │ ├─ num_cmd = 1
│ │ ╰─ cmd[0]
│ │ ╰─ t_simple_cmd
│ │ ├─ words = [echo][hello]
│ │ ╰─ t_redir_list
│ │ ╰─ redirection[0]
│ │ ╰─ t_redirection
│ │ ├─ t_redir_type = REDIR_OUTPUT
│ │ ╰─ marker = [outfile]
│ ╰─ t_operator = END
╰─ (no redirections)
EOF
finalize finalize