diff --git a/source/md.c b/source/md.c index 5630ec0..19f25b2 100644 --- a/source/md.c +++ b/source/md.c @@ -3372,19 +3372,37 @@ MD_ExprBakeOperatorTableFromList(MD_Arena *arena, MD_ExprOprList *list) // error checking MD_String8 error_str = MD_ZERO_STRUCT; + + MD_Token op_token = MD_TokenFromString(op_s); + MD_b32 is_setlike_op = + (op_s.size == 2 && + (MD_S8Match(op_s, MD_S8Lit("[]"), 0) || MD_S8Match(op_s, MD_S8Lit("()"), 0) || + MD_S8Match(op_s, MD_S8Lit("[)"), 0) || MD_S8Match(op_s, MD_S8Lit("(]"), 0) || + MD_S8Match(op_s, MD_S8Lit("{}"), 0))); + 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."); } - else if(op_kind != MD_ExprOprKind_Postfix && - (MD_S8Match(op_s, MD_S8Lit("[]"), 0) || MD_S8Match(op_s, MD_S8Lit("()"), 0) || - MD_S8Match(op_s, MD_S8Lit("[)"), 0) || MD_S8Match(op_s, MD_S8Lit("(]"), 0) || - MD_S8Match(op_s, MD_S8Lit("{}"), 0))){ + else if(is_setlike_op && op_kind != MD_ExprOprKind_Postfix) + { error_str = MD_S8Fmt(arena, "Ignored operator \"%.*s\". \"%.*s\" is only allowed as unary postfix", MD_S8VArg(op_s), MD_S8VArg(op_s)); } + else if(!is_setlike_op && + (op_token.kind != MD_TokenKind_Identifier && op_token.kind != MD_TokenKind_Symbol)) + { + error_str = MD_S8Fmt(arena, "Ignored operator \"%.*s\" because it is neither a symbol " + "nor an identifier token", MD_S8VArg(op_s)); + } + else if(!is_setlike_op && op_token.string.size < op_s.size) + { + error_str = MD_S8Fmt(arena, "Ignored operator \"%.*s\" because its prefix \"%.*s\" " + "constitutes a standalone operator", + MD_S8VArg(op_s), MD_S8VArg(op_token.string)); + } else { for(MD_ExprOpr *op2 = list->first; diff --git a/tests/expression_tests.c b/tests/expression_tests.c index ec5fa41..7878d57 100644 --- a/tests/expression_tests.c +++ b/tests/expression_tests.c @@ -300,6 +300,23 @@ operator_array[Op_##name].op = (MD_ExprOpr){ .op_id = Op_##name, .kind = MD_Expr op_table.errors.node_count == 1 && op_table.errors.first->user_ptr == minus_node); + // NOTE: Multitoken operator + 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); + + // NOTE: Wrong token kind operator + 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_ExprOprList operator_list = {0};