Skip to content

Commit d6fa1da

Browse files
committed
feat(semantic): add for/while
1 parent 5a17e94 commit d6fa1da

File tree

10 files changed

+294
-49
lines changed

10 files changed

+294
-49
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Objetivo: construir um compilador que lê um subconjunto de C e transpila para L
44

55
Resumo do MVP de linguagem suportada:
66
- Tipos: int, float, bool (true/false), char (como número), string opcional.
7-
- Estruturas: declaração de variáveis, atribuição, expressões aritméticas/lógicas, if/else, while, função (definição/chamada) e return.
7+
- Estruturas: declaração de variáveis, atribuição, expressões aritméticas/lógicas, if/else, while, for (apenas uma declaração), função (definição/chamada) e return.
88
- I/O: mapeamento simples printf/puts -> print; scanf opcional.
99
- Saída Lua: usar local para variáveis, funções Lua equivalentes, operadores com mesma semântica; arrays opcionais como tabelas.
1010

docs/sprints/4.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,12 @@ printf("3\n");
146146

147147
### Estudar e preparar apresentação/entrevista e roteiro de demo
148148

149-
- [ ] responsável: @andrelopesdesousa
150-
- [ ] responsável: @BeyondMagic
151-
- [ ] responsável: @Liviarodrigues1
152-
- [ ] responsável: @marcomarquesdc
153-
- [ ] responsável: @Sophiassilva
149+
- [ ] Léxico: responsável: @BeyondMagic
150+
- [ ] Sintático: responsável: @Sophiassilva
151+
- [ ] Semântico: responsável: @Liviarodrigues1
152+
- [ ] Intermediário: responsável: @marcomarquesdc
153+
- [ ] Geração de Código: responsável: @andrelopesdesousa
154+
154155

155156
## Critérios de pronto por fase
156157
- Léxico: todos tokens do MVP reconhecidos; sem vazamentos de memória.

src/ast.c

Lines changed: 89 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ static void ensure_capacity(void **buffer, size_t elem_size, size_t *capacity, s
3636
*capacity = new_capacity;
3737
}
3838

39+
static void ast_expr_destroy(AstExpr *expr);
40+
static void ast_stmt_destroy(AstStmt *stmt);
41+
3942
AstProgram *ast_program_create(void)
4043
{
4144
AstProgram *program = xcalloc(1, sizeof(AstProgram));
@@ -218,58 +221,75 @@ void ast_stmt_list_destroy(AstStmtList *list)
218221
}
219222
for (size_t i = 0; i < list->count; ++i)
220223
{
221-
AstStmt *stmt = list->items[i];
222-
if (!stmt)
223-
{
224-
continue;
225-
}
226-
switch (stmt->kind)
227-
{
228-
case STMT_BLOCK:
229-
ast_stmt_list_destroy(&stmt->data.block.statements);
230-
break;
231-
case STMT_DECL:
232-
free(stmt->data.decl.name);
233-
if (stmt->data.decl.init)
234-
{
235-
ast_expr_destroy(stmt->data.decl.init);
236-
}
237-
if (stmt->data.decl.array_init)
238-
{
239-
ast_expr_destroy(stmt->data.decl.array_init);
240-
}
241-
break;
242-
case STMT_ASSIGN:
243-
free(stmt->data.assign.name);
244-
ast_expr_destroy(stmt->data.assign.value);
245-
break;
246-
case STMT_ARRAY_ASSIGN:
247-
free(stmt->data.array_assign.name);
248-
ast_expr_destroy(stmt->data.array_assign.index);
249-
ast_expr_destroy(stmt->data.array_assign.value);
250-
break;
251-
case STMT_EXPR:
252-
case STMT_RETURN:
253-
if (stmt->data.expr)
254-
{
255-
ast_expr_destroy(stmt->data.expr);
256-
}
257-
break;
258-
}
259-
free(stmt);
224+
ast_stmt_destroy(list->items[i]);
260225
}
261226
free(list->items);
262227
list->items = NULL;
263228
list->count = 0;
264229
list->capacity = 0;
265230
}
266231

232+
static void ast_stmt_destroy(AstStmt *stmt)
233+
{
234+
if (!stmt)
235+
{
236+
return;
237+
}
238+
switch (stmt->kind)
239+
{
240+
case STMT_BLOCK:
241+
ast_stmt_list_destroy(&stmt->data.block.statements);
242+
break;
243+
case STMT_DECL:
244+
free(stmt->data.decl.name);
245+
if (stmt->data.decl.init)
246+
{
247+
ast_expr_destroy(stmt->data.decl.init);
248+
}
249+
if (stmt->data.decl.array_init)
250+
{
251+
ast_expr_destroy(stmt->data.decl.array_init);
252+
}
253+
break;
254+
case STMT_ASSIGN:
255+
free(stmt->data.assign.name);
256+
ast_expr_destroy(stmt->data.assign.value);
257+
break;
258+
case STMT_ARRAY_ASSIGN:
259+
free(stmt->data.array_assign.name);
260+
ast_expr_destroy(stmt->data.array_assign.index);
261+
ast_expr_destroy(stmt->data.array_assign.value);
262+
break;
263+
case STMT_WHILE:
264+
ast_expr_destroy(stmt->data.while_stmt.condition);
265+
ast_stmt_destroy(stmt->data.while_stmt.body);
266+
break;
267+
case STMT_FOR:
268+
ast_stmt_destroy(stmt->data.for_stmt.init);
269+
ast_expr_destroy(stmt->data.for_stmt.condition);
270+
ast_stmt_destroy(stmt->data.for_stmt.post);
271+
ast_stmt_destroy(stmt->data.for_stmt.body);
272+
break;
273+
case STMT_EXPR:
274+
case STMT_RETURN:
275+
if (stmt->data.expr)
276+
{
277+
ast_expr_destroy(stmt->data.expr);
278+
}
279+
break;
280+
}
281+
free(stmt);
282+
}
283+
267284
AstBlock ast_block_from_list(AstStmtList *list)
268285
{
269286
AstBlock block = {0};
270287
if (list)
271288
{
272289
block.statements = *list;
290+
list->items = NULL;
291+
list->count = 0;
292+
list->capacity = 0;
273293
}
274294
return block;
275295
}
@@ -282,6 +302,10 @@ AstStmt *ast_stmt_make_block(AstBlock *block)
282302
{
283303
stmt->data.block = *block;
284304
}
305+
else
306+
{
307+
stmt->data.block.statements = ast_stmt_list_make();
308+
}
285309
return stmt;
286310
}
287311

@@ -333,6 +357,26 @@ AstStmt *ast_stmt_make_array_assign(char *name, AstExpr *index, AstExpr *value)
333357
return stmt;
334358
}
335359

360+
AstStmt *ast_stmt_make_while(AstExpr *condition, AstStmt *body)
361+
{
362+
AstStmt *stmt = xcalloc(1, sizeof(AstStmt));
363+
stmt->kind = STMT_WHILE;
364+
stmt->data.while_stmt.condition = condition;
365+
stmt->data.while_stmt.body = body;
366+
return stmt;
367+
}
368+
369+
AstStmt *ast_stmt_make_for(AstStmt *init, AstExpr *condition, AstStmt *post, AstStmt *body)
370+
{
371+
AstStmt *stmt = xcalloc(1, sizeof(AstStmt));
372+
stmt->kind = STMT_FOR;
373+
stmt->data.for_stmt.init = init;
374+
stmt->data.for_stmt.condition = condition;
375+
stmt->data.for_stmt.post = post;
376+
stmt->data.for_stmt.body = body;
377+
return stmt;
378+
}
379+
336380
AstStmt *ast_stmt_make_expr(AstExpr *expr)
337381
{
338382
AstStmt *stmt = xcalloc(1, sizeof(AstStmt));
@@ -424,6 +468,9 @@ AstExpr *ast_expr_make_call(char *callee, AstExprList *args)
424468
if (args)
425469
{
426470
expr->data.call.args = *args;
471+
args->items = NULL;
472+
args->count = 0;
473+
args->capacity = 0;
427474
}
428475
return expr;
429476
}
@@ -436,6 +483,9 @@ AstExpr *ast_expr_make_array_literal(AstExprList *elements)
436483
if (elements)
437484
{
438485
expr->data.array_literal.elements = *elements;
486+
elements->items = NULL;
487+
elements->count = 0;
488+
elements->capacity = 0;
439489
}
440490
return expr;
441491
}

src/ast.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ typedef struct AstStmt
142142
STMT_DECL,
143143
STMT_ASSIGN,
144144
STMT_ARRAY_ASSIGN,
145+
STMT_WHILE,
146+
STMT_FOR,
145147
STMT_EXPR,
146148
STMT_RETURN
147149
} kind;
@@ -171,6 +173,18 @@ typedef struct AstStmt
171173
TypeKind element_type;
172174
size_t array_size;
173175
} array_assign;
176+
struct
177+
{
178+
AstExpr *condition;
179+
struct AstStmt *body;
180+
} while_stmt;
181+
struct
182+
{
183+
struct AstStmt *init;
184+
AstExpr *condition;
185+
struct AstStmt *post;
186+
struct AstStmt *body;
187+
} for_stmt;
174188
AstExpr *expr;
175189
} data;
176190
} AstStmt;
@@ -214,6 +228,8 @@ AstStmt *ast_stmt_make_decl(TypeKind type, char *name, AstExpr *init);
214228
AstStmt *ast_stmt_make_assign(char *name, AstExpr *value);
215229
AstStmt *ast_stmt_make_array_decl(TypeKind type, char *name, size_t size, AstExpr *init);
216230
AstStmt *ast_stmt_make_array_assign(char *name, AstExpr *index, AstExpr *value);
231+
AstStmt *ast_stmt_make_while(AstExpr *condition, AstStmt *body);
232+
AstStmt *ast_stmt_make_for(AstStmt *init, AstExpr *condition, AstStmt *post, AstStmt *body);
217233
AstStmt *ast_stmt_make_expr(AstExpr *expr);
218234
AstStmt *ast_stmt_make_return(AstExpr *expr);
219235
AstExpr *ast_expr_make_array_literal(AstExprList *elements);

src/codegen_lua.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,43 @@ static void emit_statement(FILE *out, const AstStmt *stmt, const FunctionTable *
187187
emit_expression_expected(out, stmt->data.array_assign.value, functions, stmt->data.array_assign.element_type);
188188
fputc('\n', out);
189189
break;
190+
case STMT_WHILE:
191+
emit_indent(out, indent);
192+
fputs("while ", out);
193+
emit_expression_as_bool(out, stmt->data.while_stmt.condition, functions);
194+
fputs(" do\n", out);
195+
emit_statement(out, stmt->data.while_stmt.body, functions, signature, indent + 1);
196+
emit_indent(out, indent);
197+
fputs("end\n", out);
198+
break;
199+
case STMT_FOR:
200+
emit_indent(out, indent);
201+
fputs("do\n", out);
202+
if (stmt->data.for_stmt.init)
203+
{
204+
emit_statement(out, stmt->data.for_stmt.init, functions, signature, indent + 1);
205+
}
206+
emit_indent(out, indent + 1);
207+
fputs("while ", out);
208+
if (stmt->data.for_stmt.condition)
209+
{
210+
emit_expression_as_bool(out, stmt->data.for_stmt.condition, functions);
211+
}
212+
else
213+
{
214+
fputs("true", out);
215+
}
216+
fputs(" do\n", out);
217+
emit_statement(out, stmt->data.for_stmt.body, functions, signature, indent + 2);
218+
if (stmt->data.for_stmt.post)
219+
{
220+
emit_statement(out, stmt->data.for_stmt.post, functions, signature, indent + 2);
221+
}
222+
emit_indent(out, indent + 1);
223+
fputs("end\n", out);
224+
emit_indent(out, indent);
225+
fputs("end\n", out);
226+
break;
190227
case STMT_EXPR:
191228
if (stmt->data.expr)
192229
{

src/lexer.l

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,12 @@ static char *yy_parse_string_literal(const char *src)
7474
"bool" { return KW_BOOL; }
7575
"void" { return KW_VOID; }
7676
"return" { return RETURN; }
77-
\[ { return LBRACKET; }
78-
\] { return RBRACKET; }
77+
"while" { return WHILE; }
78+
"for" { return FOR; }
7979
"true" { return TRUE; }
8080
"false" { return FALSE; }
81+
"\\[" { return LBRACKET; }
82+
"\\]" { return RBRACKET; }
8183
"//"[^\n]* { /* skip single line comments */ }
8284
"/*" { BEGIN(COMMENT); }
8385
<COMMENT>{

0 commit comments

Comments
 (0)