diff --git a/src/tools/parser.c b/src/tools/parser.c index 12508c8..ca8af77 100644 --- a/src/tools/parser.c +++ b/src/tools/parser.c @@ -36,17 +36,35 @@ static const char *skip_whitespace(const char *ptr) { } // Parse a token (atom) -static char *parse_token(const char **ptr) { +static char *parse_token(const char **ptr, int line) { const char *start = *ptr; // Skip leading whitespace start = skip_whitespace(start); - if (!*start) return NULL; + if (!*start) { + printf("Error at line:%d\n", line); + return NULL; + } const char *end = start; - // Handle parentheses specially - if (*end == '(' || *end == ')') { + // Handle quoted strings + if (*start == '"') { + end++; // Skip opening quote + // Read until closing quote or end of string + while (*end && *end != '"') { + if (*end == '\\' && *(end + 1)) { + end += 2; // Skip escaped character + } else { + end++; + } + } + if (*end == '"') { + end++; // Include closing quote + } + } + // Handle parentheses as separate tokens + else if (*end == '(' || *end == ')') { end++; } else { // Read until whitespace or parentheses @@ -71,7 +89,6 @@ static ExprNode *parse_list(const char **ptr, int line) { // Skip the opening parenthesis (*ptr)++; - // Parse the operator (first token) *ptr = skip_whitespace(*ptr); if (**ptr == ')') { // Empty list @@ -79,38 +96,28 @@ static ExprNode *parse_list(const char **ptr, int line) { return expr_node_create("nil", line); } - // Parse the operator/first element - char *op_token = parse_token(ptr); - if (!op_token) { - fprintf(stderr, "Error: Expected operator at line %d\n", line); - return NULL; - } + // Parse all children first + ExprNode **temp_children = NULL; + size_t temp_count = 0; - ExprNode *node = expr_node_create(op_token, line); - free(op_token); - - // Parse children while (**ptr && **ptr != ')') { - *ptr = skip_whitespace(*ptr); - if (**ptr == ')') break; - ExprNode *child = parse_expression(ptr, line); if (child) { - // Resize children array properly - ExprNode **new_children = (ExprNode **)safe_malloc(sizeof(ExprNode *) * (node->child_count + 1)); + // Resize temp children array + ExprNode **new_temp = (ExprNode **)safe_malloc(sizeof(ExprNode *) * (temp_count + 1)); // Copy existing children - for (size_t i = 0; i < node->child_count; i++) { - new_children[i] = node->children[i]; + for (size_t i = 0; i < temp_count; i++) { + new_temp[i] = temp_children[i]; } // Add new child - new_children[node->child_count] = child; + new_temp[temp_count] = child; + temp_count++; // Free old array and update - free(node->children); - node->children = new_children; - node->child_count++; + free(temp_children); + temp_children = new_temp; } *ptr = skip_whitespace(*ptr); @@ -122,6 +129,32 @@ static ExprNode *parse_list(const char **ptr, int line) { fprintf(stderr, "Error: Missing closing parenthesis at line %d\n", line); } + // Create the actual node + ExprNode *node; + if (temp_count > 0 && temp_children[0]->child_count == 0) { + // First child is an atom, use it as the operator + node = expr_node_create(temp_children[0]->token, line); + // Move remaining children + node->child_count = temp_count - 1; + if (node->child_count > 0) { + node->children = (ExprNode **)safe_malloc(sizeof(ExprNode *) * node->child_count); + for (size_t i = 0; i < node->child_count; i++) { + node->children[i] = temp_children[i + 1]; + } + } + // Free the first child since we used its token + expr_free(temp_children[0]); + } else { + // No operator or first child is a list + node = expr_node_create("list", line); + node->children = temp_children; + node->child_count = temp_count; + } + + if (temp_count == 0) { + free(temp_children); + } + return node; } @@ -135,7 +168,7 @@ static ExprNode *parse_expression(const char **ptr, int line) { return parse_list(ptr, line); } else { // Parse atom - char *token = parse_token(ptr); + char *token = parse_token(ptr, line); if (token) { ExprNode *node = expr_node_create(token, line); free(token);