From: Brendan Hansen Date: Mon, 18 May 2020 03:28:28 +0000 (-0500) Subject: Getting ready to start the initial parser X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=dc63dabb606009a090dc53e5722209a11e7b83e2;p=onyx.git Getting ready to start the initial parser --- diff --git a/Makefile b/Makefile index 187b707f..a3c6d82e 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ OBJ_FILES=\ onyxlex.o \ + onyxparser.o \ onyx.o CC=gcc diff --git a/bh.h b/bh.h index 10f503e7..89746593 100644 --- a/bh.h +++ b/bh.h @@ -114,7 +114,15 @@ i64 chars_match(char* ptr1, char* ptr2); #define bh_clamp(v, a, b) (bh_min((b), bh_max((a), (v)))) #define bh_abs(x) ((x) < 0 ? -(x) : (x)) + + + + +//------------------------------------------------------------------------------------- +// Helpful macros +//------------------------------------------------------------------------------------- #define bh_pointer_add(ptr, amm) ((void *)((u8 *) ptr + amm)) +#define BH_BIT(x) (1 << (x)) @@ -192,10 +200,16 @@ BH_ALLOCATOR_PROC(bh_arena_allocator_proc); +// SCRATCH ALLOCATOR +typedef struct bh_scratch { + bh_allocator backing; + ptr memory, end, curr; +} bh_scratch; - - - +void bh_scratch_init(bh_scratch* scratch, bh_allocator backing, isize scratch_size); +void bh_scratch_free(bh_scratch* scratch); +bh_allocator bh_scratch_allocator(bh_scratch* scratch); +BH_ALLOCATOR_PROC(bh_scratch_allocator_proc); @@ -736,6 +750,58 @@ BH_ALLOCATOR_PROC(bh_arena_allocator_proc) { +// SCRATCH ALLOCATOR IMPLEMENTATION +void bh_scratch_init(bh_scratch* scratch, bh_allocator backing, isize scratch_size) { + ptr memory = bh_alloc(backing, scratch_size); + + scratch->backing = backing; + scratch->memory = memory; + scratch->curr = memory; + scratch->end = memory + scratch_size; +} + +void bh_scratch_free(bh_scratch* scratch) { + bh_free(scratch->backing, scratch->memory); + + scratch->memory = NULL; + scratch->curr = NULL; + scratch->end = NULL; +} + +bh_allocator bh_scratch_allocator(bh_scratch* scratch) { + return (bh_allocator) { + .proc = bh_scratch_allocator_proc, + .data = scratch, + }; +} + +BH_ALLOCATOR_PROC(bh_scratch_allocator_proc) { + bh_scratch* scratch = (bh_scratch*) data; + ptr retval = NULL; + + switch (action) { + case bh_allocator_action_alloc: { + if (size > scratch->end - scratch->memory) { + return NULL; + } + + retval = scratch->curr; + scratch->curr += size; + + if (scratch->curr >= scratch->end) { + scratch->curr = scratch->memory; + retval = scratch->curr; + } + } break; + + case bh_allocator_action_free: + case bh_allocator_action_resize: + // Do nothing + break; + } + + return retval; +} //------------------------------------------------------------------------------------- diff --git a/docs/parse_grammar b/docs/parse_grammar index d4642989..821b5120 100644 --- a/docs/parse_grammar +++ b/docs/parse_grammar @@ -27,7 +27,7 @@ TOP_LEVEL_VALUE FUNCTION_DECLARATION = proc FUNCTION_TYPE BLOCK -FUNCTION_TYPE = :: ( FUNCTION_PARAMS ) -> TOKEN_TYPE_SYMBOL +FUNCTION_TYPE = ( FUNCTION_PARAMS ) -> TOKEN_TYPE_SYMBOL -- This may be too weird... BLOCK = { STATEMENTS | --- diff --git a/onyx b/onyx index b8911011..40a17c46 100755 Binary files a/onyx and b/onyx differ diff --git a/onyx.c b/onyx.c index e08127de..42fbb892 100644 --- a/onyx.c +++ b/onyx.c @@ -6,6 +6,7 @@ #include // TODO: Replace with custom lib #include "onyxlex.h" +#include "onyxparser.h" int main(int argc, char *argv[]) { bh_file source_file; diff --git a/onyxlex.c b/onyxlex.c index 0eef2e79..b25256f0 100644 --- a/onyxlex.c +++ b/onyxlex.c @@ -34,6 +34,7 @@ static const char* onyx_token_type_names[] = { "TOKEN_TYPE_SYM_MINUS", "TOKEN_TYPE_SYM_STAR", "TOKEN_TYPE_SYM_PERCENT", + "TOKEN_TYPE_SYM_DOT", "TOKEN_TYPE_SYM_FSLASH", "TOKEN_TYPE_SYM_BSLASH", "TOKEN_TYPE_SYM_TYPE_SIGNATURE", @@ -163,8 +164,9 @@ OnyxToken onyx_get_token(OnyxTokenizer* tokenizer) { LITERAL_TOKEN("+", TOKEN_TYPE_SYM_PLUS); LITERAL_TOKEN("-", TOKEN_TYPE_SYM_MINUS); LITERAL_TOKEN("*", TOKEN_TYPE_SYM_STAR); - LITERAL_TOKEN("/", TOKEN_TYPE_SYM_FSLASH); + LITERAL_TOKEN(".", TOKEN_TYPE_SYM_DOT); LITERAL_TOKEN("%", TOKEN_TYPE_SYM_PERCENT); + LITERAL_TOKEN("/", TOKEN_TYPE_SYM_FSLASH); LITERAL_TOKEN("\\", TOKEN_TYPE_SYM_BSLASH); LITERAL_TOKEN("::", TOKEN_TYPE_SYM_TYPE_SIGNATURE); LITERAL_TOKEN(":", TOKEN_TYPE_SYM_COLON); @@ -221,7 +223,7 @@ OnyxToken onyx_get_token(OnyxTokenizer* tokenizer) { // Number literal if (char_is_num(*tokenizer->curr)) { u64 len = 0; - while (char_is_num(*tokenizer->curr) || *tokenizer->curr == '.') { + while (char_is_num(*(tokenizer->curr + 1)) || *(tokenizer->curr + 1) == '.') { len++; INCREMENT_CURR_TOKEN(tokenizer); } diff --git a/onyxlex.h b/onyxlex.h index 399ca1cb..15b19b40 100644 --- a/onyxlex.h +++ b/onyxlex.h @@ -43,6 +43,7 @@ typedef enum OnyxTokenType { TOKEN_TYPE_SYM_MINUS, TOKEN_TYPE_SYM_STAR, TOKEN_TYPE_SYM_PERCENT, + TOKEN_TYPE_SYM_DOT, TOKEN_TYPE_SYM_FSLASH, TOKEN_TYPE_SYM_BSLASH, TOKEN_TYPE_SYM_TYPE_SIGNATURE, diff --git a/onyxparser.c b/onyxparser.c index 873380b6..8db202c7 100644 --- a/onyxparser.c +++ b/onyxparser.c @@ -1,2 +1,23 @@ #include "onyxparser.h" + +struct OnyxTypeInfo builtin_types[] = { + { ONYX_TYPE_INFO_KIND_UNKNOWN, 0, "unknown" }, + { ONYX_TYPE_INFO_KIND_VOID, 0, "void" }, + + { ONYX_TYPE_INFO_KIND_BOOL, 1, "bool", 0, 0, 0, 1 }, + + { ONYX_TYPE_INFO_KIND_UINT8, 1, "u8", 1, 1, 0, 0 }, + { ONYX_TYPE_INFO_KIND_UINT16, 2, "u16", 1, 1, 0, 0 }, + { ONYX_TYPE_INFO_KIND_UINT32, 4, "u32", 1, 1, 0, 0 }, + { ONYX_TYPE_INFO_KIND_UINT64, 8, "u64", 1, 1, 0, 0 }, + + { ONYX_TYPE_INFO_KIND_INT8, 1, "i8", 1, 0, 0, 0 }, + { ONYX_TYPE_INFO_KIND_INT16, 2, "i16", 1, 0, 0, 0 }, + { ONYX_TYPE_INFO_KIND_INT32, 4, "i32", 1, 0, 0, 0 }, + { ONYX_TYPE_INFO_KIND_INT64, 8, "i64", 1, 0, 0, 0 }, + + { ONYX_TYPE_INFO_KIND_FLOAT32, 4, "f32", 0, 0, 1, 0 }, + { ONYX_TYPE_INFO_KIND_FLOAT64, 8, "f64", 0, 0, 1, 0 }, + { ONYX_TYPE_INFO_KIND_SOFT_FLOAT, 8, "sf64", 0, 0, 1, 0 }, +}; \ No newline at end of file diff --git a/onyxparser.h b/onyxparser.h index eccf9610..c8b2c7e2 100644 --- a/onyxparser.h +++ b/onyxparser.h @@ -1,3 +1,4 @@ +#define BH_NO_STRING #include "bh.h" #include "onyxlex.h" @@ -7,12 +8,135 @@ typedef struct OnyxParser { OnyxToken *prev; OnyxToken *curr; - bh_hash(OnyxIdentifier) idens; - - bh_arr(OnyxToken) tokens; /* Maybe don't store the whole array? Ask for one as you need it? */ + bh_allocator allocator; } OnyxParser; -typedef struct OnyxParseNode { +typedef enum OnyxAstNodeKind { + ONYX_PARSE_NODE_KIND_ERROR, + ONYX_PARSE_NODE_KIND_PROGRAM, + + ONYX_PARSE_NODE_KIND_FUNCDEF, + ONYX_PARSE_NODE_KIND_BLOCK, + ONYX_PARSE_NODE_KIND_SCOPE, + + ONYX_PARSE_NODE_KIND_ADD, + ONYX_PARSE_NODE_KIND_SUB, + ONYX_PARSE_NODE_KIND_MUL, + ONYX_PARSE_NODE_KIND_DIVIDE, + ONYX_PARSE_NODE_KIND_MODULUS, + ONYX_PARSE_NODE_KIND_NEGATE, + + ONYX_PARSE_NODE_KIND_TYPE, + ONYX_PARSE_NODE_KIND_LITERAL, + ONYX_PARSE_NODE_KIND_CAST, + ONYX_PARSE_NODE_KIND_PARAM, + ONYX_PARSE_NODE_KIND_CALL, + ONYX_PARSE_NODE_KIND_RETURN, + + ONYX_PARSE_NODE_KIND_EQUAL, + ONYX_PARSE_NODE_KIND_NOT_EQUAL, + ONYX_PARSE_NODE_KIND_GREATER, + ONYX_PARSE_NODE_KIND_GREATER_EQUAL, + ONYX_PARSE_NODE_KIND_LESS, + ONYX_PARSE_NODE_KIND_LESS_EQUAL, + ONYX_PARSE_NODE_KIND_NOT, + + ONYX_PARSE_NODE_KIND_IF, + ONYX_PARSE_NODE_KIND_LOOP, + + ONYX_PARSE_NODE_KIND_COUNT +} OnyxAstNodeKind; + +typedef enum OnyxTypeInfoKind { + ONYX_TYPE_INFO_KIND_UNKNOWN, + ONYX_TYPE_INFO_KIND_VOID, + ONYX_TYPE_INFO_KIND_BOOL, + + ONYX_TYPE_INFO_KIND_UINT8, + ONYX_TYPE_INFO_KIND_UINT16, + ONYX_TYPE_INFO_KIND_UINT32, + ONYX_TYPE_INFO_KIND_UINT64, + + ONYX_TYPE_INFO_KIND_INT8, + ONYX_TYPE_INFO_KIND_INT16, + ONYX_TYPE_INFO_KIND_INT32, + ONYX_TYPE_INFO_KIND_INT64, + + ONYX_TYPE_INFO_KIND_FLOAT32, + ONYX_TYPE_INFO_KIND_FLOAT64, + ONYX_TYPE_INFO_KIND_SOFT_FLOAT, // 64-bits of data but could be treated as 32-bit +} OnyxTypeInfoKind; + +typedef struct OnyxTypeInfo { + OnyxTypeInfoKind kind; + u32 size; // in bytes + const char* name; + u32 is_int : 1; + u32 is_unsigned : 1; + u32 is_float : 1; + u32 is_bool : 1; +} OnyxTypeInfo; + +extern OnyxTypeInfo builtin_types[]; + +typedef union OnyxAstNode OnyxAstNode; +typedef struct OnyxAstNodeBlock OnyxAstNodeBlock; +typedef struct OnyxAstNodeParam OnyxAstNodeParam; +typedef struct OnyxAstNodeFuncDef OnyxAstNodeFuncDef; + +typedef enum OnyxAstFlags { + ONYX_AST_BLOCK_FLAG_HAS_RETURN = BH_BIT(1), + ONYX_AST_BLOCK_FLAG_TOP_LEVEL = BH_BIT(2), + ONYX_AST_BLOCK_FLAG_EXPORTED = BH_BIT(3), +} OnyxAstFlags; + +struct OnyxAstNodeBlock { + OnyxAstNodeKind kind; + u32 flags; OnyxToken *token; + OnyxTypeInfo *return_type; + OnyxAstNode *next; + OnyxAstNode *unused1; + OnyxAstNode *unused2; +}; + +struct OnyxAstNodeParam { + OnyxAstNodeKind kind; + u32 flags; + OnyxToken *token; + OnyxTypeInfo *type; + OnyxAstNode *next; + OnyxAstNode *left; + OnyxAstNode *right; +}; + +struct OnyxAstNodeFuncDef { + OnyxAstNodeKind kind; + u32 flags; + OnyxToken *token; // This will point to the symbol token to identify it + OnyxTypeInfo *return_type; + OnyxAstNodeBlock *body; + OnyxAstNodeParam *params; + u64 param_count; // Same size as ptr + u64 unused1; +}; + +union OnyxAstNode { + + // Generic node structure for capturing all binary ops and statements + struct { + OnyxAstNodeKind kind; + u32 flags; + OnyxToken *token; + OnyxTypeInfo* type; + OnyxAstNode *next; + OnyxAstNode *left; + OnyxAstNode *right; + } as_node; + + OnyxAstNodeBlock as_block; +}; -}; \ No newline at end of file +ptr onyx_ast_node_new(bh_allocator alloc, OnyxAstNodeKind kind); +OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer tokenizer); +OnyxAstNode* onyx_parse(OnyxParser parser); \ No newline at end of file diff --git a/progs/minimal.onyx b/progs/minimal.onyx new file mode 100644 index 00000000..7b9209ad --- /dev/null +++ b/progs/minimal.onyx @@ -0,0 +1,3 @@ +add :: proc(a i32, b i32) -> i32 { + return a + b +}; \ No newline at end of file diff --git a/progs/mvp.onyx b/progs/mvp.onyx index cef77e50..1cfbedc2 100644 --- a/progs/mvp.onyx +++ b/progs/mvp.onyx @@ -2,9 +2,9 @@ /* nested comments /* are /* okay */ */ */ */ -foreign "console" "log" :: proc (data ptr, length i32) -> void ---; - -global thing :: +foreign console { + log :: proc (data ptr, length i32) -> void ---; +} export add :: proc (a i32, b i32) -> i32 { return a + b; @@ -19,4 +19,9 @@ export max :: proc (a i32, b i32) -> i32 { } else { return b; } +}; + +export main :: proc () -> void { + console.log(add(2, 3)); + console.log(max(5, 10)); }; \ No newline at end of file