parser fixes
This commit is contained in:
parent
37ce661648
commit
3453b0fcd6
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue