From 69a2b6eaaa21354e78b5fe6d79b0e7e10e127dcc Mon Sep 17 00:00:00 2001 From: We-unite <3205135446@qq.com> Date: Mon, 3 Jun 2024 18:18:32 +0800 Subject: Initial commit: Basic found. - I use flex and bison for lexical and syntax analysis, and main c to run command - basic CFG built to deal with easy command without redirecion ( it's written but have serious problem) - it can now run command one by one, and use \ to change line without ending the command. Fighting forward! --- .gitignore | 8 ++++++++ Makefile | 32 ++++++++++++++++++++++++++++++++ bcsh.c | 10 ++++++++++ cmd.h | 30 ++++++++++++++++++++++++++++++ lex.l | 33 +++++++++++++++++++++++++++++++++ syntax.y | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 163 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 bcsh.c create mode 100644 cmd.h create mode 100644 lex.l create mode 100644 syntax.y diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..66c7e33 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +* +!*.* +!*/* +!Makefile +*.o +*.tab* +lex.yy.c +*.output \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8410a24 --- /dev/null +++ b/Makefile @@ -0,0 +1,32 @@ +CC = gcc +FLEX = flex +BISON = bison + +CFILES = $(shell find . -name "*.c") +OBJS = $(CFILES:.c=.o) +LFILE = $(wildcard *.l) +YFILE = $(wildcard *.y) +LFC = ./lex.yy.c +YFC = ./syntax.tab.c +LFO = $(LFC:.c=.o) +YFO = $(YFC:.c=.o) + +bcsh: syntax $(filter-out $(LFO),$(OBJS)) + $(CC) -g -o bcsh $(filter-out $(LFO),$(OBJS)) -lfl + +syntax: lexical syntax-c + $(CC) -c $(YFC) -o $(YFO) + +lexical: $(LFILE) + $(FLEX) -o $(LFC) $(LFILE) + +syntax-c: $(YFILE) + $(BISON) -o $(YFC) -d -v $(YFILE) -Wcounterexamples + +-include $(patsubst %.o, %.d, $(OBJS)) + +clean: + rm -f bcsh lex.yy.c syntax.tab.c syntax.tab.h syntax.output + rm -f $(OBJS) $(OBJS:.o=.d) + rm -f $(LFC) $(YFC) $(YFC:.c=.h) + rm -f *~ \ No newline at end of file diff --git a/bcsh.c b/bcsh.c new file mode 100644 index 0000000..ca83402 --- /dev/null +++ b/bcsh.c @@ -0,0 +1,10 @@ +#include "cmd.h" + +extern int yyparse(); + +int main(int argc, char **argv) { + while (true) { + yyparse(); + } + return 0; +} \ No newline at end of file diff --git a/cmd.h b/cmd.h new file mode 100644 index 0000000..adf03c7 --- /dev/null +++ b/cmd.h @@ -0,0 +1,30 @@ +#ifndef CMD_H +#define CMD_H + +#include +#include +#include + +typedef enum { + CMD_TYPE_NORMAL, + CMD_TYPE_PIPE, + CMD_TYPE_AND, + CMD_TYPE_OR, + // add more command types as needed +} CommandType; + +typedef struct Command { + CommandType type; // the type of the command + char **args; // an array of strings for the arguments of the command + struct Command *left; // a pointer to the left sub-command + struct Command *right; // a pointer to the right sub-command + char *redirect_in; // the file name for input redirection, or NULL if there + // is no input redirection + char *redirect_out; // the file name for output redirection, or NULL if + // there is no output redirection + char *append_out; // the file name for output appending, or NULL if there is + // no output appending + // add more fields as needed +} Command; + +#endif \ No newline at end of file diff --git a/lex.l b/lex.l new file mode 100644 index 0000000..036d58e --- /dev/null +++ b/lex.l @@ -0,0 +1,33 @@ +%{ +#include "syntax.tab.h" // Bison 生成的头文件 + +void yyerror(const char *s); +%} + +%option noyywrap + +%% + +[\t ]+ { /* Ignore whitespace */ } +"\n" { printf("new line\n");return NEWLINE; } +"\\\n" { printf("> "); } +">>" { return APPEND_OUT; } +"<<" { return HEREDOC; } +">" { return REDIRECT_OUT; } +"<" { return REDIRECT_IN; } +">>&" { return APPEND_OUTPUT_ERR; } +">&" { return REDIRECT_OUTPUT_ERR; } +"|" { return PIPE; } +"&&" { return AND; } +"||" { return OR; } +"&" { return BACKGROUND; } +\"(\\.|[^\"])*\" { yylval.str = strdup(yytext); return STRING; } +[a-zA-Z0-9_\-\/.]+ { yylval.str = strdup(yytext); return WORD; } + + +%% + +void yyerror(const char *s) +{ + fprintf(stderr, "error: %s\n", s); +} diff --git a/syntax.y b/syntax.y new file mode 100644 index 0000000..aa0df71 --- /dev/null +++ b/syntax.y @@ -0,0 +1,50 @@ +%{ +#include "lex.yy.c" +#include "cmd.h" + +%} + +%union { + char *str; +} + +%token WORD STRING +%token NEWLINE CONTINUATION APPEND_OUT REDIRECT_OUT REDIRECT_IN APPEND_OUTPUT_ERR REDIRECT_OUTPUT_ERR PIPE AND OR BACKGROUND HEREDOC UNKNOWN + +%% + +line: + command NEWLINE { printf("Parsed a command.\n"); } + | NEWLINE { /* empty line */ } + ; + +command: + part {printf("PART\n"); } + | part separator command { printf("COMMAND\n"); } + | part REDIRECT_OUT WORD tail { printf("REDIRECT_OUT: %s\n", $3); free($3); } + | part REDIRECT_IN WORD tail { printf("REDIRECT_IN: %s\n", $3); free($3); } + | part HEREDOC WORD tail { printf("HEREDOC: %s\n", $3); free($3); } + | part BACKGROUND { printf("BACKGROUND\n"); } + ; + +tail: + part + | part REDIRECT_OUT WORD tail { printf("REDIRECT_OUT: %s\n", $3); free($3); } + | part REDIRECT_IN WORD tail { printf("REDIRECT_IN: %s\n", $3); free($3); } + | part HEREDOC WORD tail { printf("HEREDOC: %s\n", $3); free($3); } + ; + +part: + part WORD { printf("WORD: %s\n", $2); free($2); } + | part STRING { printf("STRING: %s\n", $2); free($2); } + | WORD { printf("WORD: %s\n", $1); free($1); } + | STRING { printf("STRING: %s\n", $1); free($1); } + ; + +separator: + PIPE { printf("PIPE\n"); } + | AND { printf("AND\n"); } + | OR { printf("OR\n"); } + ; + +%% \ No newline at end of file -- cgit v1.2.3-70-g09d2