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)
|
// 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);
|
||||||
|
|
Loading…
Reference in New Issue