diff options
| author | hachem <im@hachem.wtf> | 2026-09-19 11:01:51 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-09-19 11:01:51 +0200 |
| commit | 08b8cbbccd8c8d7dab75746ee9d134f67455de91 (patch) | |
| tree | 83de1ed169e14b2595cd9da9e5c16f1d84c8c808 | |
| parent | 05bf718e37efdc5201ad281e85da7850af31bd59 (diff) | |
feat: start work on ast
| -rw-r--r-- | Makefile | 7 | ||||
| -rw-r--r-- | ast.c | 68 | ||||
| -rw-r--r-- | ast.h | 27 | ||||
| -rw-r--r-- | lexer.h | 14 | ||||
| -rw-r--r-- | main.c | 5 | ||||
| -rw-r--r-- | sfinae.l | 1 |
6 files changed, 104 insertions, 18 deletions
@@ -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 @@ -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); +} @@ -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); @@ -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); @@ -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; } @@ -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); |
