From bd003f5a1b48d0238523a92fb5f787cb41fcbc09 Mon Sep 17 00:00:00 2001 From: Liam O'Connor Date: Thu, 20 Nov 2025 20:24:55 +1100 Subject: [PATCH] forgot to add headers.. --- error.h | 45 +++++++++++++++++++++++++++++++++++++++ intern.h | 11 ++++++++++ lexer.h | 37 ++++++++++++++++++++++++++++++++ scope.h | 15 +++++++++++++ source.h | 24 +++++++++++++++++++++ syntax.h | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ util.h | 18 ++++++++++++++++ 7 files changed, 214 insertions(+) create mode 100644 error.h create mode 100644 intern.h create mode 100644 lexer.h create mode 100644 scope.h create mode 100644 source.h create mode 100644 syntax.h create mode 100644 util.h diff --git a/error.h b/error.h new file mode 100644 index 0000000..e2b178c --- /dev/null +++ b/error.h @@ -0,0 +1,45 @@ +#ifndef error_h +#define error_h +#include "source.h" +typedef enum { + ERROR_UNRECOGNISED_TOKEN, + ERROR_UNTERMINATED_STRING_LITERAL, + ERROR_PARSE_ERROR, + ERROR_EXPECTED_RPAREN, + ERROR_EXPECTED_EXPRESSION, + ERROR_INVALID_PATTERN, + ERROR_EXPECTED_SEMI, + ERROR_UNKNOWN_VARIABLE, + WARNING +} error_tag; + +typedef struct { + error_tag tag; + source_t *source; + pos_t position; + int highlight_len; +} error_t; + +static inline error_t error(error_tag tag, source_t *source, pos_t position, + int highlight_len) { + error_t it = { + .tag = tag, + .source = source, + .position = position, + .highlight_len = highlight_len + }; + return it; +} +char* error_tag_human_readable(error_tag err_tag); + +void error_set_handler(void (*eh)(error_t err)); +void error_default_handler(error_t err); + +void error_report(error_t error); + + + + +#endif + + diff --git a/intern.h b/intern.h new file mode 100644 index 0000000..2828992 --- /dev/null +++ b/intern.h @@ -0,0 +1,11 @@ +#ifndef intern_h +#define intern_h +#include +typedef struct intern_table intern_table_t; +typedef const char *intern_t; +intern_table_t *intern_table_alloc(void); +void intern_table_free(intern_table_t *table); +intern_t intern(intern_table_t *table, const char *str); +intern_t intern_prefix(intern_table_t *table, const char *str, size_t len); +const char * intern_exists(intern_table_t *table, const char *str); +#endif \ No newline at end of file diff --git a/lexer.h b/lexer.h new file mode 100644 index 0000000..6904055 --- /dev/null +++ b/lexer.h @@ -0,0 +1,37 @@ +#ifndef lexer_h +#define lexer_h + +#include "source.h" + +typedef enum { + TOKEN_LPAREN, + TOKEN_RPAREN, + TOKEN_STRING_LIT, + TOKEN_INT_LIT, + TOKEN_IDENT, + TOKEN_CONSTRUCTOR, + TOKEN_ASSIGN, + TOKEN_SEMI, + TOKEN_COMMA, + TOKEN_COLON, + TOKEN_UNRECOGNISED, + TOKEN_EOF +} token_type; +typedef struct { + token_type type; + pos_t pos; + const char* start; + size_t len; +} token_t; + +typedef struct lexer lexer_t; +// does not take ownership of the source_t +lexer_t* lexer_alloc(source_t *source_code); +source_t* lexer_source(lexer_t *lexer); +pos_t lexer_cur_pos(lexer_t* lexer); +token_t lexer_lex(lexer_t* lexer); +token_t lexer_peek(lexer_t* lexer); +void lexer_dealloc(lexer_t* lexer); + +const char* lexer_token_type_to_string(token_t to_print); +#endif \ No newline at end of file diff --git a/scope.h b/scope.h new file mode 100644 index 0000000..abf503e --- /dev/null +++ b/scope.h @@ -0,0 +1,15 @@ +#ifndef scope_h +#define scope_h +#include +#include "intern.h" + +typedef struct scope scope_t; +typedef size_t de_bruijn_t; + + +scope_t *scope_alloc(void); +void scope_push(scope_t *scope, intern_t identifier); +void scope_pop(scope_t *scope, size_t amount); +void scope_free(scope_t *scope); +de_bruijn_t scope_lookup(scope_t *scope, intern_t identifier); +#endif \ No newline at end of file diff --git a/source.h b/source.h new file mode 100644 index 0000000..29c401b --- /dev/null +++ b/source.h @@ -0,0 +1,24 @@ +#ifndef source_h +#define source_h +#include + +typedef struct source source_t; +typedef struct { + int line; int col; size_t idx; +} pos_t; + +source_t *source_alloc_from_file(char* file_name); + +// takes ownership of the file contents string. +source_t *source_alloc(const char* file_name, char* contents); + +pos_t source_next_pos(source_t *source, pos_t pos); + +void source_print_pos(source_t *source, pos_t pos); + +void source_print_line(source_t *source, pos_t pos, int highlight_len); + +const char* source_contents_from(source_t* source, pos_t pos); + +void source_dealloc(source_t* source); +#endif \ No newline at end of file diff --git a/syntax.h b/syntax.h new file mode 100644 index 0000000..899490d --- /dev/null +++ b/syntax.h @@ -0,0 +1,64 @@ +#ifndef syntax_h +#define syntax_h +#include "lexer.h" +#include "intern.h" +#include "scope.h" +#include +typedef struct expr expr_t; + + +struct expr { + enum { + EXPR_CALL, + EXPR_VAR, + EXPR_PAT_IDENT, + EXPR_CONSTRUCTOR, + EXPR_INT_LIT, + EXPR_LET_BINDING, + EXPR_STRING_LIT, + EXPR_LAMBDA, + EXPR_WEAKENING, + EXPR_ALT, + } tag; + source_t *source; + pos_t pos; + union { + struct { + expr_t *callee; + expr_t *argument; + } call; + struct { + expr_t *try; + expr_t *orelse; + } alt; + struct { + expr_t *pattern; + expr_t *expr; + expr_t *in; + } let_binding; + de_bruijn_t var; + intern_t ident; + intern_t constructor; + long int_lit; + char *string_lit; + struct { + expr_t *pattern; + expr_t *body; + } lambda; + struct { + de_bruijn_t *keep; + size_t keep_len; + expr_t *pattern; + expr_t *body; + } weakening; + } as; +}; + +expr_t *syntax_parse_expr(lexer_t *lexer, intern_table_t *table); +void syntax_expr_free(expr_t *it); + +size_t syntax_scope_check_pattern(expr_t *it, scope_t *scope); +bool syntax_scope_check_expr(expr_t *it, scope_t *scope); + +void syntax_dump_expr(expr_t *it); +#endif \ No newline at end of file diff --git a/util.h b/util.h new file mode 100644 index 0000000..42072b7 --- /dev/null +++ b/util.h @@ -0,0 +1,18 @@ +#ifndef util_h +#define util_h +#include +#include +#include +bool starts_with_any_impl(const char *str, ...); +#define starts_with_any(str, ...) starts_with_any_impl(str, __VA_ARGS__, NULL) + +noreturn void die_impl(const char *file, int line, const char *fmt, ...); + +// Simple FNV-1a hash for strings +size_t hash_buffer(const char *buf, size_t len); +size_t hash_string(const char *str); + +// Macro to capture file and line automatically +#define die(...) die_impl(__FILE__, __LINE__, __VA_ARGS__) + +#endif \ No newline at end of file -- 2.51.2