Getting ready to start the initial parser
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 18 May 2020 03:28:28 +0000 (22:28 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 18 May 2020 03:28:28 +0000 (22:28 -0500)
Makefile
bh.h
docs/parse_grammar
onyx
onyx.c
onyxlex.c
onyxlex.h
onyxparser.c
onyxparser.h
progs/minimal.onyx [new file with mode: 0644]
progs/mvp.onyx

index 187b707fa3b34a86b43ad36bf71128f3b6ffe38c..a3c6d82e3252d7f1d02975fba22fb936c21eafd2 100644 (file)
--- 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 10f503e74a3ae114c188e6eccef40726a0f64521..89746593ce2027a013f5e47d07a921188a195667 100644 (file)
--- 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;
+}
 
 
 //-------------------------------------------------------------------------------------
index d4642989d26468e182e9f12cda84314c352be003..821b5120af9d4ccfdbca1b579eaa623f176ea9ac 100644 (file)
@@ -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 b8911011cf089071f0bbd84ada557389a703a101..40a17c46c671440e0ad8fe44d735b485029ac837 100755 (executable)
Binary files a/onyx and b/onyx differ
diff --git a/onyx.c b/onyx.c
index e08127dec0e98f225b7ab2fb1952832812e60932..42fbb892abf16f5fbd161cacdbbd03f19ab6499e 100644 (file)
--- a/onyx.c
+++ b/onyx.c
@@ -6,6 +6,7 @@
 #include <stdio.h> // TODO: Replace with custom lib
 
 #include "onyxlex.h"
+#include "onyxparser.h"
 
 int main(int argc, char *argv[]) {
        bh_file source_file;
index 0eef2e79bd7035bd50fdf8d43504e309efaee393..b25256f0800c5e5644b2514e32e065a6f6c2de4d 100644 (file)
--- 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);
                }
index 399ca1cbcf8b03de758e6c1ceca1749c3d9c5729..15b19b4038267651c2781581012fb4348cf87d63 100644 (file)
--- 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,
index 873380b6c56959da54172ef02b33bd55668ff894..8db202c7597bd1001c840a63cf822a5830612818 100644 (file)
@@ -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
index eccf9610e2f6da7f00e0983505b5018a9f0e45f3..c8b2c7e261c5bd127554731b81f651bdaf9ee179 100644 (file)
@@ -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 (file)
index 0000000..7b9209a
--- /dev/null
@@ -0,0 +1,3 @@
+add :: proc(a i32, b i32) -> i32 {
+       return a + b
+};
\ No newline at end of file
index cef77e5047478856fc4273b87b4d724171cb9a82..1cfbedc218c65e281472a72432f051a5fe08bf1e 100644 (file)
@@ -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