Support variable syntax
This commit is contained in:
parent
9818c21097
commit
dc566b4345
5 changed files with 58 additions and 8 deletions
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
13
src/ast.c
13
src/ast.c
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
41
src/parser.c
41
src/parser.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue