Support variable syntax

This commit is contained in:
Night Kaly 2025-01-06 12:09:00 +00:00
parent 9818c21097
commit dc566b4345
Signed by: night0721
SSH key fingerprint: SHA256:B/hgVwUoBpx5vdNsXl9w8XwZljA9766uk6T4ubZp5HM
5 changed files with 58 additions and 8 deletions

View file

@ -102,6 +102,7 @@ expr_t *create_binary_expr(token_t *operator, expr_t *left, expr_t *right);
expr_t *create_unary_expr(token_t *operator, expr_t *right); expr_t *create_unary_expr(token_t *operator, expr_t *right);
expr_t *create_literal_expr(token_t *token); expr_t *create_literal_expr(token_t *token);
expr_t *create_grouping_expr(expr_t *expression); expr_t *create_grouping_expr(expr_t *expression);
expr_t *create_variable_expr(token_t *name);
void print_ast(expr_t *expr); void print_ast(expr_t *expr);
#endif #endif

View file

@ -15,7 +15,6 @@ typedef enum {
STMT_PRINT, STMT_PRINT,
STMT_VAR, STMT_VAR,
STMT_WHILE, STMT_WHILE,
STMT_COUNT,
} stmt_type_t; } stmt_type_t;
typedef struct stmt_t { typedef struct stmt_t {

View file

@ -80,6 +80,19 @@ expr_t *create_grouping_expr(expr_t *expression)
return expr; return expr;
} }
expr_t *create_variable_expr(token_t *name)
{
expr_t *expr = malloc(sizeof(expr_t));
expr->type = EXPR_VARIABLE;
expr->line = name->line;
expr->as.variable.name.type = name->type;
char *name_val = strdup(name->value);
expr->as.variable.name.value = name_val;
expr->as.variable.name.line = name->line;
return expr;
}
void print_ast(expr_t *expr) void print_ast(expr_t *expr)
{ {
if (!expr) if (!expr)

View file

@ -133,9 +133,10 @@ value_t visit_binary(expr_t *expr)
} }
// String/number comparisons // String/number comparisons
if ((left.type == VAL_STRING && right.type == VAL_NUMBER) || if (left.type == VAL_STRING && right.type == VAL_NUMBER ||
(left.type == VAL_NUMBER && right.type == VAL_STRING)) { left.type == VAL_NUMBER && right.type == VAL_STRING ) {
runtime_error("Operands must be numbers.", expr->line); runtime_error("Operands must be numbers.", expr->line);
} }
runtime_error("Operands must be two numbers or two strings.", expr->line); runtime_error("Operands must be two numbers or two strings.", expr->line);
@ -238,9 +239,8 @@ void print_statement(stmt_t stmt)
if (stmt.type == STMT_PRINT) { if (stmt.type == STMT_PRINT) {
value_t obj = evaluate(stmt.as.print.expression); value_t obj = evaluate(stmt.as.print.expression);
print_value(&obj); print_value(&obj);
/* } else if (stmt.type == STMT_EXPR) { */ } else if (stmt.type == STMT_EXPR) {
/* value_t obj = evaluate(stmt.as.expr.expression); */ evaluate(stmt.as.expr.expression);
/* print_value(&obj); */
} }
} }
void print_statements(stmt_array_t *array) void print_statements(stmt_array_t *array)

View file

@ -9,6 +9,7 @@
int current = 0; int current = 0;
token_t *tokens; token_t *tokens;
expr_t *expression(void); expr_t *expression(void);
void synchronize(void);
void error(token_t *token, char *message) void error(token_t *token, char *message)
{ {
@ -18,6 +19,7 @@ void error(token_t *token, char *message)
fprintf(stderr, "[line %d] at '%s': %s\n", token->line, token->value, message); fprintf(stderr, "[line %d] at '%s': %s\n", token->line, token->value, message);
} }
errno = 65; errno = 65;
synchronize();
} }
void free_expr(expr_t *expr) void free_expr(expr_t *expr)
@ -86,10 +88,13 @@ int check(token_type_t type)
} }
} }
void consume(token_type_t type, char *message) { token_t *consume(token_type_t type, char *message) {
if (!check(type)) { if (!check(type)) {
error(peek(), message); error(peek(), message);
} else {
return peek();
} }
return NULL;
} }
expr_t *primary(void) expr_t *primary(void)
@ -98,6 +103,11 @@ expr_t *primary(void)
check(TOKEN_NUMBER) || check(TOKEN_STRING)) { check(TOKEN_NUMBER) || check(TOKEN_STRING)) {
return create_literal_expr(previous()); return create_literal_expr(previous());
} }
if (check(TOKEN_IDENTIFIER)) {
return create_variable_expr(previous());
}
if (check(TOKEN_LEFT_PAREN)) { if (check(TOKEN_LEFT_PAREN)) {
expr_t *expr = expression(); expr_t *expr = expression();
consume(TOKEN_RIGHT_PAREN, "Expect ')' after expression."); consume(TOKEN_RIGHT_PAREN, "Expect ')' after expression.");
@ -203,6 +213,33 @@ stmt_t statement(void)
return expression_stmt(); return expression_stmt();
} }
stmt_t var_declaration(void)
{
token_t *name = consume(TOKEN_IDENTIFIER, "Expect variable name.");
expr_t *initializer;
if (check(TOKEN_EQUAL)) {
initializer = expression();
}
consume(TOKEN_SEMICOLON, "Expect ';' after variable declaration.");
return (stmt_t) {
.type = STMT_VAR,
.as.variable.name.type = name->type,
.as.variable.name.value = name->value,
.as.variable.name.line = name->line,
.as.variable.initializer = initializer,
};
}
stmt_t declaration(void)
{
if (check(TOKEN_VAR))
return var_declaration();
return statement();
}
void stmt_add(stmt_array_t *array, stmt_t stmt) void stmt_add(stmt_array_t *array, stmt_t stmt)
{ {
if (array->length == array->capacity) { if (array->length == array->capacity) {
@ -237,7 +274,7 @@ stmt_array_t *parse(token_t *tks)
statements->length = 0; statements->length = 0;
statements->capacity = DEFAULT_STMTS_SIZE; statements->capacity = DEFAULT_STMTS_SIZE;
while (!end()) { while (!end()) {
stmt_add(statements, statement()); stmt_add(statements, declaration());
} }
return statements; return statements;
} }