#include #pragma warning(disable : 4820) // don't care about padding #pragma warning(disable : 4388) // signed/unsigned mismatch probably doesn't matter // #pragma warning(disable : 4100) // unused local doesn't matter, because sometimes I want to kee #pragma warning(disable : 4053) // void operands are used for tricks like applying printf linting to non printf function calls #pragma warning(disable : 4255) // strange no function prototype given thing? #pragma warning(disable : 4456) // I shadow local declarations often and it's fine #pragma warning(disable : 4061) // I don't need to *explicitly* handle everything, having a default: case should mean no more warnings #pragma warning(disable : 4201) // nameless struct/union occurs #pragma warning(disable : 4366) // I think unaligned memory addresses are fine to ignore #pragma warning(disable : 4459) // Local function decl hiding global declaration I think is fine #pragma warning(disable : 5045) // spectre mitigation?? #pragma warning(disable : 4244) // loss of data warning #pragma warning(disable : 4101) // unreferenced local variable #pragma warning(disable : 4100) // unreferenced local variable again? #pragma warning(disable : 4189) // initialized and not referenced #pragma warning(disable : 4242) // conversion #pragma warning(disable : 4457) // hiding function variable happens #pragma warning(disable : 4668) // __GNU_C__ macro undefined, fixing #pragma warning(disable : 4996) // fopen is safe. I don't care about fopen_s #include "md.h" #include "md.c" #define DESKTOP #define WINDOWS #define RND_IMPLEMENTATION #include "makeprompt.h" #include // for sleep. typedef struct Error { struct Error *next, *prev; String8 message; int line; } Error; typedef struct ErrorList { int count; Error *first, *last; } ErrorList; void ErrorPush(Arena *arena, ErrorList *list, Error message) { Error *new_err = PushArrayZero(arena, Error, 1); *new_err = message; QueuePush(list->first, list->last, new_err); list->count += 1; } void error_impl(Arena *arena, ErrorList *errors, int line_in_toparse, String8 message) { ErrorPush(arena, errors, (Error){.line = line_in_toparse, .message = message}); // this is a function so you can breakpoint here and discover when errors occur } #define error(line_in_toparse, fmt_str, ...) error_impl(arena, errors, line_in_toparse, S8Fmt(arena, fmt_str, __VA_ARGS__)) int main(int argc, char **argv) { (void)argc; (void)argv; Arena *arena = ArenaAlloc(); Sleep(200); // have to wait for console to pop up, super annoying // Prose is the name for this file format where you describe the souls of characters // tokenize typedef struct ProseToken { struct ProseToken *next, *prev; String8 field; int field_number; // this is -1 if no field_number, e.g if 'Field Text #0:' isn't specified and had no '#', then this would be -1 String8 value; // may be an empty string, if it's trying to be like, an object int indentation; int line; } ProseToken; ErrorList errors_lit = {0}; ErrorList *errors = &errors_lit; Npc out = {0}; // all arena allocations done from here are temporary. As it just copies data into Npc // parse 'playground.txt' into 'out' { // read the file String8 to_parse = LoadEntireFile(arena, S8Lit("playground.txt")); // tokenize to_parse ProseToken *tokenized_first = 0; ProseToken *tokenized_last = 0; { String8List as_lines = S8Split(arena, to_parse, 1, &S8Lit("\n")); int line = 1; // lines start at 1 for (String8Node *cur = as_lines.first; cur; cur = cur->next) { int indentation = 0; while(indentation < cur->string.size && cur->string.str[indentation] == '\t') indentation += 1; String8 no_funny_business = S8SkipWhitespace(S8ChopWhitespace(cur->string)); if(no_funny_business.size == 0) continue; String8List along_colon = S8Split(arena, no_funny_business, 1, &S8Lit(":")); if(along_colon.node_count != 2 && along_colon.node_count != 1) { error(line, "Requires exactly one ':' on the line to delimit the field and value. Got %d", along_colon.node_count - 1); } else { ProseToken *token_out = PushArrayZero(arena, ProseToken, 1); token_out->field_number = -1; if(along_colon.node_count == 2) token_out->value = along_colon.last->string; token_out->line = line; token_out->indentation = indentation; DblPushBack(tokenized_first, tokenized_last, token_out); } line += 1; } } } if (errors->count > 0) { printf("Failed with errors:\n"); for (Error *cur = errors->first; cur; cur = cur->next) { printf("On line %d of input: %.*s\n", cur->line, S8VArg(cur->message)); } assert(false); } printf("Success.\n"); __debugbreak(); }