diff --git a/source/md.c b/source/md.c index 78a2d6e..5630ec0 100644 --- a/source/md.c +++ b/source/md.c @@ -3378,15 +3378,13 @@ MD_ExprBakeOperatorTableFromList(MD_Arena *arena, MD_ExprOprList *list) 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) || MD_S8Match(op_s, MD_S8Lit("(]"), 0) || + MD_S8Match(op_s, MD_S8Lit("{}"), 0))){ 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(MD_S8Match(op_s, MD_S8Lit("[)"), 0) || MD_S8Match(op_s, MD_S8Lit("(]"), 0) || - MD_S8Match(op_s, MD_S8Lit("{}"), 0)){ - error_str = MD_S8Fmt(arena, "Ignored forbidden operator \"%.*s\".", MD_S8VArg(op_s)); - } else { for(MD_ExprOpr *op2 = list->first; @@ -3529,9 +3527,21 @@ MD_ExprParse_MakeContext(MD_ExprOprTable *op_table) { MD_ExprParseCtx result = MD_ZERO_STRUCT; result.op_table = op_table; - - result.accel.call_op = MD_ExprOprFromKindString(op_table, MD_ExprOprKind_Postfix, MD_S8Lit("()")); - result.accel.subscript_op = MD_ExprOprFromKindString(op_table, MD_ExprOprKind_Binary, MD_S8Lit("[]")); + + result.accel.postfix_set_ops[0] = MD_ExprOprFromKindString(op_table, MD_ExprOprKind_Postfix, MD_S8Lit("()")); + result.accel.postfix_set_flags[0] = MD_NodeFlag_HasParenLeft | MD_NodeFlag_HasParenRight; + + result.accel.postfix_set_ops[1] = MD_ExprOprFromKindString(op_table, MD_ExprOprKind_Postfix, MD_S8Lit("[]")); + result.accel.postfix_set_flags[1] = MD_NodeFlag_HasBracketLeft | MD_NodeFlag_HasBracketRight; + + result.accel.postfix_set_ops[2] = MD_ExprOprFromKindString(op_table, MD_ExprOprKind_Postfix, MD_S8Lit("{}")); + result.accel.postfix_set_flags[2] = MD_NodeFlag_HasBraceLeft | MD_NodeFlag_HasBraceRight; + + result.accel.postfix_set_ops[3] = MD_ExprOprFromKindString(op_table, MD_ExprOprKind_Postfix, MD_S8Lit("[)")); + result.accel.postfix_set_flags[3] = MD_NodeFlag_HasBracketLeft | MD_NodeFlag_HasParenRight; + + result.accel.postfix_set_ops[4] = MD_ExprOprFromKindString(op_table, MD_ExprOprKind_Postfix, MD_S8Lit("(]")); + result.accel.postfix_set_flags[4] = MD_NodeFlag_HasParenLeft | MD_NodeFlag_HasBracketRight; return(result); } @@ -3661,8 +3671,6 @@ MD_ExprParse_MinPrecedence(MD_Arena *arena, MD_ExprParseCtx *ctx, // TODO(allen): nil MD_Expr* result = 0; - MD_ExprOpr *subscript_op = ctx->accel.subscript_op; - result = MD_ExprParse_Atom(arena, ctx, iter, first, opl); if(ctx->errors.max_message_kind == MD_MessageKind_Null) { @@ -3687,39 +3695,40 @@ MD_ExprParse_MinPrecedence(MD_Arena *arena, MD_ExprParseCtx *ctx, break; } } - - else if(subscript_op != 0 && subscript_op->precedence >= min_precedence && - (node->flags & MD_NodeFlag_HasBracketLeft) && - (node->flags & MD_NodeFlag_HasBracketRight)) - { - *iter = MD_NodeNextWithLimit(*iter, opl); - // NOTE(mal): Array subscript - MD_Expr* sub_expr = MD_ExprParse_TopLevel(arena, ctx, node->first_child, MD_NilNode()); - if(ctx->errors.max_message_kind == MD_MessageKind_Null) - { - result = MD_Expr_NewOp(arena, subscript_op, node, result, sub_expr); - } - else{ - break; - } - } - - else if(ctx->accel.call_op && ctx->accel.call_op->precedence >= min_precedence && - (node->flags & MD_NodeFlag_HasParenLeft) && - (node->flags & MD_NodeFlag_HasParenRight)) - { // NOTE: call - *iter = MD_NodeNextWithLimit(*iter, opl); - result = MD_Expr_NewOp(arena, ctx->accel.call_op, node, result, 0); - } - else if(MD_ExprParse_OprConsume(ctx, iter, opl, MD_ExprOprKind_Postfix, - min_precedence, &op)) - { - result = MD_Expr_NewOp(arena, op, node, result, 0); - } + else { - break; // NOTE: Due to lack of progress + MD_b32 found_postfix_setlike_operator = 0; + for(MD_u32 i_op = 0; + i_op < MD_ArrayCount(ctx->accel.postfix_set_ops); + ++i_op) + { + MD_ExprOpr *op = ctx->accel.postfix_set_ops[i_op]; + if(op && op->precedence >= min_precedence && + node->flags == ctx->accel.postfix_set_flags[i_op]) + { + *iter = MD_NodeNextWithLimit(*iter, opl); + result = MD_Expr_NewOp(arena, op, node, result, 0); + found_postfix_setlike_operator = 1; + break; + } + } + + if(!found_postfix_setlike_operator) + { + if(MD_ExprParse_OprConsume(ctx, iter, opl, MD_ExprOprKind_Postfix, + min_precedence, &op)) + { + result = MD_Expr_NewOp(arena, op, node, result, 0); + } + else + { + break; // NOTE: Due to lack of progress + } + } + } + } } diff --git a/source/md.h b/source/md.h index acc6b9a..35e0661 100644 --- a/source/md.h +++ b/source/md.h @@ -780,12 +780,14 @@ typedef struct MD_ExprParseCtx MD_ExprParseCtx; struct MD_ExprParseCtx { MD_ExprOprTable *op_table; - + +#define MD_POSTFIX_SETLIKE_OP_COUNT 5 // (), [], {}, [), (] struct { - MD_ExprOpr *call_op; - MD_ExprOpr *subscript_op; + MD_ExprOpr *postfix_set_ops[MD_POSTFIX_SETLIKE_OP_COUNT]; + MD_NodeFlags postfix_set_flags[MD_POSTFIX_SETLIKE_OP_COUNT]; } accel; +#undef MD_POSTFIX_SETLIKE_OP_COUNT MD_MessageList errors; }; diff --git a/tests/expression_tests.c b/tests/expression_tests.c index 976942c..ec5fa41 100644 --- a/tests/expression_tests.c +++ b/tests/expression_tests.c @@ -32,7 +32,7 @@ struct OperatorDescription{ X(PostFixIncrement, "++", Postfix, 18) \ X(PostFixDecrement, "--", Postfix, 18) \ X(Call, "()", Postfix, 18) \ -X(ArraySubscript, "[]", Binary, 18) \ +X(ArraySubscript, "[]", Postfix, 18) \ X(Member, ".", Binary, 18) \ X(PointerMember, "->", Binary, 18) \ X(PreFixIncrement, "++", Prefix, 17) \ @@ -43,7 +43,7 @@ X(LogicalNot, "!", Prefix, 17) \ X(BitwiseNot, "~", Prefix, 17) \ X(Dereference, "*", Prefix, 17) \ X(AddressOf, "&", Prefix, 17) \ -X(SizeOf, "sizeof", Prefix, 17) /* NOTE(mal); Just for fun*/ \ +X(SizeOf, "sizeof", Prefix, 17) /* NOTE(mal); Just for fun */ \ X(Multiplication, "*", Binary, 15) \ X(Division, "/", Binary, 15) \ X(Modulo, "%", Binary, 15) \ @@ -72,7 +72,11 @@ X(AssignLeftShift, "<<=", BinaryRightAssociative, 4) \ X(AssignRightShift, ">>=", BinaryRightAssociative, 4) \ X(AssignBitwiseAnd, "&=", BinaryRightAssociative, 4) \ X(AssignBitwiseXor, "^=", BinaryRightAssociative, 4) \ -X(AssignBitwiseOr, "|=", BinaryRightAssociative, 4) +X(AssignBitwiseOr, "|=", BinaryRightAssociative, 4) \ +/* NOTE(mal): These are not in C */ \ +X(PostfixBraceBrace, "{}", Postfix, 18) \ +X(PostfixBracketParen, "[)", Postfix, 18) \ +X(PostfixParenBracket, "(]", Postfix, 18) \ // TODO(allen): I don't think we want to do this // X(Cast "()", Prefix, 17) @@ -82,7 +86,7 @@ X(AssignBitwiseOr, "|=", BinaryRightAssociative, 4) typedef enum{ Op_Null, OPERATORS - Op_COUNT + Op_COUNT } Op; #undef X @@ -129,23 +133,11 @@ static void parenthesize_exclude_outer(MD_Arena *arena, OperatorDescription *des MD_ExprOpr *op = &descs[node->op_id].op; if(op->kind == MD_ExprOprKind_Binary || op->kind == MD_ExprOprKind_BinaryRightAssociative) { - parenthesize_exclude_outer(arena, descs, l, node->left, 0); - - MD_b32 is_subscript = (node->op_id == Op_ArraySubscript); - if(is_subscript) - { - MD_S8ListPush(arena, l, MD_S8Lit("[")); - parenthesize_exclude_outer(arena, descs, l, node->right, 1); - MD_S8ListPush(arena, l, MD_S8Lit("]")); - } - else - { - MD_S8ListPush(arena, l, MD_S8Lit(" ")); - MD_S8ListPush(arena, l, node->md_node->string); - MD_S8ListPush(arena, l, MD_S8Lit(" ")); - parenthesize_exclude_outer(arena, descs, l, node->right, 0); - } + MD_S8ListPush(arena, l, MD_S8Lit(" ")); + MD_S8ListPush(arena, l, node->md_node->string); + MD_S8ListPush(arena, l, MD_S8Lit(" ")); + parenthesize_exclude_outer(arena, descs, l, node->right, 0); } else if(op->kind == MD_ExprOprKind_Prefix) { @@ -162,11 +154,15 @@ static void parenthesize_exclude_outer(MD_Arena *arena, OperatorDescription *des else if(op->kind == MD_ExprOprKind_Postfix) { parenthesize_exclude_outer(arena, descs, l, node->left, 0); - - MD_b32 is_call = (node->op_id == Op_Call); - if(is_call) + + MD_String8 op_s = descs[op->op_id].s; + if(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)) { - MD_S8ListPush(arena, l, MD_S8Lit("(...)")); + MD_S8ListPush(arena, l, MD_S8Substring(op_s, 0, 1)); + MD_S8ListPush(arena, l, MD_S8Lit("...")); + MD_S8ListPush(arena, l, MD_S8Substring(op_s, 1, 2)); } else { @@ -337,8 +333,9 @@ operator_array[Op_##name].op = (MD_ExprOpr){ .op_id = Op_##name, .kind = MD_Expr { .q = "a.b()", .a = "(a . b)(...)" }, { .q = "sizeof a + b", .a = "(sizeof a) + b" }, { .q = "[1, 100] * [1)",.a = "[...] * [...)" }, - { .q = "a[b+c]", .a = "a[b + c]" }, - { .q = "a + b[c[d]+e]", .a = "a + (b[(c[d]) + e])" }, + { .q = "a[b+c]", .a = "a[...]" }, + { .q = "a[a+]", .a = "a[...]", }, // NOTE(mal): No error because "a+" remains unparsed + { .q = "a + b[c[d]+e]", .a = "a + (b[...])" }, { .q = "a++ + b", .a = "(a++) + b" }, { .q = "a.b(c)", .a = "(a . b)(...)" }, { .q = "a*b.x+c", .a = "(a * (b . x)) + c" }, @@ -358,7 +355,7 @@ operator_array[Op_##name].op = (MD_ExprOpr){ .op_id = Op_##name, .kind = MD_Expr { .q = "* + +a", .a = "*(+(+a))" }, { .q = "+ + *a", .a = "+(+(*a))" }, { .q = "!a", .a = "!a" }, - { .q = "*f()[10]", .a = "*((f(...))[10])" }, + { .q = "*f()[10]", .a = "*((f(...))[...])" }, { .q = "a >> b << c", .a = "(a >> b) << c" }, { .q = "a < b <= c", .a = "(a < b) <= c" }, @@ -368,7 +365,9 @@ operator_array[Op_##name].op = (MD_ExprOpr){ .op_id = Op_##name, .kind = MD_Expr { .q = "a & &b", .a = "a & (&b)" }, { .q = "\"a\" + b + c", .a = "(\"a\" + b) + c" }, - + { .q = "a{b+c}", .a = "a{...}" }, // NOTE(mal): Non-standard postfix set-like operators + { .q = "a[b+c)", .a = "a[...)" }, + { .q = "(a", .a = "", ExpressionErrorKind_MD, 0}, { .q = "a)", .a = "", ExpressionErrorKind_MD, 1}, { .q = "/a", .a = "", ExpressionErrorKind_Expr, 0}, @@ -376,8 +375,6 @@ operator_array[Op_##name].op = (MD_ExprOpr){ .op_id = Op_##name, .kind = MD_Expr { .q = "a+", .a = "", ExpressionErrorKind_Expr, 2}, { .q = "a 1", .a = "", ExpressionErrorKind_Expr, 2}, { .q = "a + (a+)", .a = "", ExpressionErrorKind_Expr, 7}, - // TODO(mal): This test should not generate an error when [] is postfix and a+ remains unparsed - { .q = "a[a+]", .a = "", ExpressionErrorKind_Expr, 4}, }; for(MD_u32 i_test = 0; i_test < MD_ArrayCount(tests); i_test+=1)