parser fixes

This commit is contained in:
zongor 2025-09-21 10:09:14 -07:00
parent 37ce661648
commit 3453b0fcd6
1 changed files with 60 additions and 27 deletions

View File

@ -36,17 +36,35 @@ static const char *skip_whitespace(const char *ptr) {
} }
// Parse a token (atom) // Parse a token (atom)
static char *parse_token(const char **ptr) { static char *parse_token(const char **ptr, int line) {
const char *start = *ptr; const char *start = *ptr;
// Skip leading whitespace // Skip leading whitespace
start = skip_whitespace(start); start = skip_whitespace(start);
if (!*start) return NULL; if (!*start) {
printf("Error at line:%d\n", line);
return NULL;
}
const char *end = start; const char *end = start;
// Handle parentheses specially // Handle quoted strings
if (*end == '(' || *end == ')') { 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++; end++;
} else { } else {
// Read until whitespace or parentheses // Read until whitespace or parentheses
@ -71,7 +89,6 @@ static ExprNode *parse_list(const char **ptr, int line) {
// Skip the opening parenthesis // Skip the opening parenthesis
(*ptr)++; (*ptr)++;
// Parse the operator (first token)
*ptr = skip_whitespace(*ptr); *ptr = skip_whitespace(*ptr);
if (**ptr == ')') { if (**ptr == ')') {
// Empty list // Empty list
@ -79,38 +96,28 @@ static ExprNode *parse_list(const char **ptr, int line) {
return expr_node_create("nil", line); return expr_node_create("nil", line);
} }
// Parse the operator/first element // Parse all children first
char *op_token = parse_token(ptr); ExprNode **temp_children = NULL;
if (!op_token) { size_t temp_count = 0;
fprintf(stderr, "Error: Expected operator at line %d\n", line);
return NULL;
}
ExprNode *node = expr_node_create(op_token, line);
free(op_token);
// Parse children
while (**ptr && **ptr != ')') { while (**ptr && **ptr != ')') {
*ptr = skip_whitespace(*ptr);
if (**ptr == ')') break;
ExprNode *child = parse_expression(ptr, line); ExprNode *child = parse_expression(ptr, line);
if (child) { if (child) {
// Resize children array properly // Resize temp children array
ExprNode **new_children = (ExprNode **)safe_malloc(sizeof(ExprNode *) * (node->child_count + 1)); ExprNode **new_temp = (ExprNode **)safe_malloc(sizeof(ExprNode *) * (temp_count + 1));
// Copy existing children // Copy existing children
for (size_t i = 0; i < node->child_count; i++) { for (size_t i = 0; i < temp_count; i++) {
new_children[i] = node->children[i]; new_temp[i] = temp_children[i];
} }
// Add new child // Add new child
new_children[node->child_count] = child; new_temp[temp_count] = child;
temp_count++;
// Free old array and update // Free old array and update
free(node->children); free(temp_children);
node->children = new_children; temp_children = new_temp;
node->child_count++;
} }
*ptr = skip_whitespace(*ptr); *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); 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; return node;
} }
@ -135,7 +168,7 @@ static ExprNode *parse_expression(const char **ptr, int line) {
return parse_list(ptr, line); return parse_list(ptr, line);
} else { } else {
// Parse atom // Parse atom
char *token = parse_token(ptr); char *token = parse_token(ptr, line);
if (token) { if (token) {
ExprNode *node = expr_node_create(token, line); ExprNode *node = expr_node_create(token, line);
free(token); free(token);