aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-08-19 00:26:29 +0900
committernsfisis <nsfisis@gmail.com>2025-08-19 00:26:29 +0900
commit2aacd7a4b67bd6f9c11e005c72c4e52e6b644212 (patch)
tree7396430bf8f204e1bd2dadca429408359ef14a09
parent79796388b3c040bda25ce330af72ca514b30f60c (diff)
downloadducc-2aacd7a4b67bd6f9c11e005c72c4e52e6b644212.tar.gz
ducc-2aacd7a4b67bd6f9c11e005c72c4e52e6b644212.tar.zst
ducc-2aacd7a4b67bd6f9c11e005c72c4e52e6b644212.zip
feat: support global variable declaration with multiple variables
-rw-r--r--parse.c56
-rw-r--r--tests/095.sh3
2 files changed, 29 insertions, 30 deletions
diff --git a/parse.c b/parse.c
index 88fecfc..08fa436 100644
--- a/parse.c
+++ b/parse.c
@@ -1110,50 +1110,42 @@ AstNode* parse_param_list(Parser* p) {
return list;
}
-AstNode* parse_global_var_decl(Parser* p, Type* ty, const char* name) {
- if (type_is_unsized(ty)) {
+AstNode* parse_global_var_decl(Parser* p) {
+ Type* base_ty = parse_type(p);
+ if (type_is_unsized(base_ty)) {
fatal_error("parse_global_var_decl: invalid type for variable");
}
- if (peek_token(p)->kind == TokenKind_bracket_l) {
- next_token(p);
- AstNode* size_expr = parse_expr(p);
- if (size_expr->kind != AstNodeKind_int_expr) {
- fatal_error("parse_global_var_decl: invalid array size");
- }
- int size = size_expr->node_int_value;
- expect(p, TokenKind_bracket_r);
- ty = type_new_array(ty, size);
- }
-
- AstNode* init = NULL;
- if (peek_token(p)->kind == TokenKind_assign) {
- next_token(p);
- init = parse_assignment_expr(p);
- }
+ AstNode* decls = parse_init_declarator_list(p, base_ty);
expect(p, TokenKind_semicolon);
- if (find_gvar(p, name) != -1) {
- fatal_error("parse_global_var_decl: %s redeclared", name);
- }
+ for (int i = 0; i < decls->node_len; ++i) {
+ AstNode* decl = &decls->node_items[i];
- p->gvars[p->n_gvars].name = name;
- p->gvars[p->n_gvars].ty = ty;
- ++p->n_gvars;
+ if (find_gvar(p, decl->name) != -1) {
+ fatal_error("parse_global_var_decl: %s redeclared", decl->name);
+ }
+ p->gvars[p->n_gvars].name = decl->name;
+ p->gvars[p->n_gvars].ty = decl->ty;
+ ++p->n_gvars;
- AstNode* ret = ast_new(AstNodeKind_gvar_decl);
- ret->name = name;
- ret->ty = ty;
- ret->node_expr = init;
- return ret;
+ decl->kind = AstNodeKind_gvar_decl;
+ decl->node_expr = decl->node_init;
+ }
+ return decls;
}
AstNode* parse_func_decl_or_def(Parser* p) {
+ // TODO: remove it.
+ int start_pos = p->pos;
+
Type* ty = parse_type(p);
const char* name = parse_ident(p);
if (peek_token(p)->kind != TokenKind_paren_l) {
- return parse_global_var_decl(p, ty, name);
+ // TODO: avoid backtracking
+ p->pos = start_pos;
+ return parse_global_var_decl(p);
}
expect(p, TokenKind_paren_l);
@@ -1390,6 +1382,10 @@ Program* parse(TokenArray* tokens) {
ast_append(funcs, n);
} else if (n->kind == AstNodeKind_gvar_decl && n->ty) {
ast_append(vars, n);
+ } else if (n->kind == AstNodeKind_list) {
+ for (int i = 0; i < n->node_len; ++i) {
+ ast_append(vars, &n->node_items[i]);
+ }
}
}
Program* prog = calloc(1, sizeof(Program));
diff --git a/tests/095.sh b/tests/095.sh
index 58ee35f..65cd31a 100644
--- a/tests/095.sh
+++ b/tests/095.sh
@@ -2,14 +2,17 @@ set -e
cat <<'EOF' > expected
1 2 3 4
+0 0 5
EOF
bash ../../test_diff.sh <<'EOF'
int printf();
+int x, y, z = 5;
int main() {
int a, b;
a = 1, b = 2;
int c = 3, d = 4;
printf("%d %d %d %d\n", a, b, c, d);
+ printf("%d %d %d\n", x, y, z);
}
EOF