[expr parser] Communicate expression operator table bake errors through callback.

This commit is contained in:
Miguel Lechon
2021-10-24 17:11:28 +02:00
parent 8ec2e23a1d
commit 47613b5563
3 changed files with 56 additions and 39 deletions
+14 -17
View File
@@ -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
+2 -1
View File
@@ -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;
+40 -21
View File
@@ -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};