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 {...@@ -136,6 +136,9 @@ pub fn renderError(tree: Tree, parse_error: Error, stream: anytype) !void {
136 // location would point to the `*` after the `.*`.136 // location would point to the `*` after the `.*`.
137 return stream.writeAll("'.*' cannot be followed by '*'. Are you missing a space?");137 return stream.writeAll("'.*' cannot be followed by '*'. Are you missing a space?");
138 },138 },
139 .chained_comparison_operators => {
140 return stream.writeAll("comparison operators cannot be chained");
141 },
139 .decl_between_fields => {142 .decl_between_fields => {
140 return stream.writeAll("declarations are not allowed between container fields");143 return stream.writeAll("declarations are not allowed between container fields");
141 },144 },
...@@ -2424,6 +2427,7 @@ pub const Error = struct {...@@ -2424,6 +2427,7 @@ pub const Error = struct {
24242427
2425 pub const Tag = enum {2428 pub const Tag = enum {
2426 asterisk_after_ptr_deref,2429 asterisk_after_ptr_deref,
2430 chained_comparison_operators,
2427 decl_between_fields,2431 decl_between_fields,
2428 expected_block,2432 expected_block,
2429 expected_block_or_assignment,2433 expected_block_or_assignment,
lib/std/zig/parse.zig+5-1
...@@ -1374,6 +1374,7 @@ const Parser = struct {...@@ -1374,6 +1374,7 @@ const Parser = struct {
1374 });1374 });
13751375
1376 fn parseExprPrecedence(p: *Parser, min_prec: i32) Error!Node.Index {1376 fn parseExprPrecedence(p: *Parser, min_prec: i32) Error!Node.Index {
1377 assert(min_prec >= 0);
1377 var node = try p.parsePrefixExpr();1378 var node = try p.parsePrefixExpr();
1378 if (node == 0) {1379 if (node == 0) {
1379 return null_node;1380 return null_node;
...@@ -1384,9 +1385,12 @@ const Parser = struct {...@@ -1384,9 +1385,12 @@ const Parser = struct {
1384 while (true) {1385 while (true) {
1385 const tok_tag = p.token_tags[p.tok_i];1386 const tok_tag = p.token_tags[p.tok_i];
1386 const info = operTable[@intCast(usize, @enumToInt(tok_tag))];1387 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) {
1388 break;1389 break;
1389 }1390 }
1391 if (info.prec == banned_prec) {
1392 return p.fail(.chained_comparison_operators);
1393 }
1390 const oper_token = p.nextToken();1394 const oper_token = p.nextToken();
1391 // Special-case handling for "catch" and "&&".1395 // Special-case handling for "catch" and "&&".
1392 switch (tok_tag) {1396 switch (tok_tag) {
lib/std/zig/parser_test.zig+2-2
...@@ -5056,8 +5056,8 @@ test "recovery: non-associative operators" {...@@ -5056,8 +5056,8 @@ test "recovery: non-associative operators" {
5056 \\const x = a == b == c;5056 \\const x = a == b == c;
5057 \\const x = a == b != c;5057 \\const x = a == b != c;
5058 , &[_]Error{5058 , &[_]Error{
5059 .expected_token,5059 .chained_comparison_operators,
5060 .expected_token,5060 .chained_comparison_operators,
5061 });5061 });
5062}5062}
50635063
test/compile_errors.zig+9-6
...@@ -5033,18 +5033,21 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -5033,18 +5033,21 @@ pub fn addCases(ctx: *TestContext) !void {
5033 "tmp.zig:2:5: note: control flow is diverted here",5033 "tmp.zig:2:5: note: control flow is diverted here",
5034 });5034 });
50355035
5036 ctx.objErrStage1("unreachable code - multiple things",5036 ctx.objErrStage1("unreachable code - nested returns",
5037 \\export fn a() i32 {5037 \\export fn a() i32 {
5038 \\ return return 1;5038 \\ return return 1;
5039 \\}5039 \\}
5040 \\export fn b(value: u32) bool {
5041 \\ return 1 < value < 1000;
5042 \\}
5043 , &[_][]const u8{5040 , &[_][]const u8{
5044 "tmp.zig:2:5: error: unreachable code",5041 "tmp.zig:2:5: error: unreachable code",
5045 "tmp.zig:2:12: note: control flow is diverted here",5042 "tmp.zig:2:12: note: control flow is diverted here",
5046 "tmp.zig:5:22: error: unreachable code",5043 });
5047 "tmp.zig:5:5: note: control flow is diverted here",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",
5048 });5051 });
50495052
5050 ctx.objErrStage1("bad import",5053 ctx.objErrStage1("bad import",