authorgravatar for matthew.h.borkowski@gmail.comMatthew Borkowski <matthew.h.borkowski@gmail.com> 2021-12-02 03:50:23-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-12-02 11:59:29-08:00
logc98b020ce29467e80217718e0a1856b7fccd6b53
treea8b4385bc6d9403d8762f63329d423a2789487f3
parentfb9fcf5632468b2aa8af73f4e3269a01535076f5

parse.zig: make chained comparison operators a parse error


4 files changed, 20 insertions(+), 9 deletions(-)

lib/std/zig/Ast.zig+4
......@@ -136,6 +136,9 @@ pub fn renderError(tree: Tree, parse_error: Error, stream: anytype) !void {
136136 // location would point to the `*` after the `.*`.
137137 return stream.writeAll("'.*' cannot be followed by '*'. Are you missing a space?");
138138 },
139 .chained_comparison_operators => {
140 return stream.writeAll("comparison operators cannot be chained");
141 },
139142 .decl_between_fields => {
140143 return stream.writeAll("declarations are not allowed between container fields");
141144 },
......@@ -2424,6 +2427,7 @@ pub const Error = struct {
24242427
24252428 pub const Tag = enum {
24262429 asterisk_after_ptr_deref,
2430 chained_comparison_operators,
24272431 decl_between_fields,
24282432 expected_block,
24292433 expected_block_or_assignment,
lib/std/zig/parse.zig+5-1
......@@ -1374,6 +1374,7 @@ const Parser = struct {
13741374 });
13751375
13761376 fn parseExprPrecedence(p: *Parser, min_prec: i32) Error!Node.Index {
1377 assert(min_prec >= 0);
13771378 var node = try p.parsePrefixExpr();
13781379 if (node == 0) {
13791380 return null_node;
......@@ -1384,9 +1385,12 @@ const Parser = struct {
13841385 while (true) {
13851386 const tok_tag = p.token_tags[p.tok_i];
13861387 const info = operTable[@intCast(usize, @enumToInt(tok_tag))];
1387 if (info.prec < min_prec or info.prec == banned_prec) {
1388 if (info.prec < min_prec) {
13881389 break;
13891390 }
1391 if (info.prec == banned_prec) {
1392 return p.fail(.chained_comparison_operators);
1393 }
13901394 const oper_token = p.nextToken();
13911395 // Special-case handling for "catch" and "&&".
13921396 switch (tok_tag) {
lib/std/zig/parser_test.zig+2-2
......@@ -5056,8 +5056,8 @@ test "recovery: non-associative operators" {
50565056 \\const x = a == b == c;
50575057 \\const x = a == b != c;
50585058 , &[_]Error{
5059 .expected_token,
5060 .expected_token,
5059 .chained_comparison_operators,
5060 .chained_comparison_operators,
50615061 });
50625062}
50635063
test/compile_errors.zig+9-6
......@@ -5033,18 +5033,21 @@ pub fn addCases(ctx: *TestContext) !void {
50335033 "tmp.zig:2:5: note: control flow is diverted here",
50345034 });
50355035
5036 ctx.objErrStage1("unreachable code - multiple things",
5036 ctx.objErrStage1("unreachable code - nested returns",
50375037 \\export fn a() i32 {
50385038 \\ return return 1;
50395039 \\}
5040 \\export fn b(value: u32) bool {
5041 \\ return 1 < value < 1000;
5042 \\}
50435040 , &[_][]const u8{
50445041 "tmp.zig:2:5: error: unreachable code",
50455042 "tmp.zig:2:12: note: control flow is diverted here",
5046 "tmp.zig:5:22: error: unreachable code",
5047 "tmp.zig:5:5: note: control flow is diverted here",
5043 });
5044
5045 ctx.objErrStage1("chained comparison operators",
5046 \\export fn a(value: u32) bool {
5047 \\ return 1 < value < 1000;
5048 \\}
5049 , &[_][]const u8{
5050 "tmp.zig:2:22: error: comparison operators cannot be chained",
50485051 });
50495052
50505053 ctx.objErrStage1("bad import",