lang: slice ranges take the same bound markers as for-header ranges
xs[1..=3] (end inclusive), xs[0<..<4] (both exclusive), xs[..=2] (prefix form with markers, implicit 0 start), xs[2<..] (open end, exclusive start), and xs[..] (whole collection) — lowered as lo+1 / hi+1 on the existing subslice op. Strings slice through the same path. An explicit end marker requires an end expression, matching the for-header rule. Regression: examples/0052-basic-slice-range-bounds.sx.
This commit is contained in:
@@ -2575,26 +2575,45 @@ pub const Parser = struct {
|
||||
const saved_hdr_idx = self.in_for_header;
|
||||
self.in_for_header = false;
|
||||
defer self.in_for_header = saved_hdr_idx;
|
||||
if (self.current.tag == .dot_dot) {
|
||||
// [..end]
|
||||
if (rangeTokenInfo(self.current.tag)) |rt| {
|
||||
// Prefix form: [..end] / [..=end] / [..] — implicit 0 start
|
||||
// (a start marker applies to it: [<..end] begins at 1).
|
||||
self.advance();
|
||||
const end_expr = try self.parseExpr();
|
||||
if (rt.end_marked and self.current.tag == .r_bracket) {
|
||||
return self.fail("a range with an explicit end marker ('..=' / '..<') requires an end expression — the open form is '..'");
|
||||
}
|
||||
const end_expr: ?*ast.Node = if (self.current.tag != .r_bracket)
|
||||
try self.parseExpr()
|
||||
else
|
||||
null;
|
||||
try self.expect(.r_bracket);
|
||||
expr = try self.createNode(expr.span.start, .{ .slice_expr = .{
|
||||
.object = expr, .start = null, .end = end_expr,
|
||||
.object = expr,
|
||||
.start = null,
|
||||
.end = end_expr,
|
||||
.start_exclusive = rt.start_exclusive,
|
||||
.end_inclusive = rt.end_inclusive,
|
||||
} });
|
||||
} else {
|
||||
const first = try self.parseExpr();
|
||||
if (self.current.tag == .dot_dot) {
|
||||
// [start..end] or [start..]
|
||||
if (rangeTokenInfo(self.current.tag)) |rt| {
|
||||
// [start..end] or [start..] — same bound-marker matrix
|
||||
// as the for-header ranges.
|
||||
self.advance();
|
||||
if (rt.end_marked and self.current.tag == .r_bracket) {
|
||||
return self.fail("a range with an explicit end marker ('..=' / '..<') requires an end expression — the open form is 'a..'");
|
||||
}
|
||||
const end_expr: ?*ast.Node = if (self.current.tag != .r_bracket)
|
||||
try self.parseExpr()
|
||||
else
|
||||
null;
|
||||
try self.expect(.r_bracket);
|
||||
expr = try self.createNode(expr.span.start, .{ .slice_expr = .{
|
||||
.object = expr, .start = first, .end = end_expr,
|
||||
.object = expr,
|
||||
.start = first,
|
||||
.end = end_expr,
|
||||
.start_exclusive = rt.start_exclusive,
|
||||
.end_inclusive = rt.end_inclusive,
|
||||
} });
|
||||
} else {
|
||||
// [index] — normal index access
|
||||
|
||||
Reference in New Issue
Block a user