From 09da92f1524cd2c943512a4bc3b218e1f786f844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Luttringer?= Date: Fri, 18 Aug 2006 14:03:40 +0000 Subject: [PATCH] travail renaison --- GRAMMAR | 6 +- src/Makefile.am | 12 ++ src/ast/ast.h | 425 ++++++++++++++++++++++------------------- src/ast/ast_and.c | 34 ++++ src/ast/ast_bang.c | 34 ++++ src/ast/ast_case.c | 64 +++++++ src/ast/ast_for.c | 40 ++++ src/ast/ast_funcdec.c | 34 ++++ src/ast/ast_if.c | 38 ++++ src/ast/ast_or.c | 35 ++++ src/ast/ast_pipe.c | 35 ++++ src/ast/ast_sep.c | 15 +- src/ast/ast_sepand.c | 35 ++++ src/ast/ast_subshell.c | 34 ++++ src/ast/ast_until.c | 34 ++++ src/ast/ast_while.c | 34 ++++ src/common/strndup.c | 4 +- src/parser/lexer.c | 120 +++++++++--- src/parser/parser.c | 39 ++-- src/parser/parser.h | 89 +++++---- 20 files changed, 869 insertions(+), 292 deletions(-) create mode 100644 src/ast/ast_and.c create mode 100644 src/ast/ast_bang.c create mode 100644 src/ast/ast_case.c create mode 100644 src/ast/ast_for.c create mode 100644 src/ast/ast_funcdec.c create mode 100644 src/ast/ast_if.c create mode 100644 src/ast/ast_or.c create mode 100644 src/ast/ast_pipe.c create mode 100644 src/ast/ast_sepand.c create mode 100644 src/ast/ast_subshell.c create mode 100644 src/ast/ast_until.c create mode 100644 src/ast/ast_while.c diff --git a/GRAMMAR b/GRAMMAR index ba0cea9..eec3387 100644 --- a/GRAMMAR +++ b/GRAMMAR @@ -5,7 +5,7 @@ input: list '\n' list: and_or ((';'|'&') and_or)* ['&'|';'] -and_or: pipeline (('&&'|'||') ('\n')* pipeline)* +and_or: pipeline (('&&'|'||') ('\n')* pipeline)* pipeline: ['!'] command ('|' ('\n')* command)* @@ -58,7 +58,7 @@ else_clause: 'else' compound_list do_group: 'do' compound_list 'done' -case_clause: pattern (';;' (\n)* pattern)* [;;] +case_clause: case_item (';;' (\n)* case_item)* [;;] -pattern: ['('] WORD ('|' WORD)* ')' ( ('\n')* | compound_list ) +case_item: ['('] WORD ('|' WORD)* ')' ( ('\n')* | compound_list ) diff --git a/src/Makefile.am b/src/Makefile.am index c9f1298..859a64c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,8 +5,20 @@ bin_PROGRAMS=42sh 42sh_SOURCES= ast/ast.h \ + ast/ast_and.c \ + ast/ast_bang.c \ + ast/ast_case.c \ ast/ast_destruct.c \ + ast/ast_for.c \ + ast/ast_funcdec.c \ + ast/ast_if.c \ + ast/ast_or.c \ + ast/ast_pipe.c \ ast/ast_sep.c \ + ast/ast_sepand.c \ + ast/ast_subshell.c \ + ast/ast_until.c \ + ast/ast_while.c \ common/common.h \ common/mem.h \ common/strmerge.c \ diff --git a/src/ast/ast.h b/src/ast/ast.h index 21d6e97..213687c 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -5,7 +5,7 @@ ** Login ** ** Started on Sun Jul 30 04:40:03 2006 Seblu -** Last update Thu Aug 3 03:03:42 2006 Seblu +** Last update Fri Aug 18 15:56:25 2006 Seblu */ #ifndef AST_H_ @@ -33,19 +33,29 @@ typedef struct s_if_node */ typedef struct s_for_node { - char *name; - ts_ast_node *values; + char *varname; + char **values; ts_ast_node *exec; } ts_for_node; +/* +** Case item (not an ast node) +*/ +typedef struct s_case_item ts_case_item; +struct s_case_item +{ + char **pattern; + ts_ast_node *list; + ts_case_item *next; +}; + /* ** Case ast node */ typedef struct s_case_node { char *word; - //FIXME - struct s_case_item **items; + ts_case_item *items; } ts_case_node; /* @@ -105,14 +115,6 @@ typedef struct s_bin_node ts_ast_node *rhs; } ts_bin_node; -/* -** Subshell ast node -*/ -typedef struct s_subshell_node -{ - ts_ast_node *head; -} ts_subshell_node; - /* ** Funcdec node */ @@ -138,18 +140,9 @@ typedef enum e_node_type T_FUNCDEC, T_BANG, T_PIPE, - T_SEP_AND, + T_SEPAND, T_SEP, T_CASE, - - T_CASE_LIST, - T_LIST, - T_CL, - T_CASE_ITEM, - T_ITEM, - T_LINE, - T_WL, - T_END } te_node_type; /* @@ -159,23 +152,18 @@ typedef union u_node_item { ts_if_node child_if; ts_for_node child_for; - ts_case_node child_case; + ts_case_node child_case; //todo ts_while_node child_while; ts_while_node child_until; - ts_cmd_node child_cmd; + ts_cmd_node child_cmd; //todo ts_bin_node child_and; ts_bin_node child_or; - ts_subshell_node child_subshell; + ts_bin_node child_subshell; ts_funcdec_node child_funcdec; ts_bin_node child_bang; ts_bin_node child_pipe; ts_bin_node child_sep; - ts_bin_node child_sep_and; - - -/* ts_case_item node_case_item; */ -/* ts_wordlist node_wl; */ -/* ts_case_list node_case_list; */ + ts_bin_node child_sepand; } tu_node_item; /* @@ -187,172 +175,221 @@ struct s_ast tu_node_item body; }; - +/*! +** Destroy node and all its childs +** +** @param ast mother node to destroy +** +*/ void ast_destruct(ts_ast_node *ast); +/*! +** Create an if ast node +** +** @param cond if condition +** @param cond_true tree if condition is true +** @param cond_false tree if condition is false +** +** @return the node +*/ +ts_ast_node *ast_create_if(ts_ast_node *cond, + ts_ast_node *cond_true, + ts_ast_node *cond_false); + +/*! +** Destruct an if ast node +** +** @param node node to destroy +*/ +void ast_destruct_if(ts_ast_node *node); + +/*! +** Create a for ast node +** +** @param varname variable name +** @param values word list that var @value varname will take. +** @warning values is a NULL termined list of string +** @param exec tree to execute with @value varname correctly set +** +** @return the node +*/ +ts_ast_node *ast_create_for(char *varname, + char **values, + ts_ast_node *exec); + +/*! +** Destruct a for ast node +** +** @param node node to destroy +*/ +void ast_destruct_for(ts_ast_node *node); + +/*! +** Create a while ast node +** +** @param cond poursuit condition +** @param exec tree to execute if cond is true +** +** @return the node +*/ +ts_ast_node *ast_create_while(ts_ast_node *cond, ts_ast_node *exec); + +/*! +** Destruct a while ast node +** +** @param node node to destroy +*/ +void ast_destruct_while(ts_ast_node *node); + +/*! +** Create a until ast node +** +** @param cond poursuit condition +** @param exec tree to execute if cond is false +** +** @return the node +*/ +ts_ast_node *ast_create_until(ts_ast_node *cond, ts_ast_node *exec); + +/*! +** Destruct a until ast node +** +** @param node node to destroy +*/ +void ast_destruct_until(ts_ast_node *node); + +/*! +** Create an and (&&) ast node +** +** @param lhs left child +** @param rhs right child +** +** @return the node +*/ +ts_ast_node *ast_create_and(ts_ast_node *lhs, ts_ast_node *rhs); + +/*! +** Destruct an and (&&) node +** +** @param node node to destroy +*/ +void ast_destruct_and(ts_ast_node *node); + +/*! +** Create an or (||) ast node +** +** @param lhs left child +** @param rhs right child +** +** @return the node +*/ +ts_ast_node *ast_create_or(ts_ast_node *lhs, ts_ast_node *rhs); + +/*! +** Destruct an or (||) node +** +** @param node node to destroy +*/ +void ast_destruct_or(ts_ast_node *node); + +/*! +** Create a subshell ($()) ast node +** +** @param child subshell tree +** +** @return the node +*/ +ts_ast_node *ast_create_subshell(ts_ast_node *child); + +/*! +** Destruct a subshell ($()) node +** +** @param node node to destroy +*/ +void ast_destruct_subshell(ts_ast_node *node); + +/*! +** Create a funcdec (function declaration) ast node +** +** @param name function name +** @param body function body +** +** @return the node +*/ +ts_ast_node *ast_create_funcdec(char *name, ts_ast_node *body); + +/*! +** Destruct a funcdec ast node +** +** @param node node to destroy +*/ +void ast_destruct_funcdec(ts_ast_node *node); + +/*! +** Create a bang (!) ast node +** +** @param child under bang tree +** +** @return the node +*/ +ts_ast_node *ast_create_bang(ts_ast_node *child); + +/*! +** Destruct a bang (!) node +** +** @param node node to destroy +*/ +void ast_destruct_bang(ts_ast_node *node); + +/*! +** Create a pipe (|) ast node +** +** @param lhs left child +** @param rhs right child +** +** @return the node +*/ +ts_ast_node *ast_create_pipe(ts_ast_node *lhs, ts_ast_node *rhs); + +/*! +** Destruct a pipe (|) node +** +** @param node node to destroy +*/ +void ast_destruct_pipe(ts_ast_node *node); + +/*! +** Create a separtor (;) ast node +** +** @param lhs left child +** @param rhs right child +** +** @return the node +*/ ts_ast_node *ast_create_sep(ts_ast_node *lhs, ts_ast_node *rhs); + +/*! +** Destruct a sep (;) node +** +** @param node node to destroy +*/ void ast_destruct_sep(ts_ast_node *node); -/* /\** */ -/* ** structure wordlist ex : for var in wordlist do */ -/* ** word : word */ -/* ** next : next word finally Sexy NULL */ -/* *\/ */ -/* struct s_wordlist */ -/* { */ -/* char *word; */ -/* struct s_wordlist *next; */ -/* }; */ - -/* struct s_case_item */ -/* { */ -/* char **patterns; */ -/* int allocated; */ -/* int pos; */ -/* }; */ - -/* struct s_item */ -/* { */ -/* struct s_wordlist *pl; */ -/* struct s_ast *cmd_list; */ -/* }; */ - - - -/* /\** */ -/* ** temporary structure */ -/* ** which contains prefix and */ -/* ** suffix command informations */ -/* ** argv word or assigment words terminated by NULL */ -/* ** redirs redirection pointer */ -/* ** pos position in argv array */ -/* ** nb_arg_alloc positions allocated */ -/* *\/ */ -/* struct s_cmd_opt */ -/* { */ -/* char **argv; */ -/* struct s_redir *redirs; */ -/* int pos; */ -/* int nb_arg_alloc; */ -/* }; */ -/* /\** */ -/* ** create temporary structure */ -/* ** in order to get prefix and */ -/* ** suffix informations */ -/* *\/ */ -/* struct s_cmd_opt *tmp_create_cmdopt(struct s_cmd_opt *opt, */ -/* struct s_redir *redir, */ -/* char *arg); */ -/* /\** */ -/* ** add redirection to temporary */ -/* ** structure s_redir */ -/* *\/ */ -/* struct s_redir *tmp_add_redir(struct s_redir *base, struct s_redir *nelt); */ -/* /\** */ -/* ** create temporary structure s_redir */ -/* *\/ */ -/* struct s_redir *tmp_create_redir(enum e_redir type, */ -/* char *filename, */ -/* int fd, */ -/* struct s_redir *redir); */ -/* /\* */ -/* ** PLEASE NOTE */ -/* ** Every time, any argument given so this functions must be on the heap, */ -/* ** they are not copied. Don't forget to dup string, for function create_cmd, */ -/* ** function add_redir and function create_for */ -/* *\/ */ - -/* /\*! */ -/* ** Create an and node */ -/* ** */ -/* ** @param lhs left hand side */ -/* ** @param rhs right hand side */ -/* ** */ -/* ** @return new ast node */ -/* *\/ */ -/* struct s_ast *ast_create_and(struct s_ast *lhs, struct s_ast *rhs); */ -/* /\*! */ -/* ** Create an or node */ -/* ** */ -/* ** @param lhs left hand side */ -/* ** @param rhs right hand side */ -/* ** */ -/* ** @return new ast node */ -/* *\/ */ -/* struct s_ast *ast_create_or(struct s_ast *lhs, struct s_ast *rhs); */ -/* struct s_ast *ast_create_case_clause(char *word, */ -/* struct s_ast *case_list); */ -/* struct s_ast *ast_create_if(struct s_ast *cond, */ -/* struct s_ast *positive, */ -/* struct s_ast *negative); */ -/* struct s_ast *ast_create_funcdec(char *name, struct s_ast *body); */ -/* struct s_ast *ast_create_subshell(struct s_ast *cmd); */ -/* struct s_ast *ast_create_for(char *varname, */ -/* struct s_ast *value, */ -/* struct s_ast *exec); */ -/* /\** */ -/* ** create cmd node */ -/* *\/ */ -/* struct s_ast *ast_create_cmd(struct s_cmd_opt *prefix, */ -/* char *cmd, */ -/* struct s_cmd_opt *suffix); */ - -/* /\* struct s_ast *ast_create_list(struct s_ast **item); *\/ */ -/* struct s_ast *ast_create_until(struct s_ast *cond, */ -/* struct s_ast *exec); */ -/* struct s_ast *ast_create_while(struct s_ast *cond, */ -/* struct s_ast *exec); */ -/* /\** */ -/* ** create pipe node */ -/* *\/ */ -/* struct s_ast *ast_create_pipe(struct s_ast *cmd1, */ -/* struct s_ast *cmd2); */ -/* /\** */ -/* ** create shell structure */ -/* *\/ */ -/* struct s_42sh *ast_create_ast(struct s_42sh *shell, */ -/* struct s_ast *ast; */ - -/* struct s_ast *ast_create_patterns(char *word, struct s_ast *case_item); */ -/* struct s_ast *ast_create_case_list(struct s_ast *item, */ -/* struct s_ast *case_list); */ -/* struct s_ast *ast_create_wordlist(struct s_ast *wl, */ -/* char *w); */ -/* /\** */ -/* ** change ast type : PIPE -> BANG_PIPE and CMD -> BANG_CMD */ -/* *\/ */ -/* struct s_ast *ast_create_bang(struct s_ast *ast); */ -/* struct s_ast *ast_create_sep_op(struct s_ast *cmd1, */ -/* enum e_type sep_op, */ -/* struct s_ast *cmd2); */ - -/* /\* void ast_destruct_list(struct s_ast *node); *\/ */ -/* void ast_destruct_cmd(struct s_ast *node); */ -/* void ast_destruct_pipe(struct s_ast *node); */ -/* void ast_destruct_redir(struct s_redir *red); */ - -/* /\* void ast_print(struct s_ast *ast); *\/ */ -/* void ast_destruct_sep_op(struct s_ast *node); */ -/* void ast_destruct_for(struct s_ast *node); */ -/* void ast_destruct_until(struct s_ast *node); */ -/* void ast_destruct_while(struct s_ast *node); */ -/* void ast_destruct_if(struct s_ast *node); */ -/* void ast_destruct(struct s_ast *node); */ -/* void ast_destruct_bang(struct s_ast *node); */ -/* void ast_destruct_wordlist(struct s_ast *node); */ -/* void ast_destruct_case(struct s_ast *node); */ -/* /\*! */ -/* ** Destruct an and node */ -/* ** */ -/* ** @param node head of node to destruct */ -/* *\/ */ -/* void ast_destruct_and(struct s_ast *node); */ -/* /\*! */ -/* ** Destruct an or node */ -/* ** */ -/* ** @param node head of node to destruct */ -/* *\/ */ -/* void ast_destruct_or(struct s_ast *node); */ -/* void ast_destruct_subshell(struct s_ast *node); */ +/*! +** Create a sepand (&) ast node +** +** @param lhs left child +** @param rhs right child +** +** @return the node +*/ +ts_ast_node *ast_create_sepand(ts_ast_node *lhs, ts_ast_node *rhs); + +/*! +** Destruct a sepand (&) node +** +** @param node node to destroy +*/ +void ast_destruct_sep(ts_ast_node *node); #endif /* !AST_H_ */ diff --git a/src/ast/ast_and.c b/src/ast/ast_and.c new file mode 100644 index 0000000..f63478c --- /dev/null +++ b/src/ast/ast_and.c @@ -0,0 +1,34 @@ +/* +** ast_and.c for 42sh +** +** Made by Seblu +** Login +** +** Started on Thu Aug 3 02:41:37 2006 Seblu +** Last update Thu Aug 3 03:03:31 2006 Seblu +*/ + +#include "../common/mem.h" +#include "ast.h" + +ts_ast_node *ast_create_and(ts_ast_node *lhs, ts_ast_node *rhs) +{ + ts_ast_node *node; + + secmalloc(node, sizeof (ts_ast_node)); + node->type = T_AND; + node->body.child_and.lhs = lhs; + node->body.child_and.rhs = rhs; + return node; +} + +void ast_destruct_and(ts_ast_node *node) +{ + if (node->type != T_AND) { + ast_destruct(node); + return; + } + ast_destruct(node->body.child_and.lhs); + ast_destruct(node->body.child_and.rhs); + free(node); +} diff --git a/src/ast/ast_bang.c b/src/ast/ast_bang.c new file mode 100644 index 0000000..dc46e78 --- /dev/null +++ b/src/ast/ast_bang.c @@ -0,0 +1,34 @@ +/* +** ast_bang.c for 42sh +** +** Made by Seblu +** Login +** +** Started on Thu Aug 3 02:41:37 2006 Seblu +** Last update Fri Aug 18 15:57:05 2006 Seblu +*/ + +#include "../common/mem.h" +#include "ast.h" + +ts_ast_node *ast_create_bang(ts_ast_node *child) +{ + ts_ast_node *node; + + secmalloc(node, sizeof (ts_ast_node)); + node->type = T_BANG; + node->body.child_bang.lhs = child; + node->body.child_bang.rhs = NULL; + return node; +} + +void ast_destruct_bang(ts_ast_node *node) +{ + if (node->type != T_BANG) { + ast_destruct(node); + return; + } + ast_destruct(node->body.child_bang.lhs); + free(node); +} + diff --git a/src/ast/ast_case.c b/src/ast/ast_case.c new file mode 100644 index 0000000..7aae77a --- /dev/null +++ b/src/ast/ast_case.c @@ -0,0 +1,64 @@ +/* +** ast_for.c for 42sh +** +** Made by Seblu +** Login +** +** Started on Thu Aug 3 02:41:37 2006 Seblu +** Last update Fri Aug 18 15:55:00 2006 Seblu +*/ + +#include "../common/mem.h" +#include "ast.h" + +ts_ast_node *ast_case_create(char *word) +{ + ts_ast_node *node; + + secmalloc(node, sizeof (ts_ast_node)); + node->type = T_CASE; + node->body.child_case.word = word; + node->body.child_case.items = NULL; + return node; +} + +void ast_case_add_item(ts_ast_node *node, + char **pattern, + ts_ast_node *list) +{ +/* ts_case_item *item; */ + +/* secmalloc(item, sizeof (ts_case_item)); */ +/* item->pattern = pattern; */ +/* item->list = list; */ + node = node; + pattern = pattern; + list = list; +/* for (ts_case_item **this = &node->items; */ +/* *this; */ +/* *this = (*this)->next) */ +/* ; //do nothing */ +/* *this = item; */ +} + +void ast_case_destruct(ts_ast_node *node) +{ + node = node; +/* ts_case_item *this, *buf; */ + +/* if (node->type != T_CASE) { */ +/* ast_destruct(node); */ +/* return; */ +/* } */ +/* free(node->body.child_case.word); */ +/* /\* for (ts_case_item *this = node->items; *\/ */ +/* /\* this; *\/ */ +/* /\* this = this->next) *\/ */ +/* /\* for (register int i = 0; node->body.child_case.items[i]; ++i) { *\/ */ +/* //fixme for multiple pattern */ +/* free(node->body.child_case.items[i].pattern); */ +/* ast_destruct(node->body.child_case.items[i].list); */ +/* } */ +/* free(node->body.child_case.items); */ +/* free(node); */ +} diff --git a/src/ast/ast_for.c b/src/ast/ast_for.c new file mode 100644 index 0000000..0dedb2a --- /dev/null +++ b/src/ast/ast_for.c @@ -0,0 +1,40 @@ +/* +** ast_for.c for 42sh +** +** Made by Seblu +** Login +** +** Started on Thu Aug 3 02:41:37 2006 Seblu +** Last update Thu Aug 3 03:03:31 2006 Seblu +*/ + +#include "../common/mem.h" +#include "ast.h" + +ts_ast_node *ast_create_for(char *varname, + char **values, + ts_ast_node *exec) +{ + ts_ast_node *node; + + secmalloc(node, sizeof (ts_ast_node)); + node->type = T_FOR; + node->body.child_for.varname = varname; + node->body.child_for.values = values; + node->body.child_for.exec = exec; + return node; +} + +void ast_destruct_for(ts_ast_node *node) +{ + if (node->type != T_FOR) { + ast_destruct(node); + return; + } + free(node->body.child_for.varname); + for (register int i = 0; node->body.child_for.values[i]; ++i) + free(node->body.child_for.values[i]); + free(node->body.child_for.values); + ast_destruct(node->body.child_for.exec); + free(node); +} diff --git a/src/ast/ast_funcdec.c b/src/ast/ast_funcdec.c new file mode 100644 index 0000000..f60e929 --- /dev/null +++ b/src/ast/ast_funcdec.c @@ -0,0 +1,34 @@ +/* +** ast_funcdec.c for 42sh +** +** Made by Seblu +** Login +** +** Started on Thu Aug 3 02:41:37 2006 Seblu +** Last update Fri Aug 18 15:55:42 2006 Seblu +*/ + +#include "../common/mem.h" +#include "ast.h" + +ts_ast_node *ast_create_funcdec(char *name, ts_ast_node *body) +{ + ts_ast_node *node; + + secmalloc(node, sizeof (ts_ast_node)); + node->type = T_FUNCDEC; + node->body.child_funcdec.name = name; + node->body.child_funcdec.body = body; + return node; +} + +void ast_destruct_funcdec(ts_ast_node *node) +{ + if (node->type != T_FUNCDEC) { + ast_destruct(node); + return; + } + free(node->body.child_funcdec.name); + ast_destruct(node->body.child_funcdec.body); + free(node); +} diff --git a/src/ast/ast_if.c b/src/ast/ast_if.c new file mode 100644 index 0000000..4ebb56c --- /dev/null +++ b/src/ast/ast_if.c @@ -0,0 +1,38 @@ +/* +** ast_if.c for 42sh +** +** Made by Seblu +** Login +** +** Started on Thu Aug 3 02:41:37 2006 Seblu +** Last update Thu Aug 3 03:03:31 2006 Seblu +*/ + +#include "../common/mem.h" +#include "ast.h" + +ts_ast_node *ast_create_if(ts_ast_node *cond, + ts_ast_node *cond_true, + ts_ast_node *cond_false) +{ + ts_ast_node *node; + + secmalloc(node, sizeof (ts_ast_node)); + node->type = T_IF; + node->body.child_if.cond = cond; + node->body.child_if.cond_true = cond_true; + node->body.child_if.cond_false = cond_false; + return node; +} + +void ast_destruct_if(ts_ast_node *node) +{ + if (node->type != T_IF) { + ast_destruct(node); + return; + } + ast_destruct(node->body.child_if.cond); + ast_destruct(node->body.child_if.cond_true); + ast_destruct(node->body.child_if.cond_false); + free(node); +} diff --git a/src/ast/ast_or.c b/src/ast/ast_or.c new file mode 100644 index 0000000..e4e15ff --- /dev/null +++ b/src/ast/ast_or.c @@ -0,0 +1,35 @@ +/* +** ast_or.c for 42sh +** +** Made by Seblu +** Login +** +** Started on Thu Aug 3 02:41:37 2006 Seblu +** Last update Thu Aug 3 03:03:31 2006 Seblu +*/ + +#include "../common/mem.h" +#include "ast.h" + +ts_ast_node *ast_create_or(ts_ast_node *lhs, ts_ast_node *rhs) +{ + ts_ast_node *node; + + secmalloc(node, sizeof (ts_ast_node)); + node->type = T_OR; + node->body.child_or.lhs = lhs; + node->body.child_or.rhs = rhs; + return node; +} + +void ast_destruct_or(ts_ast_node *node) +{ + if (node->type != T_OR) { + ast_destruct(node); + return; + } + ast_destruct(node->body.child_or.lhs); + ast_destruct(node->body.child_or.rhs); + free(node); +} + diff --git a/src/ast/ast_pipe.c b/src/ast/ast_pipe.c new file mode 100644 index 0000000..7c895f9 --- /dev/null +++ b/src/ast/ast_pipe.c @@ -0,0 +1,35 @@ +/* +** ast_pipe.c for 42sh +** +** Made by Seblu +** Login +** +** Started on Thu Aug 3 02:41:37 2006 Seblu +** Last update Thu Aug 3 03:03:31 2006 Seblu +*/ + +#include "../common/mem.h" +#include "ast.h" + +ts_ast_node *ast_create_pipe(ts_ast_node *lhs, ts_ast_node *rhs) +{ + ts_ast_node *node; + + secmalloc(node, sizeof (ts_ast_node)); + node->type = T_PIPE; + node->body.child_pipe.lhs = lhs; + node->body.child_pipe.rhs = rhs; + return node; +} + +void ast_destruct_pipe(ts_ast_node *node) +{ + if (node->type != T_PIPE) { + ast_destruct(node); + return; + } + ast_destruct(node->body.child_pipe.lhs); + ast_destruct(node->body.child_pipe.rhs); + free(node); +} + diff --git a/src/ast/ast_sep.c b/src/ast/ast_sep.c index 9e90178..2428eab 100644 --- a/src/ast/ast_sep.c +++ b/src/ast/ast_sep.c @@ -2,7 +2,7 @@ ** ast_sep.c for 42sh ** ** Made by Seblu -** Login +** Login ** ** Started on Thu Aug 3 02:41:37 2006 Seblu ** Last update Thu Aug 3 03:03:31 2006 Seblu @@ -11,14 +11,6 @@ #include "../common/mem.h" #include "ast.h" -/*! -** Create a separtor ast node -** -** @param lhs left child -** @param rhs right child -** -** @return the node -*/ ts_ast_node *ast_create_sep(ts_ast_node *lhs, ts_ast_node *rhs) { ts_ast_node *node; @@ -30,11 +22,6 @@ ts_ast_node *ast_create_sep(ts_ast_node *lhs, ts_ast_node *rhs) return node; } -/*! -** Destruct and separator node -** -** @param node node to destroy -*/ void ast_destruct_sep(ts_ast_node *node) { if (node->type != T_SEP) { diff --git a/src/ast/ast_sepand.c b/src/ast/ast_sepand.c new file mode 100644 index 0000000..8d9a774 --- /dev/null +++ b/src/ast/ast_sepand.c @@ -0,0 +1,35 @@ +/* +** ast_sepand.c for 42sh +** +** Made by Seblu +** Login +** +** Started on Thu Aug 3 02:41:37 2006 Seblu +** Last update Thu Aug 3 03:03:31 2006 Seblu +*/ + +#include "../common/mem.h" +#include "ast.h" + +ts_ast_node *ast_create_sepand(ts_ast_node *lhs, ts_ast_node *rhs) +{ + ts_ast_node *node; + + secmalloc(node, sizeof (ts_ast_node)); + node->type = T_SEPAND; + node->body.child_sepand.lhs = lhs; + node->body.child_sepand.rhs = rhs; + return node; +} + +void ast_destruct_sepand(ts_ast_node *node) +{ + if (node->type != T_SEPAND) { + ast_destruct(node); + return; + } + ast_destruct(node->body.child_sepand.lhs); + ast_destruct(node->body.child_sepand.rhs); + free(node); +} + diff --git a/src/ast/ast_subshell.c b/src/ast/ast_subshell.c new file mode 100644 index 0000000..dc4ef11 --- /dev/null +++ b/src/ast/ast_subshell.c @@ -0,0 +1,34 @@ +/* +** ast_subshell.c for 42sh +** +** Made by Seblu +** Login +** +** Started on Thu Aug 3 02:41:37 2006 Seblu +** Last update Thu Aug 3 03:03:31 2006 Seblu +*/ + +#include "../common/mem.h" +#include "ast.h" + +ts_ast_node *ast_create_subshell(ts_ast_node *child) +{ + ts_ast_node *node; + + secmalloc(node, sizeof (ts_ast_node)); + node->type = T_SUBSHELL; + node->body.child_subshell.lhs = child; + node->body.child_subshell.rhs = NULL; + return node; +} + +void ast_destruct_subshell(ts_ast_node *node) +{ + if (node->type != T_SUBSHELL) { + ast_destruct(node); + return; + } + ast_destruct(node->body.child_subshell.lhs); + free(node); +} + diff --git a/src/ast/ast_until.c b/src/ast/ast_until.c new file mode 100644 index 0000000..afcc291 --- /dev/null +++ b/src/ast/ast_until.c @@ -0,0 +1,34 @@ +/* +** ast_until.c for 42sh +** +** Made by Seblu +** Login +** +** Started on Thu Aug 3 02:41:37 2006 Seblu +** Last update Thu Aug 3 03:03:31 2006 Seblu +*/ + +#include "../common/mem.h" +#include "ast.h" + +ts_ast_node *ast_create_until(ts_ast_node *cond, ts_ast_node *exec) +{ + ts_ast_node *node; + + secmalloc(node, sizeof (ts_ast_node)); + node->type = T_UNTIL; + node->body.child_until.cond = cond; + node->body.child_until.exec = exec; + return node; +} + +void ast_destruct_until(ts_ast_node *node) +{ + if (node->type != T_UNTIL) { + ast_destruct(node); + return; + } + ast_destruct(node->body.child_until.cond); + ast_destruct(node->body.child_until.exec); + free(node); +} diff --git a/src/ast/ast_while.c b/src/ast/ast_while.c new file mode 100644 index 0000000..7ab25fa --- /dev/null +++ b/src/ast/ast_while.c @@ -0,0 +1,34 @@ +/* +** ast_while.c for 42sh +** +** Made by Seblu +** Login +** +** Started on Thu Aug 3 02:41:37 2006 Seblu +** Last update Thu Aug 3 03:03:31 2006 Seblu +*/ + +#include "../common/mem.h" +#include "ast.h" + +ts_ast_node *ast_create_while(ts_ast_node *cond, ts_ast_node *exec) +{ + ts_ast_node *node; + + secmalloc(node, sizeof (ts_ast_node)); + node->type = T_WHILE; + node->body.child_while.cond = cond; + node->body.child_while.exec = exec; + return node; +} + +void ast_destruct_while(ts_ast_node *node) +{ + if (node->type != T_WHILE) { + ast_destruct(node); + return; + } + ast_destruct(node->body.child_while.cond); + ast_destruct(node->body.child_while.exec); + free(node); +} diff --git a/src/common/strndup.c b/src/common/strndup.c index b5faf8a..f834378 100644 --- a/src/common/strndup.c +++ b/src/common/strndup.c @@ -10,6 +10,7 @@ #include #include +#include "mem.h" char *strndup(const char *str, size_t n) { @@ -21,8 +22,7 @@ char *strndup(const char *str, size_t n) max_length = n; if ((length = strlen(str)) > max_length) length = max_length; - if ((new = malloc((length + 1) * sizeof (char))) == NULL) - return NULL; + secmalloc(new, (length + 1) * sizeof (char)); for (i = 0; i < length; ++i) new[i] = str[i]; new[length] = 0; diff --git a/src/parser/lexer.c b/src/parser/lexer.c index afd5cb4..c032b31 100644 --- a/src/parser/lexer.c +++ b/src/parser/lexer.c @@ -10,11 +10,27 @@ #include #include +#include #include "parser.h" #include "../shell/shell.h" #include "../readline/readline.h" +#include "../common/common.h" -int lexer_reconize(ts_parser *parser); +#define is_quote(c) ((c) == '"' || (c) == '\'' || (c) == '`') +#define is_sep(c) ((c) == ' ' || (c) == '\t' || (c) == '\v') + +static int lexer_reconize(ts_parser *parser); + +/*! +** Set the current token for a parser +** +** @param p the parser +** @param t new token id +** @param s new token str +** +** @return token string representation +*/ +static void set_current_token(ts_parser *p, te_tokenid t, const char *s); ts_token tokens[] = { @@ -52,69 +68,117 @@ ts_token tokens[] = void lexer_reset(ts_parser *parser) { - parser->current.id = TOK_NONE; - parser->current.str = "none"; + set_current_token(parser, TOK_BEGIN, "begin"); if (parser->buf != NULL) free(parser->buf); parser->buf = NULL; - parser->buf_size = 0; - parser->buf_pos = 0; + parser->buf_size = parser->buf_pos = 0; } -const char *get_token_string(t_token t) +const char *get_token_string(te_tokenid t) { for (register int i = 0; tokens[i].str; ++i) if (tokens[i].id == t) return tokens[i].str; - return "unknow"; + return NULL; } ts_token lexer_get(ts_parser *parser) { - if (parser->current.id == TOK_NONE) + if (parser->current.id == TOK_BEGIN) lexer_eat(parser); return parser->current; } void lexer_eat(ts_parser *parser) { + char *lbuf, *lbuf2; + + // return EOF (the last), if file is ended if (parser->status == PARSE_END) return; + //if line is void, start readding if (parser->buf_size == 0) { if ((parser->buf = readline(get_prompt(TYPE_PS1))) == NULL) { - parser->current.id = TOK_EOF; + set_current_token(parser, TOK_EOF, "eof"); parser->status = PARSE_END; return; } parser->buf_pos = 0; parser->buf_size = strlen(parser->buf); } - if (parser->buf_size > 0 && - parser->buf_size != parser->buf_pos) { - if (lexer_reconize(parser)) - return; - } - do - if ((parser->buf = readline(get_prompt(TYPE_PS2))) == NULL) { - parser->current.id = TOK_EOF; + //read line while a token will not be reconized + while (!lexer_reconize(parser)) { + if ((lbuf2 = readline(get_prompt(TYPE_PS2))) == NULL) { + set_current_token(parser, TOK_EOF, "eof"); parser->status = PARSE_END; + return; } - while (lexer_reconize(parser)); + lbuf = parser->buf; + parser->buf = strmerge(2, lbuf, lbuf2); + parser->buf_size = strlen(parser->buf); + free(lbuf), free(lbuf2); + } } -int lexer_reconize(ts_parser *parser) +static void set_current_token(ts_parser *p, te_tokenid t, const char *s) { - size_t n; + if (p->current.id == TOK_WORD) + free((char*)p->current.str); + p->current.id = t; + p->current.str = s; +} +static int lexer_reconize(ts_parser *parser) +{ + const char *buf = parser->buf; + const size_t buf_size = parser->buf_size; + size_t *buf_pos = &parser->buf_pos; + size_t token_start; + size_t token_pos; + int end_found = 0; + char backed = 0; + char quoted = 0; + + //eat spaces (" ",\t, \v) + while (*buf_pos < buf_size && + is_sep(buf[*buf_pos])) + ++*buf_pos; + //check for leading \n token + if (buf[*buf_pos] == '\n') { + ++*buf_pos; + set_current_token(parser, TOK_NEWLINE, "\n"); + return 1; + } + //cut a token + token_start = token_pos = *buf_pos; + for (; !end_found && token_pos < buf_size; ++token_pos) + if (backed) + backed = 0; + else if (!quoted && (buf[token_pos] == '\n' || is_sep(buf[token_pos]))) + { end_found = 1; break; } + else if (!quoted && is_quote(buf[token_pos])) + quoted = buf[token_pos]; + else if (quoted && buf[token_pos] == quoted) + quoted = 0; + else if (!backed && buf[token_pos] == '\\') + backed = 1; + if (!end_found) return 0; + parser->buf_pos = token_pos; + printf("cutted token: '%s'\n", + strndup(buf + token_start, token_pos - token_start)); + //check if it's a registered keyword for (register int i = 0; tokens[i].str; ++i) - if (!strncmp(tokens[i].str, parser->buf + parser->buf_pos, - n = strlen(tokens[i].str))) { - parser->current = tokens[i]; - parser->buf_pos += n; - printf("reconized %d\n", tokens[i].id); + if (!strncmp(tokens[i].str, buf + token_start, + token_pos - token_start)) { + set_current_token(parser, tokens[i].id, tokens[i].str); + printf("reconized token: %d (%s)\n", tokens[i].id, tokens[i].str); return 1; } - parser->current.id = TOK_NONE; - parser->current.str = "none"; - return 0; + //althought this token is a word + set_current_token(parser, TOK_WORD, + strndup(buf + token_start, token_pos - token_start)); + printf("reconized token (WORD): %d (%s)\n", + parser->current.id, parser->current.str); + return 1; } diff --git a/src/parser/parser.c b/src/parser/parser.c index 2f2a74e..c2d2de0 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Wed Aug 2 00:56:07 2006 Seblu -** Last update Thu Aug 3 12:30:15 2006 Seblu +** Last update Fri Aug 18 15:46:11 2006 Seblu */ #include @@ -61,6 +61,18 @@ ts_ast_node *parse(ts_parser *parser) { lexer_reset(parser); parser->status = PARSE_OK; + //test lexer mode +/* while (1) */ +/* { */ +/* ts_token tok; */ + +/* tok = lexer_get(parser); */ +/* if (tok.id == TOK_EOF) */ +/* exit(42); */ +/* if (tok.id == TOK_NEWLINE) */ +/* lexer_reset(parser); */ +/* lexer_eat(parser); */ +/* } */ return parse_input(parser); } @@ -71,13 +83,12 @@ static ts_ast_node *parse_input(ts_parser *parser) lexer_eat(parser); cur_token = lexer_get(parser); - if (cur_token.id == TOK_EOF) { - parser->status = PARSE_END; + if (cur_token.id == TOK_EOF) return NULL; - } if (cur_token.id == TOK_NEWLINE) return ast_create_sep(NULL, NULL); buf = parse_list(parser); + lexer_eat(parser); cur_token = lexer_get(parser); if (cur_token.id != TOK_EOF || cur_token.id != TOK_NEWLINE) parse_error(parser, cur_token); @@ -87,21 +98,27 @@ static ts_ast_node *parse_input(ts_parser *parser) static ts_ast_node *parse_list(ts_parser *parser) { ts_token next_token; - ts_ast_node *buf; + ts_ast_node *lhs; +/* ts_ast_node *rhs; */ - parse_andor(parser); + lhs = parse_andor(parser); lexer_eat(parser); next_token = lexer_get(parser); - if (next_token.id != TOK_SEP && next_token.id != TOK_SEPAND) { - parse_error(parser, next_token); - return buf; - } +/* if (next_token.id == TOK_SEP) { */ +/* lhs = parse_andor(parser); */ +/* } */ +/* else if (next_token.id == TOK_SEPAND) { */ +/* parse_error(parser, next_token); */ +/* /\* return buf; *\/ */ +/* } */ +/* parse_error(parser, next_token); */ +/* return ; */ return NULL; } static ts_ast_node *parse_andor(ts_parser *parser) { - parser=parser; + parser = parser; return NULL; } diff --git a/src/parser/parser.h b/src/parser/parser.h index 0db08c0..e5645c5 100644 --- a/src/parser/parser.h +++ b/src/parser/parser.h @@ -14,64 +14,70 @@ #ifndef PARSER_H_ # define PARSER_H_ -# define TOK_AND 1 -# define TOK_OR 2 -# define TOK_DSEMI 3 -# define TOK_DLESS 4 -# define TOK_DGREAT 5 -# define TOK_LESSAND 6 -# define TOK_GREATAND 7 -# define TOK_LESSGREAT 8 -# define TOK_DLESSDASH 9 -# define TOK_CLOBBER 10 -# define TOK_IF 11 -# define TOK_THEN 12 -# define TOK_ELSE 13 -# define TOK_FI 14 -# define TOK_ELIF 15 -# define TOK_DO 16 -# define TOK_DONE 17 -# define TOK_CASE 18 -# define TOK_ESAC 19 -# define TOK_WHILE 20 -# define TOK_UNTIL 21 -# define TOK_FOR 22 -# define TOK_IN 23 -# define TOK_LBRACE 24 -# define TOK_RBRACE 25 -# define TOK_BANG 26 -# define TOK_NEWLINE 27 -# define TOK_SEP 28 -# define TOK_SEPAND 29 -# define TOK_EOF 30 -# define TOK_NONE 31 - -typedef int t_token; +typedef enum e_token + { + TOK_AND, + TOK_OR, + TOK_DSEMI, + TOK_DLESS, + TOK_DGREAT, + TOK_LESSAND, + TOK_GREATAND, + TOK_LESSGREAT, + TOK_DLESSDASH, + TOK_CLOBBER, + TOK_IF, + TOK_THEN, + TOK_ELSE, + TOK_FI, + TOK_ELIF, + TOK_DO, + TOK_DONE, + TOK_CASE, + TOK_ESAC, + TOK_WHILE, + TOK_UNTIL, + TOK_FOR, + TOK_IN, + TOK_LBRACE, + TOK_RBRACE, + TOK_BANG, + TOK_NEWLINE, + TOK_SEP, + TOK_SEPAND, + TOK_WORD, + TOK_EOF, + TOK_BEGIN + } te_tokenid; typedef struct s_token { - t_token id; + te_tokenid id; const char *str; } ts_token; - -typedef enum e_parse_status +typedef enum e_parser_status { PARSE_OK, PARSE_ERROR, PARSE_END - } te_parse_status; + } te_parser_status; typedef struct s_parser { - te_parse_status status; + te_parser_status status; ts_token current; FILE *fs; char *buf; size_t buf_size; size_t buf_pos; + size_t tok_start; } ts_parser; +/* +** FILE: parser.c +*/ + /*! ** Parser initialization ** @@ -81,7 +87,6 @@ typedef struct s_parser */ ts_parser *parser_init(FILE *fs); - /*! ** Notify a parse error ** @@ -99,6 +104,10 @@ void parse_error(ts_parser *parser, ts_token t); */ ts_ast_node *parse(ts_parser *parser); +/* +** FILE: lexer.c +*/ + /*! ** Set (or reset) the lexer ** @@ -125,6 +134,6 @@ void lexer_eat(ts_parser *lex); ** ** @return token string representation */ -const char *get_token_string(t_token t); +const char *get_token_string(te_tokenid t); #endif -- GitLab