aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-09-01 23:32:41 +0900
committernsfisis <nsfisis@gmail.com>2025-09-01 23:55:56 +0900
commit5c1716417609ac2cea1470b3d3bb38a6e758279a (patch)
tree54047e6c04209b08599efac91d01cffee7c66135
parentc5cf38fffec9b7e0a96cc3f016c3a01820498953 (diff)
downloadducc-5c1716417609ac2cea1470b3d3bb38a6e758279a.tar.gz
ducc-5c1716417609ac2cea1470b3d3bb38a6e758279a.tar.zst
ducc-5c1716417609ac2cea1470b3d3bb38a6e758279a.zip
feat: support array type in struct/union members
-rw-r--r--src/ast.h1
-rw-r--r--src/parse.c67
-rw-r--r--tests/116.sh33
3 files changed, 76 insertions, 25 deletions
diff --git a/src/ast.h b/src/ast.h
index 13fbf55..399befc 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -116,7 +116,6 @@ enum AstNodeKind {
AstNodeKind_unary_expr,
AstNodeKind_union_decl,
AstNodeKind_union_def,
- AstNodeKind_union_member,
// Intermediate ASTs: they are used only in parsing, not for parse result.
AstNodeKind_declarator,
diff --git a/src/parse.c b/src/parse.c
index e2466ad..b4c33b5 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -1230,39 +1230,58 @@ static AstNode* parse_func_decl_or_def(Parser* p, AstNode* decls) {
return func;
}
-static AstNode* parse_struct_member(Parser* p) {
- Type* ty = parse_type_name(p);
- const Token* name = parse_ident(p);
- expect(p, TokenKind_semicolon);
- AstNode* member = ast_new(AstNodeKind_struct_member);
- member->name = name->value.string;
- member->ty = ty;
- return member;
+// member-declarator:
+// declarator
+// TODO declarator? ':' constant-expression
+static AstNode* parse_member_declarator(Parser* p, Type* base_ty) {
+ return parse_declarator(p, base_ty);
}
-static AstNode* parse_struct_members(Parser* p) {
- AstNode* list = ast_new_list(4);
- while (peek_token(p)->kind != TokenKind_brace_r) {
- AstNode* member = parse_struct_member(p);
- ast_append(list, member);
+// member-declarator-list:
+// { member-declarator | ',' }+
+static AstNode* parse_member_declarator_list(Parser* p, Type* base_ty) {
+ AstNode* list = ast_new_list(1);
+ while (1) {
+ AstNode* d = parse_member_declarator(p, base_ty);
+ ast_append(list, d);
+ if (!consume_token_if(p, TokenKind_comma)) {
+ break;
+ }
}
return list;
}
-static AstNode* parse_union_member(Parser* p) {
- Type* ty = parse_type_name(p);
- const Token* name = parse_ident(p);
+static Type* parse_specifier_qualifier_list(Parser* p);
+
+// member-declaration:
+// TODO attribute-specifier-sequence? specifier-qualifier-list member-declaration-list? ';'
+// TODO static_assert-declaration
+static AstNode* parse_member_declaration(Parser* p) {
+ Type* base_ty = parse_specifier_qualifier_list(p);
+
+ AstNode* decls = NULL;
+ if (consume_token_if(p, TokenKind_semicolon)) {
+ unimplemented();
+ }
+ decls = parse_member_declarator_list(p, base_ty);
+
expect(p, TokenKind_semicolon);
- AstNode* member = ast_new(AstNodeKind_union_member);
- member->name = name->value.string;
- member->ty = ty;
- return member;
+
+ if (decls->node_len != 1)
+ unimplemented();
+
+ AstNode* m = ast_new(AstNodeKind_struct_member);
+ m->name = decls->node_items[0].name;
+ m->ty = decls->node_items[0].ty;
+ return m;
}
-static AstNode* parse_union_members(Parser* p) {
+// member-declaration-list:
+// { member-declaration }+
+static AstNode* parse_member_declaration_list(Parser* p) {
AstNode* list = ast_new_list(4);
while (peek_token(p)->kind != TokenKind_brace_r) {
- AstNode* member = parse_union_member(p);
+ AstNode* member = parse_member_declaration(p);
ast_append(list, member);
}
return list;
@@ -1375,7 +1394,7 @@ static Type* parse_struct_specifier(Parser* p) {
struct_idx = p->structs->node_len - 1;
}
- AstNode* members = parse_struct_members(p);
+ AstNode* members = parse_member_declaration_list(p);
expect(p, TokenKind_brace_r);
p->structs->node_items[struct_idx].node_members = members;
@@ -1427,7 +1446,7 @@ static Type* parse_union_specifier(Parser* p) {
union_idx = p->unions->node_len - 1;
}
- AstNode* members = parse_union_members(p);
+ AstNode* members = parse_member_declaration_list(p);
expect(p, TokenKind_brace_r);
p->unions->node_items[union_idx].node_members = members;
diff --git a/tests/116.sh b/tests/116.sh
new file mode 100644
index 0000000..628c0d3
--- /dev/null
+++ b/tests/116.sh
@@ -0,0 +1,33 @@
+cat <<'EOF' > expected
+20
+10
+20
+30
+40
+50
+EOF
+
+test_diff <<'EOF'
+int printf();
+
+struct S {
+ int a[5];
+};
+
+int main() {
+ struct S x;
+ x.a[0] = 10;
+ x.a[1] = 20;
+ x.a[2] = 30;
+ x.a[3] = 40;
+ x.a[4] = 50;
+
+ printf("%zu\n", sizeof(struct S));
+
+ printf("%d\n", x.a[0]);
+ printf("%d\n", x.a[1]);
+ printf("%d\n", x.a[2]);
+ printf("%d\n", x.a[3]);
+ printf("%d\n", x.a[4]);
+}
+EOF