mirror of
https://codeberg.org/la-chouette/minishell.git
synced 2025-12-06 07:28:09 +01:00
cmdgroup parsing: parse cmdlist surrounded by parentheses
This commit is contained in:
parent
185a069044
commit
0fbfee7d78
7 changed files with 169 additions and 5 deletions
3
Makefile
3
Makefile
|
|
@ -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 \
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
paren = match_paren(builder.current_word->word);
|
||||||
|
if (paren == PAREN_INVALID)
|
||||||
cmdgroup_builder_next_word(&builder, &words);
|
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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
23
src/parser/cmdgroup/paren.c
Normal file
23
src/parser/cmdgroup/paren.c
Normal 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);
|
||||||
|
}
|
||||||
25
src/parser/cmdgroup/paren.h
Normal file
25
src/parser/cmdgroup/paren.h
Normal 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
71
test.sh
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue