diff options
| author | Isaac Freund <ifreund@ifreund.xyz> | 2021-03-07 12:38:08 +0100 |
|---|---|---|
| committer | Isaac Freund <ifreund@ifreund.xyz> | 2021-03-08 01:37:28 +0100 |
| commit | b988815bf0771dd86a345ce8ed8b0d3eb9d6f55e (patch) | |
| tree | fed9a51f338b4ada0bbebf6314bba22482813361 /lib/std | |
| parent | d01bb211732f1d0aebf558c43825a52254d034ab (diff) | |
| download | zig-b988815bf0771dd86a345ce8ed8b0d3eb9d6f55e.tar.gz zig-b988815bf0771dd86a345ce8ed8b0d3eb9d6f55e.zip | |
parser: fix parsing/rendering of a[b.. :c] slicing
The modification to the grammar in the comment is in line with the
grammar in the zig-spec repo.
Note: checking if the previous token is a colon is insufficent to tell
if a block has a label, the identifier must be checked for as well. This
can be seen in sentinel terminated slicing: `foo[0..1:{}]`
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/zig/ast.zig | 9 | ||||
| -rw-r--r-- | lib/std/zig/parse.zig | 36 | ||||
| -rw-r--r-- | lib/std/zig/parser_test.zig | 2 | ||||
| -rw-r--r-- | lib/std/zig/render.zig | 29 |
4 files changed, 40 insertions, 36 deletions
diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index 1a0515b475..59de727bcc 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -525,7 +525,9 @@ pub const Tree = struct { => { // Look for a label. const lbrace = main_tokens[n]; - if (token_tags[lbrace - 1] == .colon) { + if (token_tags[lbrace - 1] == .colon and + token_tags[lbrace - 2] == .identifier) + { end_offset += 2; } return lbrace - end_offset; @@ -989,13 +991,13 @@ pub const Tree = struct { }, .slice => { const extra = tree.extraData(datas[n].rhs, Node.Slice); - assert(extra.end != 0); // should have used SliceOpen + assert(extra.end != 0); // should have used slice_open end_offset += 1; // rbracket n = extra.end; }, .slice_sentinel => { const extra = tree.extraData(datas[n].rhs, Node.SliceSentinel); - assert(extra.sentinel != 0); // should have used Slice + assert(extra.sentinel != 0); // should have used slice end_offset += 1; // rbracket n = extra.sentinel; }, @@ -2925,6 +2927,7 @@ pub const Node = struct { pub const SliceSentinel = struct { start: Index, + /// May be 0 if the slice is "open" end: Index, sentinel: Index, }; diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index ad32d3182d..c8a4cffdbd 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -3441,7 +3441,7 @@ const Parser = struct { } /// SuffixOp - /// <- LBRACKET Expr (DOT2 (Expr (COLON Expr)?)?)? RBRACKET + /// <- LBRACKET Expr (DOT2 (Expr? (COLON Expr)?)?)? RBRACKET /// / DOT IDENTIFIER /// / DOTASTERISK /// / DOTQUESTIONMARK @@ -3453,17 +3453,6 @@ const Parser = struct { if (p.eatToken(.ellipsis2)) |_| { const end_expr = try p.parseExpr(); - if (end_expr == 0) { - _ = try p.expectToken(.r_bracket); - return p.addNode(.{ - .tag = .slice_open, - .main_token = lbracket, - .data = .{ - .lhs = lhs, - .rhs = index_expr, - }, - }); - } if (p.eatToken(.colon)) |_| { const sentinel = try p.parseExpr(); _ = try p.expectToken(.r_bracket); @@ -3479,20 +3468,29 @@ const Parser = struct { }), }, }); - } else { - _ = try p.expectToken(.r_bracket); + } + _ = try p.expectToken(.r_bracket); + if (end_expr == 0) { return p.addNode(.{ - .tag = .slice, + .tag = .slice_open, .main_token = lbracket, .data = .{ .lhs = lhs, - .rhs = try p.addExtra(Node.Slice{ - .start = index_expr, - .end = end_expr, - }), + .rhs = index_expr, }, }); } + return p.addNode(.{ + .tag = .slice, + .main_token = lbracket, + .data = .{ + .lhs = lhs, + .rhs = try p.addExtra(Node.Slice{ + .start = index_expr, + .end = end_expr, + }), + }, + }); } _ = try p.expectToken(.r_bracket); return p.addNode(.{ diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 5c0f4b3bda..b9f856fba3 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -852,6 +852,7 @@ test "zig fmt: slices" { try testCanonical( \\const a = b[0..]; \\const c = d[0..1]; + \\const d = f[0.. :0]; \\const e = f[0..1 :0]; \\ ); @@ -861,6 +862,7 @@ test "zig fmt: slices with spaces in bounds" { try testCanonical( \\const a = b[0 + 0 ..]; \\const c = d[0 + 0 .. 1]; + \\const c = d[0 + 0 .. :0]; \\const e = f[0 .. 1 + 1 :0]; \\ ); diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 069b62af79..30e83e9a7c 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -470,9 +470,9 @@ fn renderExpression(gpa: *Allocator, ais: *Ais, tree: ast.Tree, node: ast.Node.I return renderToken(ais, tree, rbracket, space); // ] }, - .slice_open => return renderSlice(gpa, ais, tree, tree.sliceOpen(node), space), - .slice => return renderSlice(gpa, ais, tree, tree.slice(node), space), - .slice_sentinel => return renderSlice(gpa, ais, tree, tree.sliceSentinel(node), space), + .slice_open => return renderSlice(gpa, ais, tree, node, tree.sliceOpen(node), space), + .slice => return renderSlice(gpa, ais, tree, node, tree.slice(node), space), + .slice_sentinel => return renderSlice(gpa, ais, tree, node, tree.sliceSentinel(node), space), .deref => { try renderExpression(gpa, ais, tree, datas[node].lhs, .none); @@ -815,6 +815,7 @@ fn renderSlice( gpa: *Allocator, ais: *Ais, tree: ast.Tree, + slice_node: ast.Node.Index, slice: ast.full.Slice, space: Space, ) Error!void { @@ -822,7 +823,9 @@ fn renderSlice( const after_start_space_bool = nodeCausesSliceOpSpace(node_tags[slice.ast.start]) or if (slice.ast.end != 0) nodeCausesSliceOpSpace(node_tags[slice.ast.end]) else false; const after_start_space = if (after_start_space_bool) Space.space else Space.none; - const after_dots_space = if (slice.ast.end != 0) after_start_space else Space.none; + const after_dots_space = if (slice.ast.end != 0) + after_start_space + else if (slice.ast.sentinel != 0) Space.space else Space.none; try renderExpression(gpa, ais, tree, slice.ast.sliced, .none); try renderToken(ais, tree, slice.ast.lbracket, .none); // lbracket @@ -830,20 +833,18 @@ fn renderSlice( const start_last = tree.lastToken(slice.ast.start); try renderExpression(gpa, ais, tree, slice.ast.start, after_start_space); try renderToken(ais, tree, start_last + 1, after_dots_space); // ellipsis2 ("..") - if (slice.ast.end == 0) { - return renderToken(ais, tree, start_last + 2, space); // rbracket + + if (slice.ast.end != 0) { + const after_end_space = if (slice.ast.sentinel != 0) Space.space else Space.none; + try renderExpression(gpa, ais, tree, slice.ast.end, after_end_space); } - const end_last = tree.lastToken(slice.ast.end); - const after_end_space = if (slice.ast.sentinel != 0) Space.space else Space.none; - try renderExpression(gpa, ais, tree, slice.ast.end, after_end_space); - if (slice.ast.sentinel == 0) { - return renderToken(ais, tree, end_last + 1, space); // rbracket + if (slice.ast.sentinel != 0) { + try renderToken(ais, tree, tree.firstToken(slice.ast.sentinel) - 1, .none); // colon + try renderExpression(gpa, ais, tree, slice.ast.sentinel, .none); } - try renderToken(ais, tree, end_last + 1, .none); // colon - try renderExpression(gpa, ais, tree, slice.ast.sentinel, .none); - try renderToken(ais, tree, tree.lastToken(slice.ast.sentinel) + 1, space); // rbracket + try renderToken(ais, tree, tree.lastToken(slice_node), space); // rbracket } fn renderAsmOutput( |
