aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-05-04 14:29:07 +0900
committernsfisis <nsfisis@gmail.com>2025-05-04 14:29:07 +0900
commit298977906d005ec026778286591f5843406291b7 (patch)
tree064de1d23fe0ffdb5d69403bf5fe8bdbe09bcadf
parent9a35c86da5a81d9e83f7729f1ada8a5bf5934014 (diff)
downloadP4Dcc-298977906d005ec026778286591f5843406291b7.tar.gz
P4Dcc-298977906d005ec026778286591f5843406291b7.tar.zst
P4Dcc-298977906d005ec026778286591f5843406291b7.zip
support pointer types
-rw-r--r--main.c34
-rw-r--r--tests/021.sh24
2 files changed, 55 insertions, 3 deletions
diff --git a/main.c b/main.c
index c90c71b..0adbedf 100644
--- a/main.c
+++ b/main.c
@@ -230,6 +230,8 @@ TOKEN* tokenize(char* src, int len) {
tok->kind = TK_K_SIZEOF;
} else if (strstr(src + start, "struct") == src + start) {
tok->kind = TK_K_STRUCT;
+ } else if (strstr(src + start, "void") == src + start) {
+ tok->kind = TK_K_VOID;
} else {
tok->kind = TK_IDENT;
tok->value = calloc(pos - start + 1, sizeof(char));
@@ -251,12 +253,12 @@ TOKEN* tokenize(char* src, int len) {
#define TY_INT 2
#define TY_LONG 3
#define TY_VOID 4
-#define TY_STRUCT 5
-#define TY_ARR 6
-#define TY_PTR 7
+#define TY_PTR 5
+#define TY_STRUCT 6
typedef struct Type {
int kind;
+ struct Type* to;
} TYPE;
TYPE* type_new(int kind) {
@@ -265,6 +267,17 @@ TYPE* type_new(int kind) {
return ty;
}
+TYPE* type_new_ptr(TYPE* to) {
+ TYPE* ty = calloc(1, sizeof(TYPE));
+ ty->kind = TY_PTR;
+ ty->to = to;
+ return ty;
+}
+
+int type_is_valid_for_var(TYPE* ty) {
+ return ty->kind != TY_VOID;
+}
+
#define AST_UNKNOWN 0
#define AST_ARG_LIST 1
@@ -668,11 +681,23 @@ TYPE* parse_type(PARSER* p) {
} else if (t->kind == TK_K_VOID) {
ty->kind = TY_VOID;
}
+ while (1) {
+ TOKEN* t2 = peek_token(p);
+ if (t2->kind == TK_STAR) {
+ next_token(p);
+ ty = type_new_ptr(ty);
+ } else {
+ break;
+ }
+ }
return ty;
}
AST* parse_var_decl(PARSER* p) {
TYPE* ty = parse_type(p);
+ if (!type_is_valid_for_var(ty)) {
+ fatal_error("parse_var_decl: invalid type for variable");
+ }
char* name = parse_ident(p);
AST* decl = ast_new(AST_VAR_DECL);
expect(p, TK_SEMICOLON);
@@ -747,6 +772,9 @@ void parse_register_params(PARSER* p, AST* params) {
AST* parse_param(PARSER* p) {
TYPE* ty = parse_type(p);
+ if (!type_is_valid_for_var(ty)) {
+ fatal_error("parse_param: invalid type for variable");
+ }
char* name = parse_ident(p);
AST* param = ast_new(AST_PARAM);
param->ty = ty;
diff --git a/tests/021.sh b/tests/021.sh
new file mode 100644
index 0000000..2f225e1
--- /dev/null
+++ b/tests/021.sh
@@ -0,0 +1,24 @@
+set -e
+
+cat <<'EOF' > expected
+EOF
+bash ../../test_diff.sh <<'EOF'
+int main() {
+ int a1;
+ int* a2;
+ char a3;
+ char* a4;
+ long a5;
+ long* a6;
+ void* a8;
+ int** a10;
+ char** a12;
+ long** a14;
+ void** a16;
+ int*** a18;
+ char*** a20;
+ long*** a22;
+ void*** a24;
+ return 0;
+}
+EOF