From 47613b5563ee135fdff2c2f53955d34f3c3ee048 Mon Sep 17 00:00:00 2001 From: Miguel Lechon Date: Sun, 24 Oct 2021 17:11:28 +0200 Subject: [PATCH] [expr parser] Communicate expression operator table bake errors through callback. --- source/md.c | 31 +++++++++----------- source/md.h | 3 +- tests/expression_tests.c | 61 ++++++++++++++++++++++++++-------------- 3 files changed, 56 insertions(+), 39 deletions(-) diff --git a/source/md.c b/source/md.c index f468573..f5b678e 100644 --- a/source/md.c +++ b/source/md.c @@ -2907,15 +2907,6 @@ MD_MakeNodeError(MD_Arena *arena, MD_Node *node, MD_MessageKind kind, MD_String8 return error; } -MD_FUNCTION MD_Message* -MD_MakeDetachedError(MD_Arena *arena, MD_MessageKind kind, MD_String8 str, void *user_ptr) -{ - MD_Node *err_node = MD_MakeErrorMarkerNode(arena, MD_S8Lit(""), 0); - MD_Message *result = MD_MakeNodeError(arena, err_node, kind, str); - result->user_ptr = user_ptr; - return(result); -} - MD_FUNCTION MD_Message * MD_MakeTokenError(MD_Arena *arena, MD_String8 parse_contents, MD_Token token, MD_MessageKind kind, MD_String8 str) @@ -3400,6 +3391,15 @@ MD_ExprOprPush(MD_Arena *arena, MD_ExprOprList *list, op->op_ptr = op_ptr; } +MD_GLOBAL MD_BakeOperatorErrorHandler md_bake_operator_error_handler = 0; + +MD_FUNCTION MD_BakeOperatorErrorHandler +MD_ExprSetBakeOperatorErrorHandler(MD_BakeOperatorErrorHandler handler){ + MD_BakeOperatorErrorHandler old_handler = md_bake_operator_error_handler; + md_bake_operator_error_handler = handler; + return old_handler; +} + MD_FUNCTION MD_ExprOprTable MD_ExprBakeOperatorTableFromList(MD_Arena *arena, MD_ExprOprList *list) { @@ -3427,7 +3427,8 @@ MD_ExprBakeOperatorTableFromList(MD_Arena *arena, MD_ExprOprList *list) if(op_kind != MD_ExprOprKind_Prefix && op_kind != MD_ExprOprKind_Postfix && op_kind != MD_ExprOprKind_Binary && op_kind != MD_ExprOprKind_BinaryRightAssociative) { - error_str = MD_S8Fmt(arena, "Invalid operator kind."); + error_str = MD_S8Fmt(arena, "Ignored operator \"%.*s\" because its kind value (%d) does not match " + "any valid operator kind", MD_S8VArg(op_s), op_kind); } else if(is_setlike_op && op_kind != MD_ExprOprKind_Postfix) { @@ -3469,7 +3470,7 @@ MD_ExprBakeOperatorTableFromList(MD_Arena *arena, MD_ExprOprList *list) { if(op_kind == op2_kind) { - error_str = MD_S8Fmt(arena, "Ignored repeat operator \"%.*s\".", MD_S8VArg(op_s)); + error_str = MD_S8Fmt(arena, "Ignored repeat operator \"%.*s\"", MD_S8VArg(op_s)); } else if(op_kind != MD_ExprOprKind_Prefix && op2_kind != MD_ExprOprKind_Prefix) { @@ -3483,13 +3484,9 @@ MD_ExprBakeOperatorTableFromList(MD_Arena *arena, MD_ExprOprList *list) } // save error - if(error_str.size != 0) + if(error_str.size != 0 && md_bake_operator_error_handler) { - // TODO(allen): review: does it make sense to use these kinds of errors - // for *this* which isn't derived from metadesk at all? - MD_Message *error = MD_MakeDetachedError(arena, MD_MessageKind_Warning, - error_str, op->op_ptr); - MD_MessageListPush(&result.errors, error); + md_bake_operator_error_handler(MD_MessageKind_Warning, error_str); } // save list diff --git a/source/md.h b/source/md.h index f2afa8b..b8428a9 100644 --- a/source/md.h +++ b/source/md.h @@ -790,7 +790,6 @@ struct MD_ExprOprTable { // TODO(mal): @upgrade_potential Hash? MD_ExprOprList table[MD_ExprOprKind_COUNT]; - MD_MessageList errors; }; typedef struct MD_Expr MD_Expr; @@ -833,6 +832,8 @@ struct MD_ExprParseCtx MD_MessageList errors; }; +typedef void (*MD_BakeOperatorErrorHandler)(MD_MessageKind kind, MD_String8 s); + //~ String Generation Types typedef MD_u32 MD_GenerateFlags; diff --git a/tests/expression_tests.c b/tests/expression_tests.c index b20bda2..b691cd1 100644 --- a/tests/expression_tests.c +++ b/tests/expression_tests.c @@ -223,6 +223,23 @@ static MD_String8 parenthesize(MD_Arena *arena, OperatorDescription *descs, MD_E return result; } +static MD_MessageList global_message_list = {0}; +static MD_MessageKind global_max_message_kind = MD_MessageKind_Null; +static void reset_global_messages() +{ + global_message_list = (MD_MessageList){0}; + global_max_message_kind = MD_MessageKind_Null; +} +static void bake_operator_error_handler(MD_MessageKind kind, MD_String8 s) +{ + // NOTE: Append error to global error list + MD_Message *message = MD_PushArrayZero(arena, MD_Message, 1); + message->kind = kind; + message->string = s; + MD_MessageListPush(&global_message_list, message); + global_max_message_kind = global_max_message_kind >= kind ? global_max_message_kind: kind; +} + int main(void) { OperatorDescription operator_array[Op_COUNT] = {0}; @@ -246,75 +263,77 @@ operator_array[Op_##name].op = (MD_ExprOpr){ .op_id = Op_##name, .kind = MD_Expr MD_Node *cast_node = MD_MakeNode(arena, MD_NodeKind_Main, cast, cast, 0); MD_Node *minus_node = MD_MakeNode(arena, MD_NodeKind_Main, minus, minus, 0); MD_Node *plus_node_bis = MD_MakeNode(arena, MD_NodeKind_Main, plus, plus, 0); + + MD_ExprSetBakeOperatorErrorHandler(bake_operator_error_handler); // NOTE: Wrong operator kind + reset_global_messages(); operator_list = (MD_ExprOprList){0}; MD_ExprOprPush(arena, &operator_list, MD_ExprOprKind_Null, 1, MD_S8Lit("+"), Op_Addition, plus_node); op_table = MD_ExprBakeOperatorTableFromList(arena, &operator_list); - MD_Assert(op_table.errors.max_message_kind == MD_MessageKind_Warning && - op_table.errors.node_count == 1 && - op_table.errors.first->user_ptr == plus_node); + MD_Assert(global_max_message_kind == MD_MessageKind_Warning && + global_message_list.node_count == 1); // NOTE: () not as unary postfix operator_list = (MD_ExprOprList){0}; + reset_global_messages(); MD_ExprOprPush(arena, &operator_list, MD_ExprOprKind_Prefix, 1, MD_S8Lit("()"), 23 /* arbitrary MD_ExprOprKind */, cast_node); op_table = MD_ExprBakeOperatorTableFromList(arena, &operator_list); - MD_Assert(op_table.errors.max_message_kind == MD_MessageKind_Warning && - op_table.errors.node_count == 1 && - op_table.errors.first->user_ptr == cast_node); + MD_Assert(global_max_message_kind == MD_MessageKind_Warning && + global_message_list.node_count == 1); // NOTE: Repeat operator operator_list = (MD_ExprOprList){0}; + reset_global_messages(); MD_ExprOprPush(arena, &operator_list, MD_ExprOprKind_Binary, 1, MD_S8Lit("+"), Op_Addition, plus_node); MD_ExprOprPush(arena, &operator_list, MD_ExprOprKind_Binary, 1, MD_S8Lit("+"), Op_Addition, plus_node_bis); op_table = MD_ExprBakeOperatorTableFromList(arena, &operator_list); - MD_Assert(op_table.errors.max_message_kind == MD_MessageKind_Warning && - op_table.errors.node_count == 1 && - op_table.errors.first->user_ptr == plus_node_bis); + MD_Assert(global_max_message_kind == MD_MessageKind_Warning && + global_message_list.node_count == 1); operator_list = (MD_ExprOprList){0}; + reset_global_messages(); // NOTE: Binary-postfix operator conflict MD_ExprOprPush(arena, &operator_list, MD_ExprOprKind_Binary, 1, MD_S8Lit("+"), Op_Addition, plus_node); MD_ExprOprPush(arena, &operator_list, MD_ExprOprKind_Postfix, 1, MD_S8Lit("+"), Op_Addition, plus_node_bis); op_table = MD_ExprBakeOperatorTableFromList(arena, &operator_list); - MD_Assert(op_table.errors.max_message_kind == MD_MessageKind_Warning - && op_table.errors.node_count == 1 && - op_table.errors.first->user_ptr == plus_node_bis); + MD_Assert(global_max_message_kind == MD_MessageKind_Warning + && global_message_list.node_count == 1); operator_list = (MD_ExprOprList){0}; + reset_global_messages(); // NOTE: Same precedence difference associativity conflict MD_ExprOprPush(arena, &operator_list, MD_ExprOprKind_Binary, 1, MD_S8Lit("+"), Op_Addition, plus_node); MD_ExprOprPush(arena, &operator_list, MD_ExprOprKind_BinaryRightAssociative, 1, MD_S8Lit("-"), Op_Addition, minus_node); op_table = MD_ExprBakeOperatorTableFromList(arena, &operator_list); - MD_Assert(op_table.errors.max_message_kind == MD_MessageKind_Warning && - op_table.errors.node_count == 1 && - op_table.errors.first->user_ptr == minus_node); + MD_Assert(global_max_message_kind == MD_MessageKind_Warning && + global_message_list.node_count == 1); // NOTE: Multitoken operator + reset_global_messages(); operator_list = (MD_ExprOprList){0}; MD_ExprOprPush(arena, &operator_list, MD_ExprOprKind_Prefix, 1, MD_S8Lit("+ +"), 23 /* arbitrary MD_ExprOprKind */, plus_node); op_table = MD_ExprBakeOperatorTableFromList(arena, &operator_list); - MD_Assert(op_table.errors.max_message_kind == MD_MessageKind_Warning && - op_table.errors.node_count == 1 && - op_table.errors.first->user_ptr == plus_node); + MD_Assert(global_max_message_kind == MD_MessageKind_Warning && + global_message_list.node_count == 1); // NOTE: Wrong token kind operator + reset_global_messages(); operator_list = (MD_ExprOprList){0}; MD_ExprOprPush(arena, &operator_list, MD_ExprOprKind_Prefix, 1, MD_S8Lit("123"), 23 /* arbitrary MD_ExprOprKind */, plus_node); op_table = MD_ExprBakeOperatorTableFromList(arena, &operator_list); - MD_Assert(op_table.errors.max_message_kind == MD_MessageKind_Warning && - op_table.errors.node_count == 1 && - op_table.errors.first->user_ptr == plus_node); + MD_Assert(global_max_message_kind == MD_MessageKind_Warning && + global_message_list.node_count == 1); } MD_ExprOprList operator_list = {0};