//////////////////////////////////////////////////////////// //~ Blob types Enum(JSON_Type) { JSON_Type_Null, JSON_Type_Bool, JSON_Type_Number, JSON_Type_String, JSON_Type_Array, JSON_Type_Object }; Struct(JSON_Blob) { JSON_Type type; String key; JSON_Blob *parent; JSON_Blob *next; JSON_Blob *child_first; JSON_Blob *child_last; union { String string; f64 number; b32 boolean; } value; }; Struct(JSON_Error) { String msg; u64 start; u64 end; JSON_Error *next; }; Struct(JSON_ErrorList) { u64 count; JSON_Error *first; JSON_Error *last; }; Struct(JSON_Result) { JSON_Blob *root; JSON_ErrorList errors; }; //////////////////////////////////////////////////////////// //~ Lexer types #define JSON_Case_Newline \ 0x0A: /* Line feed or New line */ \ case 0x0D /* Carriage return */ #define JSON_Case_Space \ 0x20: /* Space */ \ case 0x09 /* Horizontal tab */ #define JSON_Case_Digit0Through9 \ '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9' #define JSON_Case_Digit1Through9 \ '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9' #define JSON_Case_Symbol \ ',': case ':': case '[': case ']': case '{': case '}' Enum(JSON_TokenKind) { JSON_TokenKind_Unknown, JSON_TokenKind_Number, JSON_TokenKind_String, JSON_TokenKind_KeywordTrue, JSON_TokenKind_KeywordFalse, JSON_TokenKind_KeywordNull, JSON_TokenKind_Comma, JSON_TokenKind_Colon, JSON_TokenKind_SquareBraceOpen, JSON_TokenKind_SquareBraceClose, JSON_TokenKind_CurlyBraceOpen, JSON_TokenKind_CurlyBraceClose, JSON_TokenKind_Bof, JSON_TokenKind_Eof }; Struct(JSON_Token) { JSON_TokenKind kind; u64 start; u64 end; JSON_Token *next; }; Struct(JSON_TokenList) { JSON_Token *token_first; JSON_Token *token_last; }; Enum(JSON_LexNumberState) { JSON_LexNumberState_Whole, JSON_LexNumberState_Fraction, JSON_LexNumberState_Exponent }; Global Readonly String JSON_keyword_strings[] = { ['t'] = CompLit("true"), ['f'] = CompLit("false"), ['n'] = CompLit("null") }; Global Readonly JSON_TokenKind JSON_keyword_types[] = { ['t'] = JSON_TokenKind_KeywordTrue, ['f'] = JSON_TokenKind_KeywordFalse, ['n'] = JSON_TokenKind_KeywordNull }; //////////////////////////////////////////////////////////// //~ Parser types Struct(JSON_Parser) { // Input String src; JSON_Token *at; // Output JSON_Blob *root; JSON_ErrorList errors; }; //////////////////////////////////////////////////////////// //~ Lex JSON_Token *JSON_PushToken(Arena *arena, JSON_TokenList *list); JSON_TokenList JSON_TokensFromString(Arena *arena, String src); //////////////////////////////////////////////////////////// //~ Interpret f64 interpret_number(String src); String interpret_string(Arena *arena, String src, String *error); //////////////////////////////////////////////////////////// //~ Parse void JSON_PushError(Arena *arena, JSON_Parser *p, JSON_Token *t, String msg); void JSON_Parse(Arena *arena, JSON_Parser *p); JSON_Result JSON_BlobFromString(Arena *arena, String src);