From 8fd281e46316600e1b8d5ece03907b23cf85ea5d Mon Sep 17 00:00:00 2001 From: zongor Date: Tue, 31 Mar 2026 23:16:29 -0700 Subject: [PATCH] WIP parser --- libc.c | 24 +++++- libc.h | 2 + list.c | 98 +++++++++++++++++++++++ list.h | 29 +++++++ parser.c | 232 ++++++++++++++++++++++++------------------------------- parser.h | 89 ++++++--------------- 6 files changed, 278 insertions(+), 196 deletions(-) create mode 100644 list.c create mode 100644 list.h diff --git a/libc.c b/libc.c index a48a07f..169fb21 100644 --- a/libc.c +++ b/libc.c @@ -84,7 +84,7 @@ aaloc(Arena *arena, u32 size) pos = arena->count; arena->count += size; - return &arena->tape[pos]; + return (void *)&arena->tape[pos]; } u32 @@ -94,3 +94,25 @@ afree(Arena *arena) arena->count = 0; return freed; } + +char * +ascpy(Arena *arena, const char *start, u32 length) +{ + char *str; + if(!start) return nil; + str = (char *)aalloc(arena, length + 1); + if(!str) return nil; + scpy(str, start, length); + return str; +} + +void * +amcpy(Arena *arena, void *from, u32 length) +{ + void *ptr; + if(!from) return nil; + ptr = aalloc(arena, length); + if(!ptr) return nil; + mcpy(ptr, from, length); + return ptr; +} diff --git a/libc.h b/libc.h index ffa4230..02c4405 100644 --- a/libc.h +++ b/libc.h @@ -84,5 +84,7 @@ u32 slen(const char *str); u32 snlen(const char *str, u32 max_len); void *aalloc(Arena *arena, u32 size); u32 afree(Arena *arena); +char *ascpy(Arena *arena, const char *start, u32 length); +void *amcpy(Arena *arena, void *from, u32 length); #endif diff --git a/list.c b/list.c new file mode 100644 index 0000000..5a28ded --- /dev/null +++ b/list.c @@ -0,0 +1,98 @@ +#include "list.h" + +List * +new_list(Arena *arena) +{ + List *l = aalloc(arena, sizeof(List)); + if (!l) return nil; + + l->head = nil; + l->tail = nil; + l->count = 0; + + return l; +} + +void * +node_value(Node *n) +{ + return (void *)((u8 *)n + sizeof(Node)); +} + +void * +list_push(Arena *arena, List *list, void *data, u32 data_size) +{ + void *ptr = aalloc(arena, sizeof(Node) + data_size); + Node *node = (Node *)ptr; + + if (!node) return nil; + + node->next = nil; + + if (!list->head) { + list->head = list->tail = node; + } else { + list->tail->next = node; + list->tail = node; + } + + list->count++; + + void *dest = node_value(node); + if (data && data_size > 0) { + mcpy(dest, data, data_size); + } + + return dest; +} + +void +list_foreach(List *list, list_iter_fn func) +{ + if (!list || !func) return; + + Node *curr = list->head; + while (curr) { + func(node_value(curr)); + curr = curr->next; + } +} + +void * +list_get(List *list, u32 index) +{ + if (!list || index >= list->count) return nil; + + Node *curr = list->head; + // Walk to the desired index + for (u32 i = 0; i < index; i++) { + curr = curr->next; + } + + return node_value(curr); +} + +void +list_set(List *list, u32 index, const void *data, u32 size) +{ + void *target = list_get(list, index); + if (target) { + mcpy(target, data, size); + } +} + +void * +list_find(List *list, compare_fn compare, const void *target) +{ + if (!list || !compare) return nil; + + Node *curr = list->head; + while (curr) { + void *data = node_value(curr); + if (compare(data, target)) { + return data; + } + curr = curr->next; + } + return nil; +} diff --git a/list.h b/list.h new file mode 100644 index 0000000..7249228 --- /dev/null +++ b/list.h @@ -0,0 +1,29 @@ +#ifndef UNDAR_LIST_H +#define UNDAR_LIST_H + +#include "libc.h" + +typedef struct node_s Node; +struct node_s { + struct node_s *next; +}; + +typedef struct list_s List; +struct list_s { + Node *head; + Node *tail; + u32 count; +}; + +typedef bool (*compare_fn)(const void *data, const void *target); +typedef void (*list_iter_fn)(void *data); + +List *new_list(Arena *arena); +void *node_value(Node *n); +void *list_push(Arena *arena, List *list, void *data, u32 data_size); +void list_foreach(List *list, list_iter_fn func); +void *list_find(List *list, compare_fn compare, const void *target); +void *list_get(List *list, u32 index); +void list_set(List *list, u32 index, const void *data, u32 size); + +#endif \ No newline at end of file diff --git a/parser.c b/parser.c index 9c3f0c5..59c0c41 100644 --- a/parser.c +++ b/parser.c @@ -15,158 +15,132 @@ advance() } } -bool -push(TokenStack *ts, Token t) +/**************************************************** + * Scope + ***************************************************/ + +void +scope_push(Arena *arena) { - if(ts->count >= ts->capacity) return false; - ts->stack[ts->count++] = t; - return true; + Scope *child = aalloc(arena, sizeof(Scope)); + child->symbols = new_list(arena); + child->parent = parser.current_scope; + + parser.current_scope = child; } -Token -pop(TokenStack *ts) +void +scope_pop(Arena *arena) { - if(ts->count == 0) return (Token){TOKEN_ERROR, nil, -1, -1}; - return ts->stack[--ts->count]; + Scope *prev = parser.current_scope->parent; + parser.current_scope = prev; } -Token -top(TokenStack *ts) +Symbol * +scope_get_symbol(Scope *scope, const char *name, u32 name_length) { - if(ts->count == 0) return (Token){TOKEN_ERROR, nil, -1, -1}; - return ts->stack[ts->count - 1]; + if (!scope) return nil; + + u32 count = scope->symbols->count; + for (u32 i = 0; i < count; i++) { + Symbol *sym = list_get(scope->symbols, i); + if (sleq(sym->name, name, name_length)) { + return sym; + } + } + + return scope_get_symbol(scope->parent, name, name_length); } -bool -enqueue(TokenQueue *tq, Token t) +Symbol * +scope_add_symbol(Arena *arena, const char *name, u32 name_length, SymbolType type, u32 size) { - if(tq->count >= tq->capacity) return false; + Symbol *sym = scope_get_symbol(parser.current_scope, name, name_length); + if (sym != nil) return sym; - tq->queue[tq->end] = t; - tq->end = (tq->end + 1) % tq->capacity; // Wrap around - tq->count++; - return true; -} - -Token -dequeue(TokenQueue *tq) -{ - if(tq->count == 0) return (Token){TOKEN_ERROR, NULL, -1, -1}; - - Token t = tq->queue[tq->start]; - tq->start = (tq->start + 1) % tq->capacity; // Wrap around - tq->count--; - return t; -} - -Token -peek_queue(TokenQueue *tq) -{ - if(tq->count == 0) return (Token){TOKEN_ERROR, NULL, -1, -1}; - return tq->queue[tq->start]; -} - -u32 -idx_from_arena(Arena *arena, void *p) -{ - return (u32)((u8 *)p - arena->tape); -} - -void * -ptr_from_arena(Arena *arena, u32 i) -{ - return &arena->tape[i]; -} - -ArenaList * -al_create(Arena *arena, u32 size) -{ - ArenaList *meta = aalloc(arena, sizeof(ArenaList)); - if(!meta) return nil; - - meta->size = size + sizeof(u32); - meta->arena = arena; - meta->head = 0; - meta->tail = 0; - - return meta; -} - -void * -al_append(ArenaList *list, void **out_payload) -{ - void *node = aalloc(list->arena, list->size); - if(!node) return nil; - - u32 idx = idx_from_arena(list->arena, node); - void *payload = node; /* Payload starts at offset 0 */ - - void *cdr_ptr = (u8 *)node + (list->size - sizeof(u32)); - - *(u32 *)cdr_ptr = 0; - - if(list->tail != 0) { - void *prev_node = ptr_from_arena(list->arena, list->tail); - void *prev_cdr = (u8 *)prev_node + (list->size - sizeof(u32)); - *(u32 *)prev_cdr = idx; - } else { - list->head = idx; + sym = aalloc(arena, sizeof(Symbol)); + scpy(sym->name, name, slen(name)); + sym->name_length = slen(name); + sym->type = type; + sym->secondary_type = VOID; // Default + sym->size = size; + sym->ref = 0; + if (type == PLEX || type == METHOD || type == TRAIT) { + sym->args = new_list(arena); + sym->fields = new_list(arena); } - list->tail = idx; - - if(out_payload) *out_payload = payload; - return payload; -} - -void * -al_head(ArenaList *list) -{ - if(list->head == 0) return nil; - return ptr_from_arena(list->arena, list->head); -} - -void * -al_tail(ArenaList *list) -{ - if(list->tail == 0) return nil; - return ptr_from_arena(list->arena, list->tail); -} - -SymbolLink * -symbol_table_find(ArenaList *table, const char *name) -{ - void *current = al_head(table); - Arena *arena = table->arena; - - while(current != nil) { - SymbolLink *link = (SymbolLink *)current; - - if(seq(link->s.name.start, name)) return link; - - u32 next_idx = link->cdr; - current = (next_idx == 0) ? nil : ptr_from_arena(arena, next_idx); - } - return nil; + list_push(arena, parser.current_scope->symbols, sym, sizeof(Symbol)); + + return sym; } /**************************************************** * Parser ***************************************************/ +bool +parse_trait() +{ + return true; +} bool -expression() +parse_plex() { - Token operator_stack[256]; - TokenStack operators = {0}; - operators.stack = operator_stack; - operators.capacity = 256; + return true; +} - Token output_queue[256]; - TokenQueue output = {0}; - output.queue = output_queue; - output.capacity = 256; +bool +parse_function() +{ + return true; +} +bool +parse_if() +{ + return true; +} + +bool +parse_loop() +{ + return true; +} + +bool +parse_while() +{ + return true; +} + +bool +parse_for() +{ + return true; +} + +bool +parse_return() +{ + return true; +} + +bool +parse_assignment() +{ + return true; +} + +bool +parse_expression() +{ + return true; +} + +bool +parse_statement() +{ return true; } diff --git a/parser.h b/parser.h index 7b975dd..c7b17d5 100644 --- a/parser.h +++ b/parser.h @@ -2,102 +2,59 @@ #define UNDAR_PARSER_H #include "libc.h" +#include "list.h" #include "lexer.h" typedef enum symbol_type_e { VOID, BOOL, + BYTE, + INT, + NAT, + REAL, + STR, + U8, I8, I16, - I32, - U8, U16, + I32, U32, - F8, - F16, F32, - STR, ARRAY, FUNCTION, PLEX, METHOD, TRAIT, + CONST, } SymbolType; -typedef struct arena_list_s ArenaList; typedef struct symbol_s Symbol; -typedef struct symbol_link_s SymbolLink; -typedef struct token_stack_s TokenStack; -typedef struct queue_s TokenQueue; +typedef struct scope_s Scope; typedef struct parser_s Parser; +#define MAX_SYMBOL_NAME_LENGTH 64 struct symbol_s { - Token name; - SymbolType type; - u32 size; - i32 scope; - union type_def { - struct trait_def { - u32 field_ref_start; /* reference to field list of symbols */ - u32 methods_ref_start; /* zero if none */ - } trait; - struct plex_def { - u32 field_ref_start; /* reference to field list of symbols */ - u32 methods_ref_start; /* zero if none */ - } plex; - struct function_def { - SymbolType return_type; - u32 arguments_ref_start; /* reference to field list of symbols */ - } function; - struct array_def { - SymbolType type; - u32 length; /* zero means "unbounded" */ - } array; - struct field_def { - u32 offset; - } field; - } def; + char name[MAX_SYMBOL_NAME_LENGTH]; /* ptr to name */ + u8 name_length; /* length of the name, max 64 */ + SymbolType type; /* the type for this symbol */ + SymbolType secondary_type; /* return type for functions/methods, or const if type/plex */ + u32 ref; /* either constant value or pointer to other thing */ + u32 size; /* either size of the plex or length of the array/list/etc. */ + List *args; /* function params or plex constructor args */ + List *fields; /* either plex variable fields, or method signatures */ }; -struct symbol_link_s { - Symbol s; - u32 cdr; /* zero means "end of list" */ -}; - -struct arena_list_s { - Arena *arena; - u32 head; - u32 tail; - u32 size; - u32 count; - i32 parent; -}; - -struct token_stack_s { - Token *stack; - i32 capacity; - i32 count; -}; - -struct queue_s { - Token *queue; - i32 capacity; - i32 start; - i32 end; - i32 count; +struct scope_s { + Scope *parent; /* pointer to this scopes parent to "bubble up"*/ + List *symbols; /* list of symbols that live in this scope */ }; struct parser_s { + Scope *current_scope; Token current; Token previous; }; -bool push(TokenStack *ts, Token t); -Token pop(TokenStack *ts); -Token top(TokenStack *ts); -bool enqueue(TokenQueue *tq, Token t); -Token dequeue(TokenQueue *tq); -Token peek_queue(TokenQueue *tq); bool compile(char *source); #endif