aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorIsaac Freund <ifreund@ifreund.xyz>2021-03-07 12:38:08 +0100
committerIsaac Freund <ifreund@ifreund.xyz>2021-03-08 01:37:28 +0100
commitb988815bf0771dd86a345ce8ed8b0d3eb9d6f55e (patch)
treefed9a51f338b4ada0bbebf6314bba22482813361 /lib/std
parentd01bb211732f1d0aebf558c43825a52254d034ab (diff)
downloadzig-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.zig9
-rw-r--r--lib/std/zig/parse.zig36
-rw-r--r--lib/std/zig/parser_test.zig2
-rw-r--r--lib/std/zig/render.zig29
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(