diff options
Diffstat (limited to 'lexical_analysis.c')
-rw-r--r-- | lexical_analysis.c | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/lexical_analysis.c b/lexical_analysis.c new file mode 100644 index 0000000..f931118 --- /dev/null +++ b/lexical_analysis.c @@ -0,0 +1,214 @@ +#include "lexical_analysis.h" +MAKE_QUEUE_PUSH(c_queue, cmdline, char**) + +int is_double_quotes_pair(struct param_type params) +{ + return !(params.double_quotes_counter % 2); +} + +int escape_double_quotes_or_backslash(int ch, struct param_type params) +{ + return params.escape_sequences && + (ch == double_quotes || ch == backslash); +} + +int double_quotes_again(int ch, struct param_type params) +{ + return ch == double_quotes && !params.is_word && + params.stored_symbol == '"'; +} + +int check_separation(int ch, struct param_type params) +{ + return (ch == whitespace || ch == tab) && params.is_word && + !params.escape_sequences; +} + +int ignore_spaces(int ch, struct param_type params) +{ + return (ch == whitespace || ch == tab) && !params.escape_sequences; +} + +int change_mode(int ch, struct param_type params) +{ + return ch == '"' && !params.escape_sequences; +} + +int start_escape_sequence(int ch, struct param_type params) +{ + return ch == backslash && !params.escape_sequences; +} + +int is_empty_word(int ch, struct param_type params) +{ + return (ch == whitespace || ch == tab) && !params.is_word && + params.empty_word_flag; +} + +int command_execution_condition(struct param_type *params) +{ + return + (!filename_waiting(params) && !params->pipeline) || + (params->pipeline && params->tokens == '&'); +} + +int is_special_token(int ch) +{ + return ch == and || ch == or || ch == '&' || ch == ';' || ch == '|'; +} + +int is_redirect_token(int ch, int next_ch) +{ + return ch == '<' || ch == '>' || (ch == '>' && next_ch == '>'); +} + +int excessive_words(int ch, struct param_type *params) +{ + int next_ch; + + if(filename_waiting(params)) { + if(ch == new_line) + return 0; + while((next_ch = getchar()) != new_line) { + if(next_ch == ' ') + continue; + if(!is_special_token(next_ch) && next_ch != '<' && next_ch != '>') + return 1; + else + break; + } + ungetc(next_ch, stdin); + } + return 0; +} + +void add_word_or_filename(struct w_queue *word_chain, + struct dynamic_array *tmp_word, + struct param_type *params) +{ + /* filenames */ + if(filename_waiting(params) && !params->wrong_command) + add_filename(tmp_word, params); + /* execute command */ + else if(params->is_word) + add_word(word_chain, tmp_word, params); +} + +int validate_redirections(int ch, int next_ch, struct param_type *params) +{ + return (ch == '<' && params->streams.input_stream == NULL) || + ((ch == '>' || (ch == '>' && next_ch == '>')) && + params->streams.output_stream == NULL && + params->streams.output_stream_to_append == NULL); +} + +int is_double_token(struct param_type *params) +{ + return params->tokens == and || params->tokens == or || + params->tokens == append; +} + +/* + * redirection token verification + */ +int stream_redirect_tokens(struct w_queue *word_chain, + struct dynamic_array *tmp_word, int ch, + struct param_type *params) +{ + int next_ch; + next_ch = getchar(); + ungetc(next_ch, stdin); + + if(is_redirect_token(ch, next_ch)) { + add_word_or_filename(word_chain, tmp_word, params); + + if(params->wrong_command) + return 0; + + if(validate_redirections(ch, next_ch, params)) { + params->tokens = (ch == '>' && next_ch == '>') ? append : ch; + if(is_double_token(params)) + getchar(); + return 1; + } else { + fprintf(stderr, "syntax error\n"); + params->wrong_command = 1; + } + } + return 0; +} + +int wrong_streams_redirection(struct param_type *params) +{ + return + (!params->pipeline && (params->tokens == '>' || + params->tokens == append)) || + (params->pipeline && (params->tokens == '>' || + params->tokens == append || + params->tokens == '<')); +} + +int pipeline_token_processing(struct w_queue *word_chain, + struct c_queue *cmdlines, + struct dynamic_array *tmp_word, + struct param_type *params) +{ + char **cmdline = NULL; + if(is_stream_redirection_set(params) && + wrong_streams_redirection(params)) { + /* TODO: add error codes */ + params->wrong_command = 1; + return 0; + } + params->tokens = '|'; + params->pipeline = 1; + cmdline = + create_cmdline(word_chain, w_queue_get_word_count(word_chain)); + + c_queue_push(cmdlines, cmdline); + w_queue_clear(word_chain); + dynarr_drop_word(tmp_word); + return 1; +} + +/* + * verification of special tokens (|, &, &&, ||), except redirection tokens + */ +int special_tokens(struct w_queue *word_chain, struct c_queue *cmdlines, + struct dynamic_array *tmp_word, int ch, + struct param_type *params) +{ + int next_ch; + next_ch = getchar(); + ungetc(next_ch, stdin); + + if(is_special_token(ch)) { + add_word_or_filename(word_chain, tmp_word, params); + + if(params->wrong_command) + return 0; + + if(ch == '|' && next_ch == '|') + params->tokens = or; + else if(ch == '|') { + if(!pipeline_token_processing(word_chain, cmdlines, tmp_word, + params)) + return 0; + } else if(ch == '&' && next_ch == '&') + params->tokens = and; + else if(ch == '&') { + while((ch = getchar()) != new_line) { + if(ch != whitespace && ch != tab) { + fprintf(stderr, "incorrect command\n"); + params->wrong_command = 1; + return 0; + } + } + params->tokens = '&'; + } + if(is_double_token(params)) + getchar(); + return 1; + } + return 0; +} |