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_literal_expr(token_t *token);
expr_t *create_grouping_expr(expr_t *expression);
expr_t *create_variable_expr(token_t *name);
void print_ast(expr_t *expr);
#endif

View file

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

View file

@ -80,6 +80,19 @@ expr_t *create_grouping_expr(expr_t *expression)
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)
{
if (!expr)

View file

@ -133,9 +133,10 @@ value_t visit_binary(expr_t *expr)
}
// String/number comparisons
if ((left.type == VAL_STRING && right.type == VAL_NUMBER) ||
(left.type == VAL_NUMBER && right.type == VAL_STRING)) {
if (left.type == VAL_STRING && right.type == VAL_NUMBER ||
left.type == VAL_NUMBER && right.type == VAL_STRING ) {
runtime_error("Operands must be numbers.", 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) {
value_t obj = evaluate(stmt.as.print.expression);
print_value(&obj);
/* } else if (stmt.type == STMT_EXPR) { */
/* value_t obj = evaluate(stmt.as.expr.expression); */
/* print_value(&obj); */
} else if (stmt.type == STMT_EXPR) {
evaluate(stmt.as.expr.expression);
}
}
void print_statements(stmt_array_t *array)

View file

@ -9,6 +9,7 @@
int current = 0;
token_t *tokens;
expr_t *expression(void);
void synchronize(void);
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);
}
errno = 65;
synchronize();
}
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)) {
error(peek(), message);
} else {
return peek();
}
return NULL;
}
expr_t *primary(void)
@ -98,6 +103,11 @@ expr_t *primary(void)
check(TOKEN_NUMBER) || check(TOKEN_STRING)) {
return create_literal_expr(previous());
}
if (check(TOKEN_IDENTIFIER)) {
return create_variable_expr(previous());
}
if (check(TOKEN_LEFT_PAREN)) {
expr_t *expr = expression();
consume(TOKEN_RIGHT_PAREN, "Expect ')' after expression.");
@ -203,6 +213,33 @@ stmt_t statement(void)
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)
{
if (array->length == array->capacity) {
@ -237,7 +274,7 @@ stmt_array_t *parse(token_t *tks)
statements->length = 0;
statements->capacity = DEFAULT_STMTS_SIZE;
while (!end()) {
stmt_add(statements, statement());
stmt_add(statements, declaration());
}
return statements;
}