]> www.git.momoyon.org Git - lang.git/commitdiff
WIP: Trying to port python -> c.
authorahmedsamyh <ahmedsamyh10@gmail.com>
Tue, 25 Feb 2025 10:56:08 +0000 (15:56 +0500)
committerahmedsamyh <ahmedsamyh10@gmail.com>
Tue, 25 Feb 2025 10:56:08 +0000 (15:56 +0500)
.gitignore
Makefile [new file with mode: 0644]
include/commonlib.h [new file with mode: 0644]
main.c [new file with mode: 0644]
main.momo
main.py

index ad5da304c02b6d5bc13e154448885e31809f6777..413de34f5377654c3b2fe1fba17fd000f17ef4d1 100644 (file)
@@ -1,3 +1,4 @@
 test.sh
 lang.sh
 tags
+lang
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..c3c4e45
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,7 @@
+CC=gcc
+CFLAGS=-Wall -Wextra -ggdb -I./include
+LDFLAGS=-L./lib
+LIBS=
+
+lang: main.c
+       $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(LIBS)
diff --git a/include/commonlib.h b/include/commonlib.h
new file mode 100644 (file)
index 0000000..b147ffb
--- /dev/null
@@ -0,0 +1,622 @@
+#ifndef _COMMONLIB_H_\r
+#define _COMMONLIB_H_\r
+#include <stdio.h>\r
+#include <stdbool.h>\r
+#include <stdarg.h>\r
+#include <stdint.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <ctype.h>\r
+#include <assert.h>\r
+\r
+// Memory allocation\r
+#define C_MALLOC malloc\r
+#define C_FREE free\r
+#define C_REALLOC realloc\r
+#define C_MEMCPY memcpy\r
+\r
+// Remove Prefix\r
+#ifdef COMMONLIB_REMOVE_PREFIX\r
+#define ASSERT c_ASSERT\r
+#define ARRAY_LEN c_ARRAY_LEN\r
+\r
+#define da_append c_da_append\r
+#define DYNAMIC_ARRAY_INITIAL_CAPACITY c_DYNAMIC_ARRAY_INITIAL_CAPACITY\r
+// #define c_DYNAMIC_ARRAY_INITIAL_CAPACITY\r
+\r
+#define os_get_timedate c_os_get_timedate\r
+#define os_file_exists c_os_file_exists\r
+\r
+#define log_error c_log_error\r
+#define log_info c_log_info\r
+#define log_warning c_log_warning\r
+\r
+#define slurp_file c_slurp_file\r
+#define touch_file_if_doesnt_exist c_touch_file_if_doesnt_exist\r
+\r
+#define Arena c_Arena\r
+#define Arena_make c_Arena_make\r
+#define Arena_alloc c_Arena_alloc\r
+#define Arena_reset c_Arena_reset\r
+#define Arena_free c_Arena_free\r
+#define Arena_alloc_str c_Arena_alloc_str\r
+#define Arena_alloc_wstr c_Arena_alloc_wstr\r
+\r
+#define String_view c_String_view\r
+\r
+#define shift_args c_shift_args\r
+\r
+#endif // COMMONLIB_REMOVE_PREFIX\r
+\r
+// typedefs\r
+typedef unsigned int uint;\r
+typedef uint8_t      uint8;\r
+typedef uint16_t     uint16;\r
+typedef uint32_t     uint32;\r
+typedef uint64_t     uint64;\r
+\r
+typedef int8_t  int8;\r
+typedef int16_t int16;\r
+typedef int32_t int32;\r
+typedef int64_t int64;\r
+\r
+typedef float  float32;\r
+typedef double float64;\r
+\r
+typedef wchar_t wchar;\r
+\r
+typedef const char*  cstr;\r
+typedef const wchar* wstr;\r
+\r
+\r
+// Macros\r
+#define c_ASSERT(condition, msg) do {\\r
+                if (!(condition)) {\\r
+                        fprintf(stderr, "%s:%d:0 [ASSERTION FAILED] %s: %s", __FILE__, __LINE__, #condition, msg);\\r
+                        exit(1);\\r
+                }\\r
+        } while (0)\r
+\r
+#define c_ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0]))\r
+\r
+#define c_pop_front(xs, xsz) (assert(xsz > 0 && "Array is empty"), xsz--, *xs++)\r
+#define c_shift_args c_pop_front\r
+\r
+//\r
+// Struct pre-decls\r
+//\r
+\r
+typedef struct c_Arena c_Arena;\r
+\r
+//\r
+// ## Data Structures\r
+//\r
+\r
+//\r
+// Dynamic-Array\r
+//\r
+\r
+// NOTE: To use c_da_append() the Dynamic-Array struct should be defined using\r
+// DEFINE_DYNAMIC_ARRAY or have the same members as below!\r
+// NOTE!!!: We actually don't want this since this makes the user want to \r
+// use this macro to define dynamic arrays. But the user might want extra fields\r
+// in the struct; So we recommend defining da structs manually like:\r
+// ```C\r
+// typedef struct {\r
+//    <item-type> items;\r
+//    size_t count;\r
+//    size_t capacity;\r
+//    [extra fields...];\r
+// }\r
+// ```\r
+// #define DEFINE_DYNAMIC_ARRAY(struct_name, elm_type) typedef struct {\r
+//         elm_type *items;\r
+//         size_t count;\r
+//         size_t capacity;\r
+//     }\r
+\r
+#define c_DYNAMIC_ARRAY_INITIAL_CAPACITY (sizeof(size_t))\r
+\r
+#define c_da_append(da, elm) do {\\r
+               if ((da).items == NULL) {\\r
+                       (da).capacity = c_DYNAMIC_ARRAY_INITIAL_CAPACITY;\\r
+                       (da).count = 0;\\r
+                       (da).items = C_MALLOC(sizeof(elm) * (da).capacity);\\r
+               }\\r
+               if ((da).count >= (da).capacity) {\\r
+                       (da).capacity *= 2;\\r
+                        (da).items = C_REALLOC((da).items, (da).capacity * sizeof(elm));\\r
+                       c_ASSERT((da).items != NULL, "TODO: Log error instead of asserting");\\r
+               }\\r
+               (da).items[(da).count++] = elm;\\r
+       } while (0)\r
+\r
+#define c_da_pop_front(da) (c_ASSERT(da.count > 0, "Array is empty"), da.count--, *da.items++)\r
+\r
+//\r
+// OS\r
+//\r
+\r
+#if defined(__linux__)\r
+#include <sys/stat.h>\r
+#endif\r
+\r
+void c_os_get_timedate(c_Arena* a);\r
+bool c_os_file_exists(cstr filename);\r
+\r
+//\r
+// Logging\r
+//\r
+\r
+#define c_log_error(fmt, ...) do {\\r
+               fprintf(stderr, "%s"fmt"\n", "[ERROR] ", ##__VA_ARGS__);\\r
+       } while (0)\r
+#define c_log_info(fmt, ...) do {\\r
+               fprintf(stdout, "%s"fmt"\n", "[INFO] ", ##__VA_ARGS__);\\r
+       } while (0)\r
+#define c_log_warning(fmt, ...) do {\\r
+               fprintf(stdout, "%s"fmt"\n", "[WARNING] ", ##__VA_ARGS__);\\r
+       } while (0)\r
+\r
+//\r
+// File\r
+//\r
+\r
+// reads entire file and gives back the string holding the contents. (caller must be responsible for freeing the string!)\r
+const char* c_slurp_file(const char* filename, bool* success);\r
+void c_touch_file_if_doesnt_exist(cstr file);\r
+\r
+//\r
+// ### Allocators ###\r
+//\r
+\r
+//\r
+// c_Arena\r
+//\r
+\r
+#define ARENA_BUFF_INITIAL_SIZE (1024*4)\r
+\r
+struct c_Arena {\r
+    void* buff;\r
+    uint64 buff_size;\r
+    void* ptr;\r
+};\r
+\r
+// pass size 0 to get ARENA_BUFF_INITIAL_SIZE\r
+c_Arena c_Arena_make(size_t size);\r
+void* c_Arena_alloc(c_Arena* a, size_t size);\r
+void c_Arena_reset(c_Arena* a);\r
+void c_Arena_free(c_Arena* a);\r
+\r
+#define c_Arena_alloc_str(a, fmt, ...)    c_Arena_alloc(&(a), sizeof(char)*stbsp_snprintf((a).ptr, (int)((a).buff_size - ((uint8*)(a).ptr - (uint8*)(a).buff)), (fmt), __VA_ARGS__)+1)\r
+#define c_Arena_alloc_wstr(a, fmt, ...) c_Arena_alloc(&a, sizeof(char)*wprintf(a.ptr, a.buff_size - ((uint8*)a.ptr - (uint8*)a.buff), (fmt), __VA_ARGS__)+1)\r
+\r
+//\r
+// String Builder\r
+//\r
+\r
+typedef struct {\r
+    char* data;\r
+    size_t size;\r
+    size_t capacity;\r
+} c_String_builder;\r
+\r
+void c_sb_append(c_String_builder* sb, char* data);\r
+\r
+//\r
+// String view\r
+//\r
+\r
+typedef struct {\r
+    char *data;\r
+    size_t count;\r
+} c_String_view;\r
+\r
+#define c_SV_FMT "%.*s"\r
+#define c_SV_ARG(sv) (int)sv.count, sv.data\r
+\r
+#define c_SV(cstr) (c_String_view){.data = cstr, strlen(cstr)}\r
+\r
+void c_sv_print_dumb(c_String_view sv);\r
+c_String_view c_sv_from_cstr(const char* cstr); // Actually just use SV(cstr) macro...\r
+c_String_view c_sv_lpop(c_String_view* sv, uint32 n);\r
+c_String_view c_sv_lpop_until_predicate(c_String_view* sv, int(*predicate)(int));\r
+c_String_view c_sv_rpop_until_predicate(c_String_view* sv, int(*predicate)(int));\r
+c_String_view c_sv_lpop_until_char(c_String_view* sv, char ch);\r
+c_String_view c_sv_rpop_until_char(c_String_view* sv, char ch);\r
+void c_sv_lremove(c_String_view* sv, size_t n);\r
+void c_sv_rremove(c_String_view* sv, size_t n);\r
+void c_sv_lremove_until_char(c_String_view* sv, char ch);\r
+void c_sv_rremove_until_char(c_String_view* sv, char ch);\r
+void c_sv_lremove_until_char_after(c_String_view* sv, char ch);\r
+void c_sv_rremove_until_char_after(c_String_view* sv, char ch);\r
+void c_sv_ltrim(c_String_view* sv);\r
+void c_sv_rtrim(c_String_view* sv);\r
+void c_sv_trim(c_String_view* sv);\r
+char* c_sv_to_cstr(c_String_view sv);\r
+int32 c_sv_to_int(c_String_view sv);\r
+uint64 c_sv_to_uint64(c_String_view sv);\r
+uint8 c_sv_to_uint8_hex(c_String_view sv);\r
+void* c_sv_to_ptr(c_String_view sv);\r
+float32 c_sv_to_float(c_String_view sv);\r
+bool c_sv_contains_char(c_String_view sv, char ch);\r
+bool c_sv_is_hex_numbers(c_String_view sv);\r
+bool c_sv_equals(c_String_view sv1, c_String_view sv2);\r
+\r
+#endif /* _COMMONLIB_H_ */\r
+\r
+//////////////////////////////////////////////////\r
+#ifdef COMMONLIB_IMPLEMENTATION\r
+#include <string.h>\r
+#include <errno.h>\r
+#include <stdlib.h>\r
+\r
+// My things implementation:\r
+\r
+//\r
+// OS\r
+//\r
+\r
+#if defined(_WIN32) || defined(__CYGWIN__)\r
+void c_os_get_timedate(c_Arena* a) {\r
+        (void)a;\r
+        c_ASSERT(false, "Unimplemented!");\r
+}\r
+\r
+bool c_os_file_exists(cstr filename) {\r
+        (void) filename;\r
+        c_ASSERT(false, "Unimplemented!");\r
+        return false;\r
+}\r
+\r
+#elif defined(__linux__)\r
+void c_os_get_timedate(c_Arena* a) {\r
+        (void)a;\r
+        c_ASSERT(false, "Unimplemented!");\r
+}\r
+\r
+bool c_os_file_exists(cstr filename) {\r
+        struct stat buf;\r
+        return stat(filename, &buf) == 0;\r
+}\r
+#endif\r
+\r
+// simple and dirty way to have defering in C (not recommended to use!)\r
+#define defer(ret_val) \\r
+    result = ret_val;\\r
+    goto defer\r
+\r
+// TODO: Refactor error messages\r
+const char *c_slurp_file(const char* filename, bool* success) {\r
+    FILE* f = fopen(filename, "rb");\r
+    char* result = NULL;\r
+\r
+    if (f == NULL){\r
+        c_log_error("slurp_file::fopen(\"%s\", \"rb\") -> %s\n", filename, strerror(errno));\r
+        defer(NULL);\r
+    }\r
+\r
+    if (fseek(f, 0, SEEK_END) < 0) {\r
+        c_log_error("slurp_file::fseek(%s, 0, SEEK_END) -> %s\n", filename, strerror(errno));\r
+        defer(NULL);\r
+    }\r
+\r
+    size_t fsize = ftell(f);\r
+\r
+    if (fsize == (size_t)-1){\r
+        c_log_error("slurp_file::ftell(%s) -> %s\n", filename, strerror(errno));\r
+        defer(NULL);\r
+    }\r
+\r
+    result = C_MALLOC(sizeof(char)*(fsize+1));\r
+\r
+    if (result == NULL){\r
+        c_log_error("slurp_file::malloc(%zu) -> %s\n", sizeof(char)*fsize, strerror(errno));\r
+        defer(NULL);\r
+    }\r
+\r
+    if (fseek(f, 0, SEEK_SET) < 0) {\r
+        c_log_error("slurp_file::fseek(%s, 0, SEEK_SET) -> %s\n", filename, strerror(errno));\r
+        defer(NULL);\r
+    }\r
+\r
+    if (fread((char*)result, sizeof(char), fsize, f) != fsize){\r
+        c_log_error("slurp_file::fread(result, %zu, 1, f) -> %s\n", fsize, strerror(errno));\r
+        defer(NULL);\r
+    }\r
+\r
+    // set null-terminator\r
+    result[fsize] = '\0';\r
+\r
+ defer:\r
+    if (f) fclose(f);\r
+    *success = result != NULL;\r
+    return result;\r
+}\r
+\r
+void c_touch_file_if_doesnt_exist(cstr filename) {\r
+        if (c_os_file_exists(filename)) return;\r
+        FILE* file = fopen(filename, "w");\r
+        if (file) fclose(file);\r
+}\r
+\r
+//\r
+// ### Allocators ###\r
+//\r
+\r
+// c_Arena\r
+\r
+c_Arena c_Arena_make(size_t size) {\r
+    c_Arena res = {0};\r
+    res.buff_size = size == 0 ? ARENA_BUFF_INITIAL_SIZE : size;\r
+    res.buff = C_MALLOC(res.buff_size);\r
+    res.ptr = res.buff;\r
+\r
+    c_ASSERT(res.buff, "Malloc failed?");\r
+\r
+    return res;\r
+}\r
+\r
+void* c_Arena_alloc(c_Arena* a, size_t size) {\r
+    c_ASSERT(a->buff, "Bro pass an initialized arena!");\r
+\r
+    void* res = a->ptr;\r
+    a->ptr = (uint8*)a->ptr + size;\r
+\r
+    size_t diff = (size_t)((uint8*)a->ptr - (uint8*)a->buff);\r
+    if (diff > a->buff_size) {\r
+        c_log_info("c_Arena resized from %zu to %zu", a->buff_size, a->buff_size*2);\r
+        a->buff_size *= 2;\r
+        a->buff = C_REALLOC(a->buff, a->buff_size);\r
+        a->ptr = (uint8*)a->buff + diff;\r
+        res = a->ptr;\r
+        a->ptr = (uint8*)a->ptr + size;\r
+    }\r
+    /* c_ASSERT((size_t)((uint8*)a->ptr - (uint8*)a->buff) <= a->buff_size); */\r
+\r
+    return res;\r
+}\r
+\r
+void c_Arena_reset(c_Arena* a) {\r
+    a->ptr = a->buff;\r
+}\r
+\r
+void c_Arena_free(c_Arena* a) {\r
+    C_FREE(a->buff);\r
+}\r
+\r
+//\r
+// String Builder\r
+//\r
+\r
+void c_sb_append(c_String_builder* sb, char* data) {\r
+    size_t data_size = strlen(data);\r
+    if (sb->size + data_size > sb->capacity) {\r
+        sb->capacity *= 2;\r
+        sb->data = C_REALLOC(sb->data, sb->capacity);\r
+    }\r
+\r
+    // void *memcpy(void dest[restrict .n], const void src[restrict .n],\r
+    C_MEMCPY((void *)((uintptr_t)sb->data + (uintptr_t)sb->data), data, data_size);\r
+    sb->size += data_size;\r
+}\r
+\r
+//\r
+// String view\r
+//\r
+\r
+void c_sv_print_dumb(c_String_view sv){\r
+    for (size_t i = 0; i < (size_t)sv.count; ++i){\r
+        putc(*(sv.data+i), stdout);\r
+    }\r
+}\r
+\r
+c_String_view c_sv_from_cstr(const char* cstr){\r
+    return (c_String_view){\r
+        .data = (char *)cstr,\r
+        .count = strlen(cstr),\r
+    };\r
+}\r
+\r
+c_String_view c_sv_lpop(c_String_view* sv, uint32 n) {\r
+    c_String_view res = {0};\r
+    if (sv->count < n) return res;\r
+    res.data = sv->data;\r
+    res.count = n;\r
+\r
+    sv->data += n;\r
+    sv->count -= n;\r
+\r
+    return res;\r
+}\r
+\r
+c_String_view c_sv_lpop_until_predicate(c_String_view* sv, int(*predicate)(int)){\r
+    const char* old_sv_data = sv->data;\r
+    while (sv->count > 0 && !predicate(*sv->data)){\r
+        sv->data++;\r
+        sv->count--;\r
+    }\r
+\r
+    return (c_String_view){\r
+        .data = sv->data - (sv->data - old_sv_data),\r
+        .count = (sv->data - old_sv_data),\r
+    };\r
+}\r
+\r
+c_String_view c_sv_rpop_until_predicate(c_String_view* sv, int(*predicate)(int)){\r
+    size_t old_sv_count = sv->count;\r
+    while (sv->count > 0 && !predicate(*(sv->data+sv->count-1))){\r
+        sv->count--;\r
+    }\r
+\r
+    return (c_String_view){\r
+        .data = sv->data + sv->count,\r
+        .count = old_sv_count - sv->count,\r
+    };\r
+}\r
+\r
+c_String_view c_sv_lpop_until_char(c_String_view* sv, char ch){\r
+    const char* old_sv_data = sv->data;\r
+    while (sv->count > 0 && *sv->data != ch){\r
+        sv->data++;\r
+        sv->count--;\r
+    }\r
+\r
+    return (c_String_view){\r
+        .data = sv->data - (sv->data - old_sv_data),\r
+        .count = (sv->data - old_sv_data),\r
+    };\r
+}\r
+\r
+c_String_view c_sv_rpop_until_char(c_String_view* sv, char ch){\r
+    size_t old_sv_count = sv->count;\r
+    while (sv->count > 0 && *(sv->data+sv->count-1) != ch){\r
+        sv->count--;\r
+    }\r
+\r
+    return (c_String_view){\r
+        .data = sv->data + sv->count,\r
+        .count = old_sv_count - sv->count,\r
+    };\r
+}\r
+\r
+void c_sv_lremove(c_String_view* sv, size_t n){\r
+    if (n > sv->count) n = sv->count;\r
+\r
+    sv->data += n;\r
+    sv->count -= n;\r
+}\r
+\r
+void c_sv_rremove(c_String_view* sv, size_t n){\r
+    if (n > sv->count)\r
+        sv->count = 0;\r
+    else\r
+        sv->count -= n;\r
+}\r
+\r
+void c_sv_lremove_until_char(c_String_view* sv, char ch){\r
+    while (sv->count > 0 && *sv->data != ch){\r
+        sv->data++;\r
+        sv->count--;\r
+    }\r
+}\r
+\r
+void c_sv_rremove_until_char(c_String_view* sv, char ch){\r
+    while (sv->count > 0 && *(sv->data+sv->count-1) != ch){\r
+        sv->count--;\r
+    }\r
+}\r
+\r
+void c_sv_lremove_until_char_after(c_String_view* sv, char ch){\r
+    while (sv->count > 0 && *(sv->data-1) != ch){\r
+        sv->data++;\r
+        sv->count--;\r
+    }\r
+}\r
+\r
+void c_sv_rremove_until_char_after(c_String_view* sv, char ch){\r
+    while (sv->count > 0 && *(sv->data+sv->count) != ch){\r
+        sv->count--;\r
+    }\r
+}\r
+\r
+void c_sv_ltrim(c_String_view* sv){\r
+    while (sv->count > 0 && isspace(*sv->data)){\r
+        sv->data++;\r
+        sv->count--;\r
+    }\r
+}\r
+\r
+void c_sv_rtrim(c_String_view* sv){\r
+    while (sv->count > 0 && isspace(*(sv->data+sv->count-1))){\r
+        sv->count--;\r
+    }\r
+}\r
+\r
+void c_sv_trim(c_String_view* sv){\r
+    c_sv_ltrim(sv);\r
+    c_sv_rtrim(sv);\r
+}\r
+\r
+char* c_sv_to_cstr(c_String_view sv){\r
+    char* res = (char*)calloc(1, sizeof(char)*sv.count);\r
+    C_MEMCPY(res, sv.data, sv.count);\r
+    return res;\r
+}\r
+\r
+// TODO: check for failure of conversion. returns 0/0.0 on failure, so just check if the str contains zero.\r
+int32 c_sv_to_int(c_String_view sv) {\r
+    char* str = c_sv_to_cstr(sv);\r
+    int32 res = atoi(str);\r
+    C_FREE(str);\r
+    return res;\r
+}\r
+\r
+uint64 c_sv_to_uint64(c_String_view sv) {\r
+    char* str = c_sv_to_cstr(sv);\r
+    uint64 res = (uint64)atoll(str);\r
+    C_FREE(str);\r
+    return res;\r
+}\r
+\r
+uint8 c_sv_to_uint8_hex(c_String_view sv) {\r
+    char* str = c_sv_to_cstr(sv);\r
+    char* end = str + sv.count;\r
+    uint8 res = (uint8)strtol(str, &end, 16);\r
+    C_FREE(str);\r
+    return res;\r
+}\r
+\r
+float32 c_sv_to_float(c_String_view sv) {\r
+    char* str = c_sv_to_cstr(sv);\r
+    float32 res = (float32)atof(str);\r
+    C_FREE(str);\r
+    return res;\r
+}\r
+\r
+void*    c_sv_to_ptr(c_String_view sv) {\r
+    char* str = c_sv_to_cstr(sv);\r
+    char* end = NULL;\r
+    void* res = (void*)strtoull(str, &end, 16);\r
+    C_FREE(str);\r
+    return res;\r
+}\r
+\r
+bool c_sv_contains_char(c_String_view sv, char ch){\r
+    for (size_t i = 0; i < sv.count; ++i){\r
+        if (sv.data[i] == ch) return true;\r
+    }\r
+    return false;\r
+}\r
+\r
+bool c_sv_is_hex_numbers(c_String_view sv) {\r
+    char hex[] = {\r
+        '0', '1', '2', '3', '4', '5', '6', '7',\r
+        '8', '9', '0', 'a', 'b', 'c', 'd', 'e', 'f',\r
+        'A', 'B', 'C', 'D', 'E', 'F'\r
+    };\r
+    bool found = false;\r
+    for (size_t i = 0; i < sv.count; ++i) {\r
+        char c = sv.data[i];\r
+        for (size_t j = 0; j < c_ARRAY_LEN(hex); ++j) {\r
+            if (hex[j] == c) {\r
+       found = true;\r
+            }\r
+        }\r
+    }\r
+\r
+    return found;\r
+}\r
+\r
+bool c_sv_equals(c_String_view sv1, c_String_view sv2) {\r
+    if (sv1.count != sv2.count) return false;\r
+    for (size_t i = 0; i < sv1.count; ++i) {\r
+        if (sv1.data[i] != sv2.data[i]) {\r
+            return false;\r
+        }\r
+    }\r
+\r
+    return true;\r
+}\r
+\r
+#endif\r
diff --git a/main.c b/main.c
new file mode 100644 (file)
index 0000000..6de8c60
--- /dev/null
+++ b/main.c
@@ -0,0 +1,120 @@
+#include <stdio.h>
+
+#define COMMONLIB_IMPLEMENTATION
+#define COMMONLIB_REMOVE_PREFIX
+#include <commonlib.h>
+
+#define error log_error
+#define info log_info
+
+void usage(const char *program) {
+    info("Usage: %s <file>", program);
+}
+
+typedef struct {
+    const char *src;
+    size_t      src_len;
+    size_t cur;
+    size_t bol; // Beginning of Line
+    size_t line;
+    const char *filename;
+} Lexer;
+
+typedef struct {
+    const char *lexeme;
+} Token;
+
+typedef struct {
+    Token *items;
+    size_t count;
+    size_t capacity;
+} Tokens;
+
+Lexer make_lexer(const char *filename) {
+    bool ok = false;
+    const char *buf = slurp_file(filename, &ok);
+    if (!ok) {
+        error("Failed to open '%s'", filename);
+        exit(1);
+    }
+    Lexer l = {
+        .src = buf,
+        .src_len = strlen(buf),
+        .cur = 0,
+        .bol = 0,
+        .line = 1,
+        .filename = filename,
+    };
+
+    return l;
+}
+
+bool eof(Lexer *l) {
+    return l->cur >= l->src_len;
+}
+
+char current_char(Lexer *l) {
+    ASSERT(!eof(l), "Trying to get char after EOF");
+    return l->src[l->cur];
+}
+
+char consume_char(Lexer *l) {
+    char ch = current_char(l);
+    l->cur += 1;
+    return ch;
+}
+
+void left_trim(Lexer *l) {
+    while (!eof(l) && isspace(current_char(l))) {
+        // TODO: Care about window's \r\n....
+        if (current_char(l) == '\n') {
+            l->line += 1;
+            l->bol = l->cur + 1;
+        }
+        consume_char(l);
+    }
+}
+
+bool next_token(Lexer *l, Token *t_out) {
+    left_trim(l);
+
+    if (eof(l)) return false;
+
+    char ch = current_char(l);
+
+    switch (ch) {
+    }
+
+    /*info("ch: '%c'", ch);*/
+
+    return true;
+}
+
+Tokens lex(Lexer *l) {
+    Tokens tokens = {0};
+    Token t = {0};
+    while (next_token(l, &t)) {
+        da_append(tokens, t);
+    }
+
+    return tokens;
+}
+
+int main(int argc, char **argv) {
+    const char *program = shift_args(argv, argc);
+
+    if (argc <= 0) {
+        error("Please provide a filename!");
+        usage(program);
+        return 1;
+    }
+
+    const char *filename = shift_args(argv, argc);
+
+    Lexer l = make_lexer(filename);
+
+    lex(&l);
+
+    info("OK");
+    return 0;
+}
index 7764457adce91cdbfb088903c0fbc696fe61d439..ee884b9830f197bef3d1dd7c63327aad2b474521 100644 (file)
--- a/main.momo
+++ b/main.momo
@@ -1,4 +1 @@
-msg != 0;
-msg: string = "test";
-msg = string;
-// msg: string = "Hello, World";
+int a = 0;
diff --git a/main.py b/main.py
index 94755404e97da32ed241ca93d321d60ae28c16eb..00862a438eddac98c8aa90ac22dd52ad6deb5336 100644 (file)
--- a/main.py
+++ b/main.py
@@ -125,6 +125,9 @@ class Token:
     def __str__(self):
         return f"Token ({token_type_as_str_map[self.typ]}, '{self.lexeme}', {self.loc})"
 
+    def __repr__(self):
+        return self.__str__()
+
 class Lexer:
     def __init__(self, filename: str):
         try:
@@ -710,6 +713,8 @@ def main():
     # Lexical Analysis
     tokens = lexer.lex()
 
+    print(tokens)
+
     # TODO: Parse
     parser = Parser(tokens)