hachem.wtf
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-19 11:01:51 +0200
committerhachem <im@hachem.wtf>2026-09-19 11:01:51 +0200
commit08b8cbbccd8c8d7dab75746ee9d134f67455de91 (patch)
tree83de1ed169e14b2595cd9da9e5c16f1d84c8c808
parent05bf718e37efdc5201ad281e85da7850af31bd59 (diff)
feat: start work on ast
-rw-r--r--Makefile7
-rw-r--r--ast.c68
-rw-r--r--ast.h27
-rw-r--r--lexer.h14
-rw-r--r--main.c5
-rw-r--r--sfinae.l1
6 files changed, 104 insertions, 18 deletions
diff --git a/Makefile b/Makefile
index e1140cf..a30b93c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
CC = cc
LEX = flex
CFLAGS = -std=c17 -Wall -Wextra -Werror -Wpedantic -O2
-SOURCES = lexer.h main.c
-OBJECTS = bin/lexer.o bin/main.o
+SOURCES = ast.c ast.h lexer.h main.c
+OBJECTS = bin/lexer.o bin/ast.o bin/main.o
SANITIZE = -g -O0 -fsanitize=address,undefined
.PHONY: all debug check format lint clean
@@ -25,6 +25,7 @@ bin/%.o: %.c | bin
$(CC) $(CFLAGS) -c -o $@ $<
bin/main.o: lexer.h
+bin/ast.o: ast.h lexer.h
debug: CFLAGS += $(SANITIZE)
debug: clean sfinae
@@ -39,7 +40,7 @@ format:
clang-format -i $(SOURCES)
lint:
- clang-tidy main.c -- -std=c17
+ clang-tidy ast.c main.c -- -std=c17
clean:
rm -rf bin sfinae
diff --git a/ast.c b/ast.c
new file mode 100644
index 0000000..25cecb7
--- /dev/null
+++ b/ast.c
@@ -0,0 +1,68 @@
+#include "ast.h"
+#include "lexer.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static struct Node* node_new(enum NodeKind kind)
+{
+ struct Node* node = calloc(1, sizeof *node);
+ if (node == NULL)
+ {
+ (void)fprintf(stderr, "out of memory\n");
+ exit(1);
+ }
+ node->kind = kind;
+ node->line = yylineno;
+ return node;
+}
+
+struct Node* node_leaf(enum NodeKind kind)
+{
+ return node_new(kind);
+}
+
+struct Node* node_char(char character)
+{
+ struct Node* node = node_new(NODE_CHAR);
+ node->character = character;
+ return node;
+}
+
+struct Node* node_unary(enum NodeKind kind, struct Node* first)
+{
+ struct Node* node = node_new(kind);
+ node->first = first;
+ return node;
+}
+
+struct Node* node_binary(enum NodeKind kind, struct Node* first, struct Node* second)
+{
+ struct Node* node = node_new(kind);
+ node->first = first;
+ node->second = second;
+ return node;
+}
+
+struct Node* node_append(struct Node* list, struct Node* node)
+{
+ struct Node* last = list;
+
+ if (list == NULL)
+ return node;
+ while (last->next != NULL)
+ last = last->next;
+ last->next = node;
+ return list;
+}
+
+void node_free(struct Node* node)
+{
+ if (node == NULL)
+ return;
+ node_free(node->first);
+ node_free(node->second);
+ node_free(node->next);
+ free(node);
+}
diff --git a/ast.h b/ast.h
new file mode 100644
index 0000000..1a6f159
--- /dev/null
+++ b/ast.h
@@ -0,0 +1,27 @@
+#pragma once
+
+enum NodeKind
+{
+ NODE_CHAR,
+ TYPE_DECLTYPE,
+ VALUE_DIFFERENCE,
+ STMT_EMIT
+};
+
+struct Node
+{
+ enum NodeKind kind;
+ int line;
+ char character;
+ struct Node* first;
+ struct Node* second;
+ struct Node* next;
+};
+
+struct Node* node_leaf(enum NodeKind kind);
+struct Node* node_char(char character);
+struct Node* node_unary(enum NodeKind kind, struct Node* first);
+struct Node* node_binary(enum NodeKind kind, struct Node* first, struct Node* second);
+
+struct Node* node_append(struct Node* list, struct Node* node);
+void node_free(struct Node* node);
diff --git a/lexer.h b/lexer.h
index eb7a4d3..4e09ace 100644
--- a/lexer.h
+++ b/lexer.h
@@ -3,8 +3,6 @@
#include <stdbool.h>
#include <stdio.h>
-// single characters stand for themselves
-// so the named tokens start past them
enum Token
{
TOK_END = 0,
@@ -16,15 +14,9 @@ enum Token
TOK_CHAR
};
-// provided by flex
-// the input
-// the current line
-// and the scanner itself
-extern FILE* yyin;
-extern int yylineno;
-int yylex(void);
+extern FILE* yyin; // input
+extern int yylineno; // current line
+int yylex(void); // scanner
-// true once the lexer has refused something
bool lexer_failed(void);
-// the character inside the most recent TOK_CHAR
char lexer_character(void);
diff --git a/main.c b/main.c
index 44d9025..634e6d0 100644
--- a/main.c
+++ b/main.c
@@ -11,9 +11,7 @@ static const char* token_name(int token)
case TOK_COMMIT: return "commit";
case TOK_DECLTYPE: return "decltype";
case TOK_DIFFERENCE: return "difference";
- default:
- // single characters and character literals are printed by the caller
- return NULL;
+ default: return NULL;
}
}
@@ -32,6 +30,7 @@ static int dump_tokens(void)
else
(void)printf("%c\n", (char)token);
}
+
return lexer_failed() ? 1 : 0;
}
diff --git a/sfinae.l b/sfinae.l
index 8453699..f969a98 100644
--- a/sfinae.l
+++ b/sfinae.l
@@ -20,7 +20,6 @@ static char unescape(char escaped)
}
}
-// complains, remembers, and hands back TOK_END so the scan stops where it went wrong
static int fail(const char* message)
{
(void)fprintf(stderr, "line %d: %s\n", yylineno, message);