authorgravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-04-04 14:58:51+02:00
committergravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-04-04 14:58:51+02:00
log744416ce0cd23c84e33965fc8171c0d1aea0659c
tree054deeb55f37b8eeb9531c5df88b4310b363ca7d
parentca0085c46dc5acb6ea93e35192b7b52294381d75

std.zig.parser should now parse operators with precedence.

* This haven't been tested yet

1 files changed, 177 insertions(+), 50 deletions(-)

std/zig/parser.zig+177-50
......@@ -1000,24 +1000,58 @@ pub const Parser = struct {
10001000
10011001 var expression = popSuffixOp(&stack);
10021002 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;
10071036 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 }
10211055 }
10221056 }
10231057 continue;
......@@ -1308,6 +1342,99 @@ pub const Parser = struct {
13081342 }
13091343 }
13101344
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
13111438 fn commaOrEnd(self: &Parser, stack: &ArrayList(State), end: &const Token.Id, ptr: &Token, state_after_comma: &const State) !void {
13121439 var token = self.getNextToken();
13131440 switch (token.id) {
......@@ -2549,6 +2676,39 @@ test "zig fmt: infix operators" {
25492676 );
25502677}
25512678
2679test "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
25522712test "zig fmt: prefix operators" {
25532713 try testCanonical(
25542714 \\test "prefix operators" {
......@@ -3062,39 +3222,6 @@ test "zig fmt: container initializers" {
30623222 );
30633223}
30643224
3065test "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
30983225test "zig fmt: zig fmt" {
30993226 try testCanonical(@embedFile("ast.zig"));
31003227 try testCanonical(@embedFile("index.zig"));