From 0fbc3364dbd384658f0b31757041b094a1be0bf3 Mon Sep 17 00:00:00 2001 From: erwann lesech Date: Sat, 20 Jan 2024 13:51:48 +0100 Subject: [PATCH 1/2] fix: init fix --- src/ast/ast.c | 7 ++++ src/ast/ast.h | 10 ++++- src/lexer/lexer.c | 3 +- src/lexer/tests/lexer2_tests.c | 67 +++++++++++++++++++++++++++++++-- src/lexer/token.h | 1 + src/parser/parser_element.c | 11 ++++-- src/parser/tests/parser_tests.c | 19 ++++++++++ 7 files changed, 110 insertions(+), 8 deletions(-) diff --git a/src/ast/ast.c b/src/ast/ast.c index 2dae1898..616e1a98 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -26,6 +26,13 @@ struct ast_node *ast_node_word(char *value) return node; } +struct ast_node *ast_node_word_double_quote(char *value) +{ + struct ast_node *node = ast_node_new(AST_WORD_DOUBLE_QUOTE); + node->value = value; + return node; +} + void ast_append(struct ast_node *parent, struct ast_node *child) { if (parent->children == NULL) diff --git a/src/ast/ast.h b/src/ast/ast.h index 0fda59fa..47babb3b 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -37,7 +37,8 @@ enum ast_type AST_OR, AST_COMMAND, AST_WORD_ASSIGNMENT, - AST_VARIABLE + AST_VARIABLE, + AST_WORD_DOUBLE_QUOTE }; /** @@ -79,6 +80,13 @@ void ast_free(struct ast_node *node); */ struct ast_node *ast_node_word(char *value); +/** + * \brief Create a new AST node of type AST_WORD_DOUBLE_QUOTE. + * \param value The value of the node. + * \return The new node. + */ +struct ast_node *ast_node_word_double_quote(char *value); + /** * \brief Convert an AST type to a string. * \param type The type to convert. diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index 89b5f2a4..0d1a9b80 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -317,7 +317,8 @@ struct token parse_input_for_tok(struct lexer *lexer) lexer->curr_tok.type = TOKEN_EOL; } // Else it's a word - token.type = TOKEN_WORD; + token.type = lexer->curr_tok.type == TOKEN_DOUBLE_QUOTE ? TOKEN_WORD_DOUBLE_QUOTE + : TOKEN_WORD; token.data = word; return token; } diff --git a/src/lexer/tests/lexer2_tests.c b/src/lexer/tests/lexer2_tests.c index 2422ef5f..93a6eee3 100644 --- a/src/lexer/tests/lexer2_tests.c +++ b/src/lexer/tests/lexer2_tests.c @@ -928,7 +928,7 @@ Test(lexer2, variable_distinction_access_double_quote_with_string) token_free(tok); tok = lexer_pop(lexer); - cr_assert_eq(tok.type, TOKEN_WORD, "got %d", tok.type); + cr_assert_eq(tok.type, TOKEN_WORD_DOUBLE_QUOTE, "got %d", tok.type); cr_assert_str_eq(tok.data, "variable:"); token_free(tok); @@ -1099,9 +1099,70 @@ Test(lexer2, personalized_variable2) token_free(tok); tok = lexer_pop(lexer); - cr_assert_eq(tok.type, TOKEN_VARIABLE); - cr_assert_str_eq(tok.data, "$a"); + cr_assert_eq(tok.type, TOKEN_VARIABLE, "got %d", tok.type); + cr_assert_str_eq(tok.data, "$a", "got %s", tok.data); token_free(tok); lexer_free(lexer); } + +Test (lexer2, double_quote_space) +{ + struct lexer *lexer = lexer_new("h=\"Hello\"; w=\"World\"; echo \"$h, ${w}!\""); + struct token tok = lexer_pop(lexer); + cr_assert_eq(tok.type, TOKEN_WORD_ASSIGNMENT); + cr_assert_str_eq(tok.data, "h"); + token_free(tok); + + tok = lexer_pop(lexer); + cr_assert_eq(tok.type, TOKEN_WORD); + cr_assert_str_eq(tok.data, "Hello"); + token_free(tok); + + tok = lexer_pop(lexer); + cr_assert_eq(tok.type, TOKEN_SEMICOLON); + cr_assert_str_eq(tok.data, ";"); + token_free(tok); + + tok = lexer_pop(lexer); + cr_assert_eq(tok.type, TOKEN_WORD_ASSIGNMENT); + cr_assert_str_eq(tok.data, "w"); + token_free(tok); + + tok = lexer_pop(lexer); + cr_assert_eq(tok.type, TOKEN_WORD); + cr_assert_str_eq(tok.data, "World"); + token_free(tok); + + tok = lexer_pop(lexer); + cr_assert_eq(tok.type, TOKEN_SEMICOLON); + cr_assert_str_eq(tok.data, ";"); + token_free(tok); + + tok = lexer_pop(lexer); + cr_assert_eq(tok.type, TOKEN_WORD); + cr_assert_str_eq(tok.data, "echo"); + token_free(tok); + + tok = lexer_pop(lexer); + cr_assert_eq(tok.type, TOKEN_VARIABLE); + cr_assert_str_eq(tok.data, "$h"); + token_free(tok); + + tok = lexer_pop(lexer); + cr_assert_eq(tok.type, TOKEN_WORD_DOUBLE_QUOTE); + cr_assert_str_eq(tok.data, ", "); + token_free(tok); + + tok = lexer_pop(lexer); + cr_assert_eq(tok.type, TOKEN_VARIABLE); + cr_assert_str_eq(tok.data, "$w"); + token_free(tok); + + tok = lexer_pop(lexer); + cr_assert_eq(tok.type, TOKEN_WORD); + cr_assert_str_eq(tok.data, "!"); + token_free(tok); + + lexer_free(lexer); +} \ No newline at end of file diff --git a/src/lexer/token.h b/src/lexer/token.h index b012d561..5ef1295f 100644 --- a/src/lexer/token.h +++ b/src/lexer/token.h @@ -36,6 +36,7 @@ enum token_type TOKEN_IONUMBER, // [0-9]+ TOKEN_REDIR, // >, <, >>, >&, <&, >|, <> TOKEN_DOUBLE_QUOTE, // " + TOKEN_WORD_DOUBLE_QUOTE, // "[a-zA-Z0-9_ ]*" TOKEN_WORD_ASSIGNMENT, // variable= TOKEN_VARIABLE, // $variable diff --git a/src/parser/parser_element.c b/src/parser/parser_element.c index c8635830..4e27385c 100644 --- a/src/parser/parser_element.c +++ b/src/parser/parser_element.c @@ -159,12 +159,12 @@ struct ast_node *simple_command(struct lexer *lexer) child2 = prefix(lexer); } } - if (parser_peek(lexer) != TOKEN_WORD) + if (parser_peek(lexer) != TOKEN_WORD && parser_peek(lexer) != TOKEN_WORD_DOUBLE_QUOTE) { return current; } } - if (parser_peek(lexer) == TOKEN_WORD) + if (parser_peek(lexer) == TOKEN_WORD || parser_peek(lexer) == TOKEN_WORD_DOUBLE_QUOTE) { char *value = lexer_peek(lexer).data; if (strcmp(value, "while") == 0 || strcmp(value, "until") == 0 @@ -209,11 +209,16 @@ struct ast_node *element(struct lexer *lexer) || parser_peek(lexer) == TOKEN_WORD_ASSIGNMENT || parser_peek(lexer) == TOKEN_NEGATE) { - // printf("value=%s\n", lexer_peek(lexer).data); struct ast_node *curr = ast_node_word(lexer_peek(lexer).data); parser_pop(lexer); return curr; } + else if (parser_peek(lexer) == TOKEN_WORD_DOUBLE_QUOTE) + { + struct ast_node *curr = ast_node_word_double_quote(lexer_peek(lexer).data); + parser_pop(lexer); + return curr; + } // printf("Error: element\n"); ast_free(current); diff --git a/src/parser/tests/parser_tests.c b/src/parser/tests/parser_tests.c index dd182b27..976a2c88 100644 --- a/src/parser/tests/parser_tests.c +++ b/src/parser/tests/parser_tests.c @@ -236,3 +236,22 @@ Test(parser, error4) lexer_free(lexer); ast_free(node); } + +Test(parser, custom_double_quote) +{ + struct lexer *lexer = lexer_new("echo \"variable=$a\""); + printf("LEXER:\n"); + struct ast_node *node = parse(lexer); + printf("AST:\n"); + print_ast(node, 0); + cr_assert_eq(node->type, AST_COMMAND_LIST); + cr_assert_eq(node->children[0]->type, AST_SIMPLE_COMMAND); + cr_assert_eq(node->children[0]->children[0]->type, AST_WORD); + cr_assert_str_eq(node->children[0]->children[0]->value, "echo"); + cr_assert_eq(node->children[0]->children[1]->type, AST_WORD_DOUBLE_QUOTE); + cr_assert_str_eq(node->children[0]->children[1]->value, "variable="); + cr_assert_eq(node->children[0]->children[2]->type, AST_VARIABLE); + cr_assert_str_eq(node->children[0]->children[2]->value, "$a"); + lexer_free(lexer); + ast_free(node); +} \ No newline at end of file From 70e20b6e8429c256ec815f80fa508cf5ddeb167a Mon Sep 17 00:00:00 2001 From: erwann lesech Date: Sat, 20 Jan 2024 14:08:01 +0100 Subject: [PATCH 2/2] fix: fix spaces word in double quote --- src/execute/utils/ast_variable.c | 2 +- src/execute/utils/builtin.c | 2 +- src/parser/tests/parser_tests.c | 14 ++------------ 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/execute/utils/ast_variable.c b/src/execute/utils/ast_variable.c index 79e7ba25..0c393114 100644 --- a/src/execute/utils/ast_variable.c +++ b/src/execute/utils/ast_variable.c @@ -130,7 +130,7 @@ int ast_eval_assignment(struct ast_node *node) */ char *handle_word(struct ast_node *node) { - if (node->type == AST_WORD) + if (node->type == AST_WORD || node->type == AST_WORD_DOUBLE_QUOTE) { return node->value; } diff --git a/src/execute/utils/builtin.c b/src/execute/utils/builtin.c index 4cb12a08..630e4fe5 100644 --- a/src/execute/utils/builtin.c +++ b/src/execute/utils/builtin.c @@ -67,7 +67,7 @@ void print_echo(struct ast_node *node, int enable_escapes, int j) } } if (i != node->children_count - 1 - && node->children[i]->type != AST_VARIABLE) + && node->children[i]->type != AST_VARIABLE && node->children[i]->type != AST_WORD_DOUBLE_QUOTE) putchar(' '); } } diff --git a/src/parser/tests/parser_tests.c b/src/parser/tests/parser_tests.c index 976a2c88..c9951023 100644 --- a/src/parser/tests/parser_tests.c +++ b/src/parser/tests/parser_tests.c @@ -239,19 +239,9 @@ Test(parser, error4) Test(parser, custom_double_quote) { - struct lexer *lexer = lexer_new("echo \"variable=$a\""); - printf("LEXER:\n"); + struct lexer *lexer = lexer_new("echo \"variable= $a\""); struct ast_node *node = parse(lexer); - printf("AST:\n"); - print_ast(node, 0); - cr_assert_eq(node->type, AST_COMMAND_LIST); - cr_assert_eq(node->children[0]->type, AST_SIMPLE_COMMAND); - cr_assert_eq(node->children[0]->children[0]->type, AST_WORD); - cr_assert_str_eq(node->children[0]->children[0]->value, "echo"); - cr_assert_eq(node->children[0]->children[1]->type, AST_WORD_DOUBLE_QUOTE); - cr_assert_str_eq(node->children[0]->children[1]->value, "variable="); - cr_assert_eq(node->children[0]->children[2]->type, AST_VARIABLE); - cr_assert_str_eq(node->children[0]->children[2]->value, "$a"); + lexer_free(lexer); ast_free(node); } \ No newline at end of file