Skip to content

Commit 607644b

Browse files
committed
feat: implement Abstract Syntax Tree (AST) structure and node creation functions
1 parent 722d89b commit 607644b

3 files changed

Lines changed: 53 additions & 9 deletions

File tree

include/ast.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ typedef enum {
3535
EXPR_BINARY, EXPR_UNARY, EXPR_LITERAL, EXPR_GROUPING,
3636
EXPR_VARIABLE, EXPR_ASSIGN, EXPR_LOGICAL, EXPR_CALL,
3737
EXPR_GET, EXPR_SET, EXPR_INDEX, EXPR_LIST,
38-
EXPR_DICTIONARY, EXPR_TERNARY, EXPR_LAMBDA
38+
EXPR_DICTIONARY, EXPR_TERNARY, EXPR_LAMBDA,
39+
EXPR_AWAIT
3940
} ExprType;
4041

4142
typedef enum {
@@ -102,6 +103,7 @@ typedef struct { ExprList *elements; } ListExpr;
102103
typedef struct { DictPairList *pairs; } DictionaryExpr;
103104
typedef struct { Expr *condition; Expr *true_branch; Expr *false_branch; } TernaryExpr;
104105
typedef struct { StringList *params; StmtList *body; } LambdaExpr;
106+
typedef struct { Expr *expression; } AwaitExpr;
105107

106108
struct Expr {
107109
ExprType type;
@@ -113,14 +115,14 @@ struct Expr {
113115
GroupingExpr grouping; VariableExpr variable; AssignExpr assign;
114116
LogicalExpr logical; CallExpr call; GetExpr get; SetExpr set;
115117
IndexExpr index; ListExpr list; DictionaryExpr dictionary;
116-
TernaryExpr ternary; LambdaExpr lambda;
118+
TernaryExpr ternary; LambdaExpr lambda; AwaitExpr await_expr;
117119
} as;
118120
};
119121

120122
// --- Statement Data Structures ---
121123
typedef struct { Expr *expression; } ExpressionStmt;
122124
typedef struct { char *name; Expr *initializer; TypeInfo type; bool is_const; } VarDeclStmt;
123-
typedef struct { char *name; StringList *params; StmtList *body; TypeInfo returnType; } FuncDeclStmt;
125+
typedef struct { char *name; StringList *params; StmtList *body; TypeInfo returnType; bool isAsync; } FuncDeclStmt;
124126
typedef struct { char *name; VariableExpr *superclass; StmtList *methods; } ClassDeclStmt;
125127
typedef struct { StringList *modules; } UseDeclStmt;
126128
typedef struct { Expr *condition; Stmt *then_branch; Stmt *else_branch; } IfStmt;
@@ -163,10 +165,11 @@ Expr *createListExpr(ExprList *elements, int line, int column);
163165
Expr *createDictionaryExpr(DictPairList *pairs, int line, int column);
164166
Expr *createTernaryExpr(Expr *cond, Expr *true_br, Expr *false_br, int line, int column);
165167
Expr *createLambdaExpr(StringList *params, StmtList *body, int line, int column);
168+
Expr *createAwaitExpr(Expr *expression, int line, int column);
166169

167170
Stmt *createExpressionStmt(Expr *expression, int line, int column);
168171
Stmt *createVarDeclStmt(const char *name, Expr *init, bool is_const, int line, int column);
169-
Stmt *createFuncDeclStmt(const char *name, StringList *params, StmtList *body, int line, int column);
172+
Stmt *createFuncDeclStmt(const char *name, StringList *params, StmtList *body, bool isAsync, int line, int column);
170173
Stmt *createClassDeclStmt(const char *name, VariableExpr *super, StmtList *methods, int line, int column);
171174
Stmt *createUseDeclStmt(StringList *modules, int line, int column);
172175
Stmt *createIfStmt(Expr *cond, Stmt *then_br, Stmt *else_br, int line, int column);

src/compiler/parser/ast.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,15 @@ Expr *createLambdaExpr(StringList *params, StmtList *body, int line,
303303
return expr;
304304
}
305305

306+
Expr *createAwaitExpr(Expr *expression, int line, int column) {
307+
Expr *expr = ALLOCATE(Expr, 1);
308+
expr->type = EXPR_AWAIT;
309+
expr->line = line;
310+
expr->column = column;
311+
expr->as.await_expr.expression = expression;
312+
return expr;
313+
}
314+
306315
// --- Statement Creation Functions ---
307316

308317
Stmt *createExpressionStmt(Expr *expression, int line, int column) {
@@ -332,14 +341,15 @@ Stmt *createVarDeclStmt(const char *name, Expr *init, bool is_const, int line,
332341
}
333342

334343
Stmt *createFuncDeclStmt(const char *name, StringList *params, StmtList *body,
335-
int line, int column) {
344+
bool isAsync, int line, int column) {
336345
Stmt *stmt = ALLOCATE(Stmt, 1);
337346
stmt->type = STMT_FUNC_DECL;
338347
stmt->line = line;
339348
stmt->column = column;
340349
stmt->as.func_decl.name = strdup(name);
341350
stmt->as.func_decl.params = params;
342351
stmt->as.func_decl.body = body;
352+
stmt->as.func_decl.isAsync = isAsync;
343353
return stmt;
344354
}
345355

@@ -534,6 +544,9 @@ void freeExpr(Expr *expr) {
534544
freeStringList(expr->as.lambda.params);
535545
freeStmtList(expr->as.lambda.body);
536546
break;
547+
case EXPR_AWAIT:
548+
freeExpr(expr->as.await_expr.expression);
549+
break;
537550
}
538551

539552
FREE(Expr, expr);

src/compiler/parser/parser.c

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,15 @@ StmtList *parse(Parser *parser) {
161161
// === Declarations ===
162162

163163
static Stmt *declaration(Parser *p) {
164+
if (match(p, 1, TOKEN_ASYNC)) {
165+
if (match(p, 1, TOKEN_FUNC))
166+
return funcDecl(p, "function", true);
167+
// TODO: Handle async arrow functions if supported later
168+
parserError(p, "Expect 'func' after 'async'.");
169+
return NULL;
170+
}
164171
if (match(p, 1, TOKEN_FUNC))
165-
return funcDecl(p, "function");
172+
return funcDecl(p, "function", false);
166173
if (match(p, 1, TOKEN_CLASS))
167174
return classDecl(p);
168175
if (match(p, 1, TOKEN_USE))
@@ -172,7 +179,7 @@ static Stmt *declaration(Parser *p) {
172179
return statement(p);
173180
}
174181

175-
static Stmt *funcDecl(Parser *p, const char *kind) {
182+
static Stmt *funcDecl(Parser *p, const char *kind, bool isAsync) {
176183
(void)kind;
177184
Token nameToken = consume(p, TOKEN_IDENTIFIER, "Expect function name.");
178185
char *name = tokenToString(nameToken);
@@ -194,7 +201,7 @@ static Stmt *funcDecl(Parser *p, const char *kind) {
194201

195202
StmtList *body = block(p);
196203

197-
Stmt *stmt = createFuncDeclStmt(name, params, body, nameToken.line, 0);
204+
Stmt *stmt = createFuncDeclStmt(name, params, body, isAsync, nameToken.line, 0);
198205
free(name);
199206
return stmt;
200207
}
@@ -216,7 +223,23 @@ static Stmt *classDecl(Parser *p) {
216223

217224
StmtList *methods = createStmtList();
218225
while (!check(p, TOKEN_RIGHT_BRACE) && !isAtEnd(p)) {
219-
Stmt *method = funcDecl(p, "method");
226+
bool isAsync = false;
227+
if (match(p, 1, TOKEN_ASYNC)) {
228+
isAsync = true;
229+
// consume FUNC if present (methods might just be identifier in some langs, but here it calls funcDecl which expects identifier)
230+
// Wait, funcDecl starts with identifier consumption.
231+
// check if `funcDecl` handles `func` keyword? No, `declaration` consumes `func` before calling `funcDecl`.
232+
// So for methods in classDecl, how are they parsed?
233+
// `createClassDeclStmt` calls `funcDecl`.
234+
// `classDecl` loop calls `funcDecl(p, "method")`.
235+
// `funcDecl` consumes IDENTIFIER name.
236+
// So methods don't have `func` keyword?
237+
// Let's check `funcDecl` implementation:
238+
// `Token nameToken = consume(p, TOKEN_IDENTIFIER, "Expect function name.");`
239+
// So yes, methods are `methodName() {}`.
240+
}
241+
// Check if `async` was consumed. If so, pass true.
242+
Stmt *method = funcDecl(p, "method", isAsync);
220243
appendStmt(methods, method);
221244
}
222245

@@ -596,6 +619,11 @@ static Expr *factor(Parser *p) {
596619
}
597620

598621
static Expr *unary(Parser *p) {
622+
if (match(p, 1, TOKEN_AWAIT)) {
623+
Token op = previous(p);
624+
Expr *right = unary(p);
625+
return createAwaitExpr(right, op.line, 0);
626+
}
599627
if (match(p, 2, TOKEN_BANG, TOKEN_MINUS)) {
600628
Token op = previous(p);
601629
char *opStr = tokenToString(op);

0 commit comments

Comments
 (0)