summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-10-09 16:05:33 +0200
committermetamuffin <metamuffin@disroot.org>2024-10-09 16:05:33 +0200
commitbcf69099f11a09882309b4590b55c0a3a7d5caba (patch)
tree257e1fc8817abe75ce9f4b98c68ef271d26669e1
parent0140eab52ab1d584c6526c242f173e6a55130589 (diff)
downloadattocc-bcf69099f11a09882309b4590b55c0a3a7d5caba.tar
attocc-bcf69099f11a09882309b4590b55c0a3a7d5caba.tar.bz2
attocc-bcf69099f11a09882309b4590b55c0a3a7d5caba.tar.zst
more parse
-rw-r--r--attocc.c179
1 files changed, 147 insertions, 32 deletions
diff --git a/attocc.c b/attocc.c
index 298b24c..2d38f95 100644
--- a/attocc.c
+++ b/attocc.c
@@ -337,7 +337,7 @@ struct token *tokenize(char *source) {
continue;
} else if (p[0] == '/' && p[1] == '*') {
p += 2;
- for (char c, d = '\0'; (d = c, c = *p++) && !(c == '/' && d == '*');)
+ for (char c = '\0', d; (d = c, c = *p++) && !(c == '/' && d == '*');)
;
continue;
} else if (p[0] == '#') {
@@ -583,14 +583,27 @@ struct node {
NO_STRUCT,
NO_UNION,
NO_ENUM,
+ NO_TYPE_PRIMITIVE,
+ NO_TYPE_POINTER,
NO_FUNCTION,
NO_COMPOUND,
+ NO_TR_UNIT,
} kind;
union node_data {
+ struct node *type_pointer;
+ enum node_primitive_type {
+ PRIMTY_U64,
+ PRIMTY_I32,
+ PRIMTY_U8,
+ } primitive_type;
+ struct node_data_tr_unit {
+ unsigned long num_elements;
+ struct node **elements;
+ } tr_unit;
struct node_data_function {
struct node *return_type;
char *name;
- int num_arguments;
+ unsigned long num_arguments;
struct function_argument {
char *name;
struct node *type;
@@ -598,7 +611,7 @@ struct node {
struct node *body;
} function;
struct node_data_compound {
- int num_statements;
+ unsigned long num_statements;
struct node **statements;
} compount;
struct node_data_binop {
@@ -617,29 +630,110 @@ struct node {
} data;
};
-struct node *parse_enum_decl(int *p, struct token *tokens);
+struct node *parse_enum_decl(int *p, struct token *tokens, char **error);
+struct node *parse_function(int *p, struct token *tokens, char **error);
+struct node *parse_type(int *p, struct token *tokens, char **error);
+struct node *parse_toplevel(int *p, struct token *tokens, char **error);
-struct node *parse_type(int *p, struct token *tokens) {
+struct node *parse(int *p, struct token *tokens, char **error) {
+ int num_elements = 0;
+ struct node **elements = NULL;
+ while (1) {
+ struct node *el = parse_toplevel(p, tokens, error);
+ if (!el) {
+ if (tokens[*p].kind == TOK_END)
+ break;
+ else
+ return NULL;
+ }
+ num_elements += 1;
+ elements = realloc_failsafe(elements, num_elements * sizeof(struct node *));
+ elements[num_elements - 1] = el;
+ }
+ struct node *node = realloc_failsafe(NULL, sizeof(struct node));
+ node->kind = NO_TR_UNIT;
+ node->data.tr_unit.elements = elements;
+ node->data.tr_unit.num_elements = num_elements;
+ return node;
+}
+
+struct node *parse_toplevel(int *p, struct token *tokens, char **error) {
struct node *out;
- out = parse_enum_decl(p, tokens);
+ out = parse_type(p, tokens, error);
+ if (out)
+ return out;
+ out = parse_function(p, tokens, error);
if (out)
return out;
return NULL;
}
-struct node *parse_function(int *p, struct token *tokens) {
- struct node *return_type = parse_type(p, tokens);
+struct node *parse_type(int *p, struct token *tokens, char **error) {
+ struct node *out;
+ out = parse_enum_decl(p, tokens, error);
+ if (out)
+ return out;
+
+ if (tokens[*p].kind == TOK_IDENTIFIER) {
+ struct node *node = realloc_failsafe(NULL, sizeof(struct node));
+ node->kind = NO_TYPE_PRIMITIVE;
+ node->data.primitive_type = PRIMTY_I32;
+ }
+
+ return NULL;
+}
+
+struct node *parse_function(int *p, struct token *tokens, char **error) {
+ struct node *return_type = parse_type(p, tokens, error);
if (!return_type)
return NULL;
+ if (tokens[*p].kind != TOK_IDENTIFIER)
+ return NULL;
+ char *name = strdup_failsafe(tokens[*p].data.identifier);
+ *p += 1;
+
+ if (tokens[*p].kind != TOK_SEPERATOR ||
+ tokens[*p].data.seperator != SEP_LPAREN)
+ return NULL;
+ *p += 1;
+
+ int num_arguments = 0;
+ struct function_argument *arguments = NULL;
+
+ while (1) {
+ if (tokens[*p].kind == TOK_END)
+ return NULL;
+ if (tokens[*p].kind == TOK_SEPERATOR &&
+ tokens[*p].data.seperator == SEP_RPAREN)
+ break;
+
+ struct node *type = parse_type(p, tokens, error);
+ if (tokens[*p].kind != TOK_IDENTIFIER)
+ return NULL;
+ char *name = strdup_failsafe(tokens->data.identifier);
+ *p += 1;
+
+ if (tokens[*p].kind == TOK_SEPERATOR &&
+ tokens[*p].data.seperator == SEP_COMMA)
+ *p += 1;
+
+ num_arguments += 1;
+ arguments = realloc_failsafe(
+ arguments, num_arguments * sizeof(struct function_argument));
+ arguments[num_arguments - 1].name = name;
+ arguments[num_arguments - 1].type = type;
+ }
+
struct node *node = realloc_failsafe(NULL, sizeof(struct node));
node->kind = NO_FUNCTION;
node->data.function.return_type = return_type;
+ node->data.function.name = name;
return node;
}
-struct node *parse_enum_decl(int *p, struct token *tokens) {
+struct node *parse_enum_decl(int *p, struct token *tokens, char **error) {
if (tokens[*p].kind != TOK_KEYWORD || tokens[*p].data.keyword != KW_ENUM)
return 0;
*p += 1;
@@ -721,33 +815,44 @@ struct node *parse_enum_decl(int *p, struct token *tokens) {
return node;
}
-struct node *parse(int *p, struct token *tokens) {
- return parse_type(p, tokens);
+#ifdef DEBUG
+void indent(int k) {
+ for (int i = 0; i < k; i++) {
+ printf(" ");
+ }
}
-#ifdef DEBUG
-void debug_node(struct node *node) {
+void debug_node(struct node *node, int k) {
switch (node->kind) {
case NO_ENUM:
+ indent(k);
printf("NO_ENUM\n");
- printf(" name=%s\n", node->data.enum_.name);
- printf(" is_decl=%i\n", node->data.enum_.is_decl);
+ indent(k + 1);
+ printf("name=%s\n", node->data.enum_.name);
+ indent(k + 1);
+ printf("is_decl=%i\n", node->data.enum_.is_decl);
if (node->data.enum_.is_decl) {
- printf(" num_members=%li\n", node->data.enum_.num_members);
- printf(" members\n");
- for (int i = 0; i < node->data.enum_.num_members; i++) {
- printf(" %s=%i\n", node->data.enum_.members[i].name,
+ indent(k + 1);
+ printf("num_members=%li\n", node->data.enum_.num_members);
+ indent(k + 1);
+ printf("members\n");
+ for (unsigned long i = 0; i < node->data.enum_.num_members; i++) {
+ indent(k + 2);
+ printf("%s=%i\n", node->data.enum_.members[i].name,
node->data.enum_.members[i].value);
}
}
break;
case NO_BINOP:
+ indent(k);
printf("NO_BINOP\n");
- printf(" lhs: ");
- debug_node(node->data.binop.lhs);
+ indent(k + 1);
+ printf("lhs: ");
+ debug_node(node->data.binop.lhs, k + 2);
printf("\n");
- printf(" rhs: ");
- debug_node(node->data.binop.rhs);
+ indent(k + 1);
+ printf("rhs: ");
+ debug_node(node->data.binop.rhs, k + 2);
printf("\n");
break;
case NO_MEMBER_ACCESS:
@@ -765,6 +870,11 @@ void debug_node(struct node *node) {
case NO_UNOP:
printf("NO_UNOP\n");
break;
+ case NO_TR_UNIT:
+ indent(k);
+ printf("NO_TR_UNIT\n");
+ for (unsigned long i = 0; i < node->data.tr_unit.num_elements; i++)
+ debug_node(node->data.tr_unit.elements[i], k + 1);
default:
break;
}
@@ -812,21 +922,21 @@ int main(int argc, char **argv) {
char *input = argv[1];
char *output = argv[2];
- printf("open input\n");
int input_fd = open(input, O_RDONLY | O_CLOEXEC);
if (input_fd < 0) {
perror("cannot open input");
return 1;
}
-
- printf("open output\n");
int output_fd = open(output, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, 0640);
if (output_fd < 0) {
perror("cannot open input");
return 1;
}
- printf("read input\n");
+#ifdef DEBUG
+ printf("\n=== READ INPUT ===\n");
+#endif
+
int source_len = 0;
char *source = NULL;
int size;
@@ -845,25 +955,30 @@ int main(int argc, char **argv) {
}
source[source_len] = '\0';
- printf("tokenize\n");
+#ifdef DEBUG
+ printf("%i bytes loaded\n", source_len);
+ printf("\n=== TOKENIZE ===\n");
+#endif
+
struct token *tokens = tokenize(source);
if (!tokens)
return 1;
#ifdef DEBUG
debug_tokens(tokens);
+ printf("\n=== PARSE ===\n");
#endif
- printf("parse\n");
int p = 0;
- struct node *node = parse(&p, tokens);
+ char *error = "no message";
+ struct node *node = parse(&p, tokens, &error);
if (!node) {
- printf("parse failed\n");
+ printf("parse failed: %s\n", error);
return 1;
}
#ifdef DEBUG
- debug_node(node);
+ debug_node(node, 0);
#endif
free_tokens(tokens);