aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-09-13 21:07:22 +0900
committernsfisis <nsfisis@gmail.com>2025-09-13 21:07:22 +0900
commit219653a7a1ff36776580c79f4e288e82bbcf057d (patch)
treee2ccbcf6c1da0c6b34b75e16968ed2ce6adce8fa
parentd8165f2b38c6405d506649d93112bad62d3d9ec0 (diff)
downloadducc-219653a7a1ff36776580c79f4e288e82bbcf057d.tar.gz
ducc-219653a7a1ff36776580c79f4e288e82bbcf057d.tar.zst
ducc-219653a7a1ff36776580c79f4e288e82bbcf057d.zip
feat: support parsing function pointer declaration
-rw-r--r--src/parse.c28
-rw-r--r--tests/test_function_pointers.sh12
2 files changed, 34 insertions, 6 deletions
diff --git a/src/parse.c b/src/parse.c
index 14fd7d2..c742f88 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -912,6 +912,7 @@ static AstNode* parse_declarator_or_abstract_declarator_opt(Parser* p, Type* ty)
token_stringify(tok));
}
decl = parse_declarator_or_abstract_declarator_opt(p, ty);
+ expect(p, TokenKind_paren_r);
} else {
decl = ast_new(AstNodeKind_declarator);
decl->ty = ty;
@@ -1029,26 +1030,41 @@ static Type* parse_function_declarator_suffix(Parser* p, Type* ty) {
return type_new_func(ty, params);
}
+static AstNode* parse_declarator(Parser* p, Type* ty);
+
// direct-declarator:
// identifier TODO attribute-specifier-sequence?
-// TODO '(' declarator ')'
+// '(' declarator ')'
// array-declarator TODO attribute-specifier-sequence?
// function-declarator TODO attribute-specifier-sequence?
static AstNode* parse_direct_declarator(Parser* p, Type* ty) {
- const Token* name = parse_ident(p);
+ AstNode* decl;
+ if (peek_token(p)->kind == TokenKind_ident) {
+ decl = ast_new(AstNodeKind_declarator);
+ decl->name = parse_ident(p)->value.string;
+ decl->ty = ty;
+ } else if (peek_token(p)->kind == TokenKind_paren_l && !is_type_token(p, peek_token2(p))) {
+ next_token(p);
+ decl = parse_declarator(p, ty);
+ expect(p, TokenKind_paren_r);
+ } else {
+ decl = ast_new(AstNodeKind_declarator);
+ decl->ty = ty;
+ }
+
while (1) {
if (peek_token(p)->kind == TokenKind_bracket_l) {
- ty = parse_array_declarator_suffix(p, ty);
+ decl->ty = parse_array_declarator_suffix(p, decl->ty);
} else if (peek_token(p)->kind == TokenKind_paren_l) {
- ty = parse_function_declarator_suffix(p, ty);
+ decl->ty = parse_function_declarator_suffix(p, decl->ty);
} else {
break;
}
}
AstNode* ret = ast_new(AstNodeKind_declarator);
- ret->name = name->value.string;
- ret->ty = ty;
+ ret->name = decl->name;
+ ret->ty = decl->ty;
return ret;
}
diff --git a/tests/test_function_pointers.sh b/tests/test_function_pointers.sh
new file mode 100644
index 0000000..c97a087
--- /dev/null
+++ b/tests/test_function_pointers.sh
@@ -0,0 +1,12 @@
+cat <<'EOF' > expected
+EOF
+
+test_diff <<'EOF'
+int* f(int a);
+int (*f)(int a);
+
+extern int atexit (void (*) (void));
+extern int atexit (void (*fn) (void));
+
+int main() {}
+EOF