mirror of
https://github.com/Ed94/metadesk.git
synced 2026-08-06 15:48:47 +00:00
[api] decompose error pushing functions; expose to main API
This commit is contained in:
@@ -675,6 +675,11 @@ MD_FUNCTION MD_b32 MD_TokenKindIsWhitespace(MD_TokenKind kind);
|
|||||||
MD_FUNCTION MD_b32 MD_TokenKindIsComment(MD_TokenKind kind);
|
MD_FUNCTION MD_b32 MD_TokenKindIsComment(MD_TokenKind kind);
|
||||||
MD_FUNCTION MD_b32 MD_TokenKindIsRegular(MD_TokenKind kind);
|
MD_FUNCTION MD_b32 MD_TokenKindIsRegular(MD_TokenKind kind);
|
||||||
|
|
||||||
|
MD_FUNCTION void MD_PushNodeError(MD_ParseCtx *ctx, MD_Node *node, MD_MessageKind kind, MD_String8 str);
|
||||||
|
MD_FUNCTION void MD_PushNodeErrorF(MD_ParseCtx *ctx, MD_Node *node, MD_MessageKind kind, char *fmt, ...);
|
||||||
|
MD_FUNCTION void MD_PushTokenError(MD_ParseCtx *ctx, MD_Token token, MD_MessageKind kind, MD_String8 str);
|
||||||
|
MD_FUNCTION void MD_PushTokenErrorF(MD_ParseCtx *ctx, MD_Token token, MD_MessageKind kind, char *fmt, ...);
|
||||||
|
|
||||||
MD_FUNCTION MD_ParseCtx MD_Parse_InitializeCtx(MD_String8 filename, MD_String8 contents);
|
MD_FUNCTION MD_ParseCtx MD_Parse_InitializeCtx(MD_String8 filename, MD_String8 contents);
|
||||||
MD_FUNCTION void MD_Parse_Bump(MD_ParseCtx *ctx, MD_Token token);
|
MD_FUNCTION void MD_Parse_Bump(MD_ParseCtx *ctx, MD_Token token);
|
||||||
MD_FUNCTION void MD_Parse_BumpNext(MD_ParseCtx *ctx);
|
MD_FUNCTION void MD_Parse_BumpNext(MD_ParseCtx *ctx);
|
||||||
|
|||||||
+109
-77
@@ -1115,64 +1115,6 @@ MD_PtrMap_Insert(MD_Map *map, MD_MapCollisionRule collision_rule, void *key, voi
|
|||||||
|
|
||||||
//~ Parsing
|
//~ Parsing
|
||||||
|
|
||||||
MD_PRIVATE_FUNCTION_IMPL void
|
|
||||||
_MD_Error(MD_ParseCtx *ctx, MD_Node *node, MD_MessageKind kind, char *fmt, ...)
|
|
||||||
{
|
|
||||||
// NOTE(mal): Sort errors. Traverse the whole list assuming it will be short.
|
|
||||||
// The alternative is to drop a prev pointer into MD_Error and search backwards
|
|
||||||
MD_Error *prev_error = 0;
|
|
||||||
for(MD_Error *e = ctx->first_error; e; e = e->next)
|
|
||||||
{
|
|
||||||
if(e->node->at < node->at)
|
|
||||||
{
|
|
||||||
prev_error = e;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE(mal): Ignore errors after first catastrophic error
|
|
||||||
if(ctx->error_level < MD_MessageKind_CatastrophicError || !prev_error || prev_error->next)
|
|
||||||
{
|
|
||||||
MD_Error *error = MD_PushArray(MD_Error, 1);
|
|
||||||
error->node = node;
|
|
||||||
error->kind = kind;
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
error->string = MD_PushStringFV(fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
if(prev_error)
|
|
||||||
{
|
|
||||||
error->next = prev_error->next;
|
|
||||||
prev_error->next = error;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
error->next = ctx->first_error;
|
|
||||||
ctx->first_error = error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!ctx->last_error || ctx->last_error == prev_error)
|
|
||||||
{
|
|
||||||
ctx->last_error = error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(kind > ctx->error_level)
|
|
||||||
{
|
|
||||||
ctx->error_level = kind;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define _MD_TokenError(ctx, token, kind, fmt, ...) \
|
|
||||||
_MD_Error(ctx, _MD_MakeNode_Ctx(ctx, MD_NodeKind_ErrorMarker,\
|
|
||||||
token.string, token.outer_string,\
|
|
||||||
token.outer_string.str), \
|
|
||||||
kind, fmt, __VA_ARGS__)
|
|
||||||
|
|
||||||
// TODO(allen): This helper only helps because `ctx` bundles two elements together
|
// TODO(allen): This helper only helps because `ctx` bundles two elements together
|
||||||
// that the "low level" MD_MakeNode treats as seperate. However they aren't very
|
// that the "low level" MD_MakeNode treats as seperate. However they aren't very
|
||||||
// useful as seperate concepts. If we get the "handle of file" concept down to
|
// useful as seperate concepts. If we get the "handle of file" concept down to
|
||||||
@@ -1248,8 +1190,9 @@ _MD_ParseTagList(MD_ParseCtx *ctx, MD_Node **first_out, MD_Node **last_out)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
MD_Token token = MD_Parse_PeekSkipSome(ctx, 0);
|
MD_Token token = MD_Parse_PeekSkipSome(ctx, 0);
|
||||||
_MD_TokenError(ctx, token, MD_MessageKind_Error, "\"%.*s\" is not a proper tag identifier",
|
MD_PushTokenErrorF(ctx, token, MD_MessageKind_Error,
|
||||||
MD_StringExpand(token.outer_string));
|
"\"%.*s\" is not a proper tag identifier",
|
||||||
|
MD_StringExpand(token.outer_string));
|
||||||
// NOTE(mal): There are reasons to consume the non-tag token, but also to leave it.
|
// NOTE(mal): There are reasons to consume the non-tag token, but also to leave it.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1282,6 +1225,85 @@ MD_TokenKindIsRegular(MD_TokenKind kind)
|
|||||||
return(kind > MD_TokenKind_RegularMin && kind < MD_TokenKind_RegularMax);
|
return(kind > MD_TokenKind_RegularMin && kind < MD_TokenKind_RegularMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MD_FUNCTION void
|
||||||
|
MD_PushNodeError(MD_ParseCtx *ctx, MD_Node *node, MD_MessageKind kind, MD_String8 str){
|
||||||
|
// TODO(allen): pass over this... the catastrophic error logic is a bit hard
|
||||||
|
// for me to follow.
|
||||||
|
|
||||||
|
// NOTE(mal): Sort errors. Traverse the whole list assuming it will be short.
|
||||||
|
// The alternative is to drop a prev pointer into MD_Error and search backwards
|
||||||
|
MD_Error *prev_error = 0;
|
||||||
|
for(MD_Error *e = ctx->first_error; e; e = e->next)
|
||||||
|
{
|
||||||
|
if(e->node->at < node->at)
|
||||||
|
{
|
||||||
|
prev_error = e;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE(mal): Ignore errors after first catastrophic error
|
||||||
|
if(ctx->error_level < MD_MessageKind_CatastrophicError || !prev_error || prev_error->next)
|
||||||
|
{
|
||||||
|
// TODO(allen): put memory on ctx? put memory on persistent arena?
|
||||||
|
// alloc and fill error
|
||||||
|
MD_Error *error = MD_PushArray(MD_Error, 1);
|
||||||
|
error->node = node;
|
||||||
|
error->kind = kind;
|
||||||
|
error->string = str;
|
||||||
|
|
||||||
|
// insert error
|
||||||
|
if(prev_error)
|
||||||
|
{
|
||||||
|
error->next = prev_error->next;
|
||||||
|
prev_error->next = error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error->next = ctx->first_error;
|
||||||
|
ctx->first_error = error;
|
||||||
|
}
|
||||||
|
if(ctx->last_error == prev_error)
|
||||||
|
{
|
||||||
|
ctx->last_error = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set error level
|
||||||
|
if(kind > ctx->error_level)
|
||||||
|
{
|
||||||
|
ctx->error_level = kind;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MD_FUNCTION void
|
||||||
|
MD_PushNodeErrorF(MD_ParseCtx *ctx, MD_Node *node, MD_MessageKind kind, char *fmt, ...){
|
||||||
|
// TODO(allen): use memory from ctx? use persistent memory?
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
MD_PushNodeError(ctx, node, kind, MD_PushStringFV(fmt, args));
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
MD_FUNCTION void
|
||||||
|
MD_PushTokenError(MD_ParseCtx *ctx, MD_Token token, MD_MessageKind kind, MD_String8 str){
|
||||||
|
MD_Node *stub = _MD_MakeNode_Ctx(ctx, MD_NodeKind_ErrorMarker,
|
||||||
|
token.string, token.outer_string, token.outer_string.str);
|
||||||
|
MD_PushNodeError(ctx, stub, kind, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
MD_FUNCTION void
|
||||||
|
MD_PushTokenErrorF(MD_ParseCtx *ctx, MD_Token token, MD_MessageKind kind, char *fmt, ...){
|
||||||
|
// TODO(allen): use memory from ctx? use persistent memory?
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
MD_PushTokenError(ctx, token, kind, MD_PushStringFV(fmt, args));
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
MD_FUNCTION_IMPL MD_ParseCtx
|
MD_FUNCTION_IMPL MD_ParseCtx
|
||||||
MD_Parse_InitializeCtx(MD_String8 filename, MD_String8 contents)
|
MD_Parse_InitializeCtx(MD_String8 filename, MD_String8 contents)
|
||||||
{
|
{
|
||||||
@@ -1721,7 +1743,8 @@ MD_Parse_Set(MD_ParseCtx *ctx, MD_Node *parent, MD_ParseSetFlags flags)
|
|||||||
if(brace) delimiter_char = '{';
|
if(brace) delimiter_char = '{';
|
||||||
else if(paren) delimiter_char = '(';
|
else if(paren) delimiter_char = '(';
|
||||||
else if(bracket) delimiter_char = '[';
|
else if(bracket) delimiter_char = '[';
|
||||||
_MD_TokenError(ctx, initial_token, MD_MessageKind_CatastrophicError, "Unbalanced \"%c\"", delimiter_char);
|
MD_PushTokenErrorF(ctx, initial_token, MD_MessageKind_CatastrophicError,
|
||||||
|
"Unbalanced \"%c\"", delimiter_char);
|
||||||
}
|
}
|
||||||
goto end_parse;
|
goto end_parse;
|
||||||
}
|
}
|
||||||
@@ -1821,8 +1844,8 @@ MD_ParseOneNodeFromCtx(MD_ParseCtx *ctx)
|
|||||||
if(!_MD_CommentIsSyntacticallyCorrect(comment_token))
|
if(!_MD_CommentIsSyntacticallyCorrect(comment_token))
|
||||||
{
|
{
|
||||||
MD_String8 capped = MD_StringPrefix(comment_token.outer_string, MD_UNTERMINATED_TOKEN_LEN_CAP);
|
MD_String8 capped = MD_StringPrefix(comment_token.outer_string, MD_UNTERMINATED_TOKEN_LEN_CAP);
|
||||||
_MD_TokenError(ctx, comment_token, MD_MessageKind_CatastrophicError,
|
MD_PushTokenErrorF(ctx, comment_token, MD_MessageKind_CatastrophicError,
|
||||||
"Unterminated comment \"%.*s\"", MD_StringExpand(capped));
|
"Unterminated comment \"%.*s\"", MD_StringExpand(capped));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1864,8 +1887,8 @@ MD_ParseOneNodeFromCtx(MD_ParseCtx *ctx)
|
|||||||
if(!_MD_StringLiteralIsBalanced(token))
|
if(!_MD_StringLiteralIsBalanced(token))
|
||||||
{
|
{
|
||||||
MD_String8 capped = MD_StringPrefix(token.outer_string, MD_UNTERMINATED_TOKEN_LEN_CAP);
|
MD_String8 capped = MD_StringPrefix(token.outer_string, MD_UNTERMINATED_TOKEN_LEN_CAP);
|
||||||
_MD_Error(ctx, result.node, MD_MessageKind_CatastrophicError,
|
MD_PushNodeErrorF(ctx, result.node, MD_MessageKind_CatastrophicError,
|
||||||
"Unterminated text literal \"%.*s\"", MD_StringExpand(capped));
|
"Unterminated text literal \"%.*s\"", MD_StringExpand(capped));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(token.kind == MD_TokenKind_Symbol && token.string.size == 1 && MD_CharIsReservedSymbol(token.string.str[0]))
|
else if(token.kind == MD_TokenKind_Symbol && token.string.size == 1 && MD_CharIsReservedSymbol(token.string.str[0]))
|
||||||
@@ -1873,11 +1896,12 @@ MD_ParseOneNodeFromCtx(MD_ParseCtx *ctx)
|
|||||||
MD_u8 c = token.string.str[0];
|
MD_u8 c = token.string.str[0];
|
||||||
if(c == '}' || c == ']' || c == ')')
|
if(c == '}' || c == ']' || c == ')')
|
||||||
{
|
{
|
||||||
_MD_TokenError(ctx, token, MD_MessageKind_CatastrophicError, "Unbalanced \"%c\"", c);
|
MD_PushTokenErrorF(ctx, token, MD_MessageKind_CatastrophicError, "Unbalanced \"%c\"", c);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_MD_TokenError(ctx, token, MD_MessageKind_Error, "Unexpected reserved symbol \"%c\"", c);
|
MD_PushTokenErrorF(ctx, token, MD_MessageKind_Error, "Unexpected reserved symbol \"%c\"",
|
||||||
|
c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1897,7 +1921,8 @@ MD_ParseOneNodeFromCtx(MD_ParseCtx *ctx)
|
|||||||
{
|
{
|
||||||
for(MD_EachNode(tag, fc->first_tag))
|
for(MD_EachNode(tag, fc->first_tag))
|
||||||
{
|
{
|
||||||
_MD_Error(ctx, tag, MD_MessageKind_Error, "Invalid position for tag \"%.*s\"", MD_StringExpand(tag->string));
|
MD_PushNodeErrorF(ctx, tag, MD_MessageKind_Error,
|
||||||
|
"Invalid position for tag \"%.*s\"", MD_StringExpand(tag->string));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1909,10 +1934,12 @@ MD_ParseOneNodeFromCtx(MD_ParseCtx *ctx)
|
|||||||
MD_String8List bytes = {0};
|
MD_String8List bytes = {0};
|
||||||
for(int i_byte = 0; i_byte < token.outer_string.size; ++i_byte)
|
for(int i_byte = 0; i_byte < token.outer_string.size; ++i_byte)
|
||||||
{
|
{
|
||||||
|
// TODO(allen): tighten up with good integer <-> string helpers
|
||||||
MD_PushStringToList(&bytes, MD_PushStringF("0x%02X", token.outer_string.str[i_byte]));
|
MD_PushStringToList(&bytes, MD_PushStringF("0x%02X", token.outer_string.str[i_byte]));
|
||||||
}
|
}
|
||||||
MD_String8 byte_string = MD_JoinStringList(bytes, MD_S8Lit(" "));
|
MD_String8 byte_string = MD_JoinStringList(bytes, MD_S8Lit(" "));
|
||||||
_MD_TokenError(ctx, token, MD_MessageKind_Error, "Non-ASCII character \"%.*s\"", MD_StringExpand(byte_string));
|
MD_PushTokenErrorF(ctx, token, MD_MessageKind_Error,
|
||||||
|
"Non-ASCII character \"%.*s\"", MD_StringExpand(byte_string));
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1948,8 +1975,8 @@ MD_ParseOneNodeFromCtx(MD_ParseCtx *ctx)
|
|||||||
if(!_MD_CommentIsSyntacticallyCorrect(comment_token))
|
if(!_MD_CommentIsSyntacticallyCorrect(comment_token))
|
||||||
{
|
{
|
||||||
MD_String8 capped = MD_StringPrefix(comment_token.outer_string, MD_UNTERMINATED_TOKEN_LEN_CAP);
|
MD_String8 capped = MD_StringPrefix(comment_token.outer_string, MD_UNTERMINATED_TOKEN_LEN_CAP);
|
||||||
_MD_TokenError(ctx, comment_token, MD_MessageKind_CatastrophicError,
|
MD_PushTokenErrorF(ctx, comment_token, MD_MessageKind_CatastrophicError,
|
||||||
"Unterminated comment \"%.*s\"", MD_StringExpand(capped));
|
"Unterminated comment \"%.*s\"", MD_StringExpand(capped));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2058,8 +2085,8 @@ MD_ParseWholeString(MD_String8 filename, MD_String8 contents)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
MD_Token token = MD_Parse_PeekSkipSome(&ctx, 0);
|
MD_Token token = MD_Parse_PeekSkipSome(&ctx, 0);
|
||||||
_MD_TokenError(&ctx, token, MD_MessageKind_Error, "Invalid hash directive \"%.*s\"",
|
MD_PushTokenErrorF(&ctx, token, MD_MessageKind_Error, "Invalid '#' directive \"%.*s\"",
|
||||||
MD_StringExpand(token.outer_string));
|
MD_StringExpand(token.outer_string));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2106,8 +2133,8 @@ MD_ParseWholeFile(MD_String8 filename)
|
|||||||
if(file_contents.str == 0)
|
if(file_contents.str == 0)
|
||||||
{
|
{
|
||||||
MD_ParseCtx ctx = MD_Parse_InitializeCtx(filename, MD_S8Lit(""));
|
MD_ParseCtx ctx = MD_Parse_InitializeCtx(filename, MD_S8Lit(""));
|
||||||
_MD_Error(&ctx, parse.node, MD_MessageKind_CatastrophicError, "Could not read file \"%.*s\"",
|
MD_PushNodeErrorF(&ctx, parse.node, MD_MessageKind_CatastrophicError,
|
||||||
MD_StringExpand(filename));
|
"Could not read file \"%.*s\"", MD_StringExpand(filename));
|
||||||
parse.first_error = ctx.first_error;
|
parse.first_error = ctx.first_error;
|
||||||
}
|
}
|
||||||
return parse;
|
return parse;
|
||||||
@@ -2404,8 +2431,13 @@ MD_SeekNodeWithFlags(MD_Node *start, MD_NodeFlags one_past_last_flags)
|
|||||||
MD_FUNCTION void
|
MD_FUNCTION void
|
||||||
MD_Message(FILE *out, MD_CodeLoc loc, MD_MessageKind kind, MD_String8 str)
|
MD_Message(FILE *out, MD_CodeLoc loc, MD_MessageKind kind, MD_String8 str)
|
||||||
{
|
{
|
||||||
const char *kind_name = ((kind == MD_MessageKind_Error) ? "error" : "warning");
|
const char *kind_name = "";
|
||||||
fprintf(out, "%.*s:%i:%i: %s: %.*s\n",
|
switch (kind){
|
||||||
|
case MD_MessageKind_Warning: kind_name = "warning: "; break;
|
||||||
|
case MD_MessageKind_Error: kind_name = "error: "; break;
|
||||||
|
case MD_MessageKind_CatastrophicError: kind_name = "fatal error: "; break;
|
||||||
|
}
|
||||||
|
fprintf(out, "%.*s:%i:%i: %s%.*s\n",
|
||||||
MD_StringExpand(loc.filename), loc.line, loc.column,
|
MD_StringExpand(loc.filename), loc.line, loc.column,
|
||||||
kind_name, MD_StringExpand(str));
|
kind_name, MD_StringExpand(str));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user