WIP parser
This commit is contained in:
parent
373caf7b5e
commit
8fd281e463
24
libc.c
24
libc.c
|
|
@ -84,7 +84,7 @@ aaloc(Arena *arena, u32 size)
|
||||||
|
|
||||||
pos = arena->count;
|
pos = arena->count;
|
||||||
arena->count += size;
|
arena->count += size;
|
||||||
return &arena->tape[pos];
|
return (void *)&arena->tape[pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
u32
|
u32
|
||||||
|
|
@ -94,3 +94,25 @@ afree(Arena *arena)
|
||||||
arena->count = 0;
|
arena->count = 0;
|
||||||
return freed;
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
2
libc.h
2
libc.h
|
|
@ -84,5 +84,7 @@ u32 slen(const char *str);
|
||||||
u32 snlen(const char *str, u32 max_len);
|
u32 snlen(const char *str, u32 max_len);
|
||||||
void *aalloc(Arena *arena, u32 size);
|
void *aalloc(Arena *arena, u32 size);
|
||||||
u32 afree(Arena *arena);
|
u32 afree(Arena *arena);
|
||||||
|
char *ascpy(Arena *arena, const char *start, u32 length);
|
||||||
|
void *amcpy(Arena *arena, void *from, u32 length);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
230
parser.c
230
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;
|
Scope *child = aalloc(arena, sizeof(Scope));
|
||||||
ts->stack[ts->count++] = t;
|
child->symbols = new_list(arena);
|
||||||
return true;
|
child->parent = parser.current_scope;
|
||||||
|
|
||||||
|
parser.current_scope = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
Token
|
void
|
||||||
pop(TokenStack *ts)
|
scope_pop(Arena *arena)
|
||||||
{
|
{
|
||||||
if(ts->count == 0) return (Token){TOKEN_ERROR, nil, -1, -1};
|
Scope *prev = parser.current_scope->parent;
|
||||||
return ts->stack[--ts->count];
|
parser.current_scope = prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
Token
|
Symbol *
|
||||||
top(TokenStack *ts)
|
scope_get_symbol(Scope *scope, const char *name, u32 name_length)
|
||||||
{
|
{
|
||||||
if(ts->count == 0) return (Token){TOKEN_ERROR, nil, -1, -1};
|
if (!scope) return nil;
|
||||||
return ts->stack[ts->count - 1];
|
|
||||||
|
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
|
Symbol *
|
||||||
enqueue(TokenQueue *tq, Token t)
|
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;
|
sym = aalloc(arena, sizeof(Symbol));
|
||||||
tq->end = (tq->end + 1) % tq->capacity; // Wrap around
|
scpy(sym->name, name, slen(name));
|
||||||
tq->count++;
|
sym->name_length = slen(name);
|
||||||
return true;
|
sym->type = type;
|
||||||
}
|
sym->secondary_type = VOID; // Default
|
||||||
|
sym->size = size;
|
||||||
Token
|
sym->ref = 0;
|
||||||
dequeue(TokenQueue *tq)
|
if (type == PLEX || type == METHOD || type == TRAIT) {
|
||||||
{
|
sym->args = new_list(arena);
|
||||||
if(tq->count == 0) return (Token){TOKEN_ERROR, NULL, -1, -1};
|
sym->fields = new_list(arena);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
list->tail = idx;
|
list_push(arena, parser.current_scope->symbols, sym, sizeof(Symbol));
|
||||||
|
|
||||||
if(out_payload) *out_payload = payload;
|
return sym;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************
|
/****************************************************
|
||||||
* Parser
|
* Parser
|
||||||
***************************************************/
|
***************************************************/
|
||||||
|
bool
|
||||||
|
parse_trait()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
expression()
|
parse_plex()
|
||||||
{
|
{
|
||||||
Token operator_stack[256];
|
return true;
|
||||||
TokenStack operators = {0};
|
}
|
||||||
operators.stack = operator_stack;
|
|
||||||
operators.capacity = 256;
|
|
||||||
|
|
||||||
Token output_queue[256];
|
bool
|
||||||
TokenQueue output = {0};
|
parse_function()
|
||||||
output.queue = output_queue;
|
{
|
||||||
output.capacity = 256;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
89
parser.h
89
parser.h
|
|
@ -2,102 +2,59 @@
|
||||||
#define UNDAR_PARSER_H
|
#define UNDAR_PARSER_H
|
||||||
|
|
||||||
#include "libc.h"
|
#include "libc.h"
|
||||||
|
#include "list.h"
|
||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
|
|
||||||
typedef enum symbol_type_e {
|
typedef enum symbol_type_e {
|
||||||
VOID,
|
VOID,
|
||||||
BOOL,
|
BOOL,
|
||||||
|
BYTE,
|
||||||
|
INT,
|
||||||
|
NAT,
|
||||||
|
REAL,
|
||||||
|
STR,
|
||||||
|
U8,
|
||||||
I8,
|
I8,
|
||||||
I16,
|
I16,
|
||||||
I32,
|
|
||||||
U8,
|
|
||||||
U16,
|
U16,
|
||||||
|
I32,
|
||||||
U32,
|
U32,
|
||||||
F8,
|
|
||||||
F16,
|
|
||||||
F32,
|
F32,
|
||||||
STR,
|
|
||||||
ARRAY,
|
ARRAY,
|
||||||
FUNCTION,
|
FUNCTION,
|
||||||
PLEX,
|
PLEX,
|
||||||
METHOD,
|
METHOD,
|
||||||
TRAIT,
|
TRAIT,
|
||||||
|
CONST,
|
||||||
} SymbolType;
|
} SymbolType;
|
||||||
|
|
||||||
typedef struct arena_list_s ArenaList;
|
|
||||||
typedef struct symbol_s Symbol;
|
typedef struct symbol_s Symbol;
|
||||||
typedef struct symbol_link_s SymbolLink;
|
typedef struct scope_s Scope;
|
||||||
typedef struct token_stack_s TokenStack;
|
|
||||||
typedef struct queue_s TokenQueue;
|
|
||||||
typedef struct parser_s Parser;
|
typedef struct parser_s Parser;
|
||||||
|
|
||||||
|
#define MAX_SYMBOL_NAME_LENGTH 64
|
||||||
struct symbol_s {
|
struct symbol_s {
|
||||||
Token name;
|
char name[MAX_SYMBOL_NAME_LENGTH]; /* ptr to name */
|
||||||
SymbolType type;
|
u8 name_length; /* length of the name, max 64 */
|
||||||
u32 size;
|
SymbolType type; /* the type for this symbol */
|
||||||
i32 scope;
|
SymbolType secondary_type; /* return type for functions/methods, or const if type/plex */
|
||||||
union type_def {
|
u32 ref; /* either constant value or pointer to other thing */
|
||||||
struct trait_def {
|
u32 size; /* either size of the plex or length of the array/list/etc. */
|
||||||
u32 field_ref_start; /* reference to field list of symbols */
|
List *args; /* function params or plex constructor args */
|
||||||
u32 methods_ref_start; /* zero if none */
|
List *fields; /* either plex variable fields, or method signatures */
|
||||||
} 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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct symbol_link_s {
|
struct scope_s {
|
||||||
Symbol s;
|
Scope *parent; /* pointer to this scopes parent to "bubble up"*/
|
||||||
u32 cdr; /* zero means "end of list" */
|
List *symbols; /* list of symbols that live in this scope */
|
||||||
};
|
|
||||||
|
|
||||||
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 parser_s {
|
struct parser_s {
|
||||||
|
Scope *current_scope;
|
||||||
Token current;
|
Token current;
|
||||||
Token previous;
|
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);
|
bool compile(char *source);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue