Question: In this assignment, you will: 1. Implement and test function char *sushi_unqiote(char *s), 2. Modify function void sushi_read_config(char *fname), and 1. Function char *sushi_unquote(char *s)
In this assignment, you will:
1. Implement and test function char *sushi_unqiote(char *s),
2. Modify function void sushi_read_config(char *fname), and
1. Function char *sushi_unquote(char *s) shall return the string s where each escape sequence1 shall be replaced by its value. For example, a backslash \ followed by an n shall be replaced by a newline character .
2. For this stage of the project, you must install bison and flex, free parser and lexer generators. You are not required to write your own Bison and Flex rules, but encouraged to look into the provided files.
File sushi_yylexer.l describes the tokens admissible on the sushi command line. The tokens are described as regular expressions. For example, "#".*" "? represents a comment (a pound sign #, followed by zero or more characters, optionally followed by newline). Flex converts the input file into a C file (do not edit that file by hand!) that provides function yylex(). The function is a token generator: every time you call it, you get the next token from the command line.
File sushi_yyparser.y recursively describes the grammar of the sushi language; that is, what combinations of the tokens are admissible. For example, the command line must be either an in-out program, possibly followed by an ampersand for background execution, or an in program followed by a pipe and possibly an ampersand (lines 3436). Furthermore, an in-out program is either just a program or a program with in-out redirection (lines 3840); in-out redirection, in turn, is either in redirection followed by out redirection or the other way around (lines 5052). Etc. Bison converts the input file into
1 The first eleven lines in the table https://en.wikipedia.org/wiki/Escape_sequences_in_C#Table_of_escape_sequences
Operating systems Shell project CMPSC-F355
Suffolk University Spring 2021 Math & CS Department
a C file (do not edit that file by hand!) that provides function yyparse(). The function calls yylex() to read tokens, validates the stream of tokens against the grammar rules, and executes C actions (the code in curly braces) whenever an appropriate grammar structure is encountered.
For the ease of use, I wrapped yyparse() into another function int sushi_parse_command(char *command) that takes the command line command, validates its syntax, and returns 1 or 0, depending on whether or not the command line had syntax errors. You will modify this function in the future to execute the command line.
3. Rewrite the main() function and sushi_read_config() from your previous assignment.
3a. Call sushi_parse_command() after each successful call to sushi_read_line(). (Including the calls in sushi_read_config()). Pass the value returned by sushi_read_line() to sushi_parse_command(). Do not store the line in the history if it has syntax errors (if sushi_parse_command() returns a non-0).
3b. Add the main loop to the main() function. The loop shall run for as long the global variable sushi_exit (provided) is 0. The loop shall display the prompt, call sushi_read_line(), and then call sushi_parse_command().
3c. Modify line 69 of sushi_yyparser.y: add an action that changes the value of sushi_exit. That way, you shall be able to exit sushi by typing exit on the command line.
3d. Modify line 68 of sushi_yyparser.y: add an action that shows the command history. That way, you shall be able to see the history by typing ! on the command line.
| #include | |
| #include "sushi_yyparser.tab.h" | |
| // Modify this function | |
| char *sushi_unquote(char *s) { | |
| return s; | |
| } | |
| // Do not modify this function | |
| void yyerror(const char* s) { | |
| fprintf(stderr, "Parse error: %s ", s); | |
| } |
| %{ | |
| #include "sushi.h" | |
| int yylex(); | |
| void yyerror(const char* s); | |
| %} | |
| %union { | |
| char *s; | |
| int i; | |
| } | |
| %token YY_SUSHI_SET | |
| %token YY_SUSHI_HISTORY | |
| %token YY_SUSHI_EXIT | |
| %token YY_SUSHI_JOBS | |
| %token YY_SUSHI_PWD | |
| %token YY_SUSHI_CD | |
| %token YY_SUSHI_UNKNOWN | |
| %token YY_SUSHI_LESS | |
| %token YY_SUSHI_MORE | |
| %token YY_SUSHI_MOREMORE | |
| %token YY_SUSHI_AMP | |
| %token YY_SUSHI_BAR | |
| %token | |
| %type | |
| %type bgmode | |
| %start cmdline | |
| %% | |
| cmdline: | |
| /* an empty line is valid, too! */ | |
| | inout_program bgmode /* TODO */ | |
| | in_program pipe bgmode /* TODO */ | |
| inout_program: | |
| program /* TODO */ | |
| | program inout_redirection /* TODO */ | |
| in_program: | |
| program /* TODO */ | |
| | program in_redirection /* TODO */ | |
| out_program: | |
| program /* TODO */ | |
| | program out_redirection /* TODO */ | |
| inout_redirection: | |
| in_redirection out_redirection /* TODO */ | |
| | out_redirection in_redirection /* TODO */ | |
| out_redirection: | |
| YY_SUSHI_MORE arg /* TODO */ | |
| | YY_SUSHI_MOREMORE arg /* TODO */ | |
| in_redirection: | |
| YY_SUSHI_LESS arg /* TODO */ | |
| bgmode: /* Done */ | |
| { $$ = 0; } | |
| | YY_SUSHI_AMP { $$ = 1; } | |
| program: | |
| args /* TODO */ | |
| | arg YY_SUSHI_SET arg /* TODO */ | |
| | YY_SUSHI_HISTORY { /* Add your code here */ } | |
| | YY_SUSHI_EXIT { /* Add your code here */ } | |
| | YY_SUSHI_JOBS /* TODO */ | |
| | YY_SUSHI_PWD /* TODO */ | |
| | YY_SUSHI_CD arg /* TODO */ | |
| pipe: | |
| YY_SUSHI_BAR out_program /* TODO */ | |
| | YY_SUSHI_BAR program pipe /* TODO */ | |
| args: | |
| arg /* TODO */ | |
| | args arg /* TODO */ | |
| arg: /* Done */ | |
| YY_SUSHI_TOK { $$ = $1; } |
| #include "sushi.h" | |
| #include "sushi_yyparser.tab.h" | |
| #ifdef __APPLE__ | |
| extern int yylex(void); | |
| #endif | |
| %} | |
| %option noyywrap | |
| digit [0-9] | |
| letter [a-zA-Z_] | |
| alnum {digit}|{letter} | |
| string \"([^ \\\"]|\\.)*\" | |
| quoted_string \'([^ \\\']|\\.)*\' | |
| permitted {digit}|{letter}|[-%@_+\[\]\\/,\.:] | |
| unsupported [;()*^?~{}`] | |
| %% | |
| "#".*" "? { /* comment */ } | |
| exit { return YY_SUSHI_EXIT; } | |
| jobs { return YY_SUSHI_JOBS; } | |
| pwd { return YY_SUSHI_PWD; } | |
| cd { return YY_SUSHI_CD; } | |
| \${alnum}+ { yylval.s = strdup(getenv(yytext + 1)); | |
| return YY_SUSHI_TOK; } | |
| {permitted}+ { yylval.s = strdup(sushi_unquote(yytext + 1)); | |
| return YY_SUSHI_TOK; } | |
| {quoted_string} { yytext[strlen(yytext) - 1] = 0; | |
| yylval.s = strdup(yytext + 1); | |
| return YY_SUSHI_TOK; } | |
| {string} { yytext[strlen(yytext) - 1] = 0; | |
| yylval.s = strdup(sushi_unquote(yytext + 1)); | |
| return YY_SUSHI_TOK; } | |
| "<" { return YY_SUSHI_LESS; } | |
| ">" { return YY_SUSHI_MORE; } | |
| ">>" { return YY_SUSHI_MOREMORE; } | |
| "&" { return YY_SUSHI_AMP; } | |
| "|" { return YY_SUSHI_BAR; } | |
| "=" { return YY_SUSHI_SET; } | |
| "!" { return YY_SUSHI_HISTORY; } | |
| {unsupported} { fprintf(stderr, "Unsupported command: %c ", yytext[0]); | |
| return YY_SUSHI_UNKNOWN;} | |
| [\t \b\v ]+ { /* whitespaces */ } | |
| . { fprintf(stderr, "Illegal character: %c ", yytext[0]); | |
| return YY_SUSHI_UNKNOWN; } | |
| %% | |
| // This function will be modified in the future | |
| // The function returns 0 if there are no syntax errors and 1, otherwise | |
| int sushi_parse_command(char *command) { | |
| YY_BUFFER_STATE buffer = yy_scan_string(command); | |
| int retval = yyparse(); | |
| yy_delete_buffer(buffer); | |
| return retval; | |
| } |
Step by Step Solution
There are 3 Steps involved in it
Get step-by-step solutions from verified subject matter experts
