| ... | ... | @@ -1000,24 +1000,58 @@ pub const Parser = struct { |
| 1000 | 1000 | |
| 1001 | 1001 | var expression = popSuffixOp(&stack); |
| 1002 | 1002 | while (true) { |
| 1003 | | switch (stack.pop()) { |
| 1004 | | State.Expression => |dest_ptr| { |
| 1005 | | // we're done |
| 1006 | | try dest_ptr.store(expression); |
| 1003 | const s = stack.pop(); |
| 1004 | if (s == State.Expression) { |
| 1005 | const dest_ptr = s.Expression; |
| 1006 | // we're done |
| 1007 | try dest_ptr.store(expression); |
| 1008 | break; |
| 1009 | } |
| 1010 | |
| 1011 | var placement_ptr = &expression; |
| 1012 | var rhs : &&ast.Node = undefined; |
| 1013 | const node = blk: { |
| 1014 | switch (s) { |
| 1015 | State.InfixOp => |infix_op| { |
| 1016 | infix_op.lhs = popSuffixOp(&stack); |
| 1017 | infix_op.rhs = expression; |
| 1018 | rhs = &infix_op.rhs; |
| 1019 | break :blk &infix_op.base; |
| 1020 | }, |
| 1021 | State.PrefixOp => |prefix_op| { |
| 1022 | prefix_op.rhs = expression; |
| 1023 | rhs = &prefix_op.rhs; |
| 1024 | break :blk &prefix_op.base; |
| 1025 | }, |
| 1026 | else => unreachable, |
| 1027 | } |
| 1028 | }; |
| 1029 | const node_perc = precedence(node); |
| 1030 | |
| 1031 | while (true) { |
| 1032 | const perc = precedence(*placement_ptr); |
| 1033 | |
| 1034 | if (node_perc > perc) { |
| 1035 | *placement_ptr = node; |
| 1007 | 1036 | break; |
| 1008 | | }, |
| 1009 | | State.InfixOp => |infix_op| { |
| 1010 | | infix_op.rhs = expression; |
| 1011 | | infix_op.lhs = popSuffixOp(&stack); |
| 1012 | | expression = &infix_op.base; |
| 1013 | | continue; |
| 1014 | | }, |
| 1015 | | State.PrefixOp => |prefix_op| { |
| 1016 | | prefix_op.rhs = expression; |
| 1017 | | expression = &prefix_op.base; |
| 1018 | | continue; |
| 1019 | | }, |
| 1020 | | else => unreachable, |
| 1037 | } |
| 1038 | |
| 1039 | switch ((*placement_ptr).id) { |
| 1040 | ast.Node.Id.SuffixOp => { |
| 1041 | const suffix_op = @fieldParentPtr(ast.NodeSuffixOp, "base", *placement_ptr); |
| 1042 | placement_ptr = &suffix_op.lhs; |
| 1043 | *rhs = suffix_op.lhs; |
| 1044 | }, |
| 1045 | ast.Node.Id.InfixOp => { |
| 1046 | const infix_op = @fieldParentPtr(ast.NodeInfixOp, "base", *placement_ptr); |
| 1047 | placement_ptr = &infix_op.lhs; |
| 1048 | *rhs = infix_op.lhs; |
| 1049 | }, |
| 1050 | else => { |
| 1051 | *placement_ptr = node; |
| 1052 | break; |
| 1053 | }, |
| 1054 | } |
| 1021 | 1055 | } |
| 1022 | 1056 | } |
| 1023 | 1057 | continue; |
| ... | ... | @@ -1308,6 +1342,99 @@ pub const Parser = struct { |
| 1308 | 1342 | } |
| 1309 | 1343 | } |
| 1310 | 1344 | |
| 1345 | fn precedence(node: &ast.Node) u8 { |
| 1346 | switch (node.id) { |
| 1347 | ast.Node.Id.PrefixOp => { |
| 1348 | const prefix_op = @fieldParentPtr(ast.NodePrefixOp, "base", node); |
| 1349 | switch (prefix_op.op) { |
| 1350 | ast.NodePrefixOp.PrefixOp.ArrayType, |
| 1351 | ast.NodePrefixOp.PrefixOp.SliceType => return 1, |
| 1352 | |
| 1353 | ast.NodePrefixOp.PrefixOp.BoolNot, |
| 1354 | ast.NodePrefixOp.PrefixOp.Negation, |
| 1355 | ast.NodePrefixOp.PrefixOp.NegationWrap, |
| 1356 | ast.NodePrefixOp.PrefixOp.BitNot, |
| 1357 | ast.NodePrefixOp.PrefixOp.Deref, |
| 1358 | ast.NodePrefixOp.PrefixOp.AddrOf, |
| 1359 | ast.NodePrefixOp.PrefixOp.UnwrapMaybe => return 3, |
| 1360 | |
| 1361 | ast.NodePrefixOp.PrefixOp.Try, |
| 1362 | ast.NodePrefixOp.PrefixOp.Return => return 255, |
| 1363 | } |
| 1364 | }, |
| 1365 | ast.Node.Id.SuffixOp => { |
| 1366 | const suffix_op = @fieldParentPtr(ast.NodeSuffixOp, "base", node); |
| 1367 | switch (suffix_op.op) { |
| 1368 | ast.NodeSuffixOp.SuffixOp.Call, |
| 1369 | ast.NodeSuffixOp.SuffixOp.Slice, |
| 1370 | ast.NodeSuffixOp.SuffixOp.ArrayAccess => return 2, |
| 1371 | |
| 1372 | ast.NodeSuffixOp.SuffixOp.ArrayInitializer, |
| 1373 | ast.NodeSuffixOp.SuffixOp.StructInitializer => return 5, |
| 1374 | } |
| 1375 | }, |
| 1376 | ast.Node.Id.InfixOp => { |
| 1377 | const infix_op = @fieldParentPtr(ast.NodeInfixOp, "base", node); |
| 1378 | switch (infix_op.op) { |
| 1379 | ast.NodeInfixOp.InfixOp.Period => return 2, |
| 1380 | |
| 1381 | ast.NodeInfixOp.InfixOp.ErrorUnion => return 4, |
| 1382 | |
| 1383 | ast.NodeInfixOp.InfixOp.Div, |
| 1384 | ast.NodeInfixOp.InfixOp.ArrayMult, |
| 1385 | ast.NodeInfixOp.InfixOp.Mod, |
| 1386 | ast.NodeInfixOp.InfixOp.Mult, |
| 1387 | ast.NodeInfixOp.InfixOp.MultWrap => return 6, |
| 1388 | |
| 1389 | ast.NodeInfixOp.InfixOp.Add, |
| 1390 | ast.NodeInfixOp.InfixOp.AddWrap, |
| 1391 | ast.NodeInfixOp.InfixOp.ArrayCat, |
| 1392 | ast.NodeInfixOp.InfixOp.Sub, |
| 1393 | ast.NodeInfixOp.InfixOp.SubWrap => return 7, |
| 1394 | |
| 1395 | ast.NodeInfixOp.InfixOp.BitShiftLeft, |
| 1396 | ast.NodeInfixOp.InfixOp.BitShiftRight => return 8, |
| 1397 | |
| 1398 | ast.NodeInfixOp.InfixOp.BitAnd => return 9, |
| 1399 | |
| 1400 | ast.NodeInfixOp.InfixOp.BitXor => return 10, |
| 1401 | |
| 1402 | ast.NodeInfixOp.InfixOp.BitOr => return 11, |
| 1403 | |
| 1404 | ast.NodeInfixOp.InfixOp.EqualEqual, |
| 1405 | ast.NodeInfixOp.InfixOp.BangEqual, |
| 1406 | ast.NodeInfixOp.InfixOp.GreaterOrEqual, |
| 1407 | ast.NodeInfixOp.InfixOp.GreaterThan, |
| 1408 | ast.NodeInfixOp.InfixOp.LessOrEqual, |
| 1409 | ast.NodeInfixOp.InfixOp.LessThan => return 12, |
| 1410 | |
| 1411 | ast.NodeInfixOp.InfixOp.BoolAnd => return 13, |
| 1412 | |
| 1413 | ast.NodeInfixOp.InfixOp.BoolOr => return 14, |
| 1414 | |
| 1415 | ast.NodeInfixOp.InfixOp.UnwrapMaybe => return 15, |
| 1416 | |
| 1417 | ast.NodeInfixOp.InfixOp.Assign, |
| 1418 | ast.NodeInfixOp.InfixOp.AssignBitAnd, |
| 1419 | ast.NodeInfixOp.InfixOp.AssignBitOr, |
| 1420 | ast.NodeInfixOp.InfixOp.AssignBitShiftLeft, |
| 1421 | ast.NodeInfixOp.InfixOp.AssignBitShiftRight, |
| 1422 | ast.NodeInfixOp.InfixOp.AssignBitXor, |
| 1423 | ast.NodeInfixOp.InfixOp.AssignDiv, |
| 1424 | ast.NodeInfixOp.InfixOp.AssignMinus, |
| 1425 | ast.NodeInfixOp.InfixOp.AssignMinusWrap, |
| 1426 | ast.NodeInfixOp.InfixOp.AssignMod, |
| 1427 | ast.NodeInfixOp.InfixOp.AssignPlus, |
| 1428 | ast.NodeInfixOp.InfixOp.AssignPlusWrap, |
| 1429 | ast.NodeInfixOp.InfixOp.AssignTimes, |
| 1430 | ast.NodeInfixOp.InfixOp.AssignTimesWarp, |
| 1431 | ast.NodeInfixOp.InfixOp.MergeErrorSets => return 16, |
| 1432 | } |
| 1433 | }, |
| 1434 | else => return 0, |
| 1435 | } |
| 1436 | } |
| 1437 | |
| 1311 | 1438 | fn commaOrEnd(self: &Parser, stack: &ArrayList(State), end: &const Token.Id, ptr: &Token, state_after_comma: &const State) !void { |
| 1312 | 1439 | var token = self.getNextToken(); |
| 1313 | 1440 | switch (token.id) { |
| ... | ... | @@ -2549,6 +2676,39 @@ test "zig fmt: infix operators" { |
| 2549 | 2676 | ); |
| 2550 | 2677 | } |
| 2551 | 2678 | |
| 2679 | test "zig fmt: precedence" { |
| 2680 | try testCanonical( |
| 2681 | \\test "precedence" { |
| 2682 | \\ a!b(); |
| 2683 | \\ (a!b)(); |
| 2684 | \\ !a!b; |
| 2685 | \\ !(a!b); |
| 2686 | \\ a << b + c; |
| 2687 | \\ (a << b) + c; |
| 2688 | \\ a & b << c; |
| 2689 | \\ (a & b) << c; |
| 2690 | \\ a ^ b & c; |
| 2691 | \\ (a ^ b) & c; |
| 2692 | \\ a | b ^ c; |
| 2693 | \\ (a | b) ^ c; |
| 2694 | \\ a == b | c; |
| 2695 | \\ (a == b) | c; |
| 2696 | \\ a and b == c; |
| 2697 | \\ (a and b) == c; |
| 2698 | \\ a or b and c; |
| 2699 | \\ (a or b) and c; |
| 2700 | \\ (a or b) and c; |
| 2701 | \\ a = b or c; |
| 2702 | \\ (a = b) or c; |
| 2703 | \\} |
| 2704 | \\ |
| 2705 | //\\ !a{}; |
| 2706 | //\\ !(a{}); |
| 2707 | //\\ a + b{}; |
| 2708 | //\\ (a + b){}; |
| 2709 | ); |
| 2710 | } |
| 2711 | |
| 2552 | 2712 | test "zig fmt: prefix operators" { |
| 2553 | 2713 | try testCanonical( |
| 2554 | 2714 | \\test "prefix operators" { |
| ... | ... | @@ -3062,39 +3222,6 @@ test "zig fmt: container initializers" { |
| 3062 | 3222 | ); |
| 3063 | 3223 | } |
| 3064 | 3224 | |
| 3065 | | test "zig fmt: precedence" { |
| 3066 | | try testCanonical( |
| 3067 | | \\test "precedence" { |
| 3068 | | \\ a!b(); |
| 3069 | | \\ (a!b)(); |
| 3070 | | \\ !a!b; |
| 3071 | | \\ !(a!b); |
| 3072 | | \\ !a{}; |
| 3073 | | \\ !(a{}); |
| 3074 | | \\ a + b{}; |
| 3075 | | \\ (a + b){}; |
| 3076 | | \\ a << b + c; |
| 3077 | | \\ (a << b) + c; |
| 3078 | | \\ a & b << c; |
| 3079 | | \\ (a & b) << c; |
| 3080 | | \\ a ^ b & c; |
| 3081 | | \\ (a ^ b) & c; |
| 3082 | | \\ a | b ^ c; |
| 3083 | | \\ (a | b) ^ c; |
| 3084 | | \\ a == b | c; |
| 3085 | | \\ (a == b) | c; |
| 3086 | | \\ a and b == c; |
| 3087 | | \\ (a and b) == c; |
| 3088 | | \\ a or b and c; |
| 3089 | | \\ (a or b) and c; |
| 3090 | | \\ (a or b) and c; |
| 3091 | | \\ a = b or c; |
| 3092 | | \\ (a = b) or c; |
| 3093 | | \\} |
| 3094 | | \\ |
| 3095 | | ); |
| 3096 | | } |
| 3097 | | |
| 3098 | 3225 | test "zig fmt: zig fmt" { |
| 3099 | 3226 | try testCanonical(@embedFile("ast.zig")); |
| 3100 | 3227 | try testCanonical(@embedFile("index.zig")); |