Skip to content

Commit ec124a4

Browse files
committed
Cleanup round 2 from review
- Remove TODO about stage1 CompareExpr and make a follow-up task - Support enum literals, update grammar, and add test - Remove TODO comments about enum literals - Remove TODO question about ErrorSetDecl not hard-failing - Error if label found but no block - Disallow duplicate pointer qualifiers (const, allowzero, etc.) and add a stage2 compile error test (disabled; see ziglang#1364)
1 parent b8ec839 commit ec124a4

File tree

3 files changed

+80
-12
lines changed

3 files changed

+80
-12
lines changed

std/zig/parse.zig

+41-12
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,6 @@ fn parseBoolAndExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
808808
// CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)?
809809
fn parseCompareExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
810810
return parseBinOpExpr(arena, it, tree, parseCompareOp, parseBitwiseExpr, .Once);
811-
// TODO: stage1 supplies BinOpChainInf, not Once, but grammar uses `?`
812811
}
813812

814813
// BitwiseExpr <- BitShiftExpr (BitwiseOp BitShiftExpr)*
@@ -849,8 +848,6 @@ fn parsePrefixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
849848
// / Block
850849
// / CurlySuffixExpr
851850
fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
852-
// TODO: enum literal not represented in grammar: https://github.com/ziglang/zig/issues/2235
853-
if (try parseEnumLiteral(arena, it, tree)) |node| return node;
854851
if (try parseAsmExpr(arena, it, tree)) |node| return node;
855852
if (try parseIfExpr(arena, it, tree)) |node| return node;
856853

@@ -1213,6 +1210,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
12131210
// <- BUILTINIDENTIFIER FnCallArguments
12141211
// / CHAR_LITERAL
12151212
// / ContainerDecl
1213+
// / DOT IDENTIFIER
12161214
// / ErrorSetDecl
12171215
// / FLOAT
12181216
// / FnProto
@@ -1243,6 +1241,7 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
12431241
return &node.base;
12441242
}
12451243
if (try parseContainerDecl(arena, it, tree)) |node| return node;
1244+
if (try parseEnumLiteral(arena, it, tree)) |node| return node;
12461245
if (try parseErrorSetDecl(arena, it, tree)) |node| return node;
12471246
if (try parseFloatLiteral(arena, it, tree)) |node| return node;
12481247
if (try parseFnProto(arena, it, tree)) |node| return node;
@@ -1318,7 +1317,7 @@ fn parseContainerDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Nod
13181317
fn parseErrorSetDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
13191318
const error_token = eatToken(it, .Keyword_error) orelse return null;
13201319
if (eatToken(it, .LBrace) == null) {
1321-
// TODO: Check the order of choices that leads to this not being "expectToken"
1320+
// Might parse as `KEYWORD_error DOT IDENTIFIER` later in PrimaryTypeExpr, so don't error
13221321
_ = prevToken(it);
13231322
return null;
13241323
}
@@ -1381,8 +1380,11 @@ fn parseLabeledTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
13811380
}
13821381

13831382
if (label != null) {
1384-
_ = prevToken(it); // rewind IDENTIFIER
1385-
_ = prevToken(it); // rewind ":"
1383+
// If we saw a label, there should have been a block next
1384+
try tree.errors.push(AstError{
1385+
.ExpectedLBrace = AstError.ExpectedLBrace{ .token = it.index },
1386+
});
1387+
return Error.UnexpectedToken;
13861388
}
13871389
return null;
13881390
}
@@ -1519,11 +1521,10 @@ fn parseAsmExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
15191521
return &node.base;
15201522
}
15211523

1522-
// TODO: enum literal not represented in grammar: https://github.com/ziglang/zig/issues/2235
1524+
// DOT IDENTIFIER
15231525
fn parseEnumLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
15241526
const dot = eatToken(it, .Period) orelse return null;
15251527
const name = try expectToken(it, tree, .Identifier);
1526-
15271528
const node = try arena.create(Node.EnumLiteral);
15281529
node.* = Node.EnumLiteral{
15291530
.base = Node{ .id = .EnumLiteral },
@@ -1646,7 +1647,12 @@ fn parseBlockLabel(arena: *Allocator, it: *TokenIterator, tree: *Tree) ?TokenInd
16461647
fn parseFieldInit(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
16471648
const period_token = eatToken(it, .Period) orelse return null;
16481649
const name_token = try expectToken(it, tree, .Identifier);
1649-
const eq_token = try expectToken(it, tree, .Equal);
1650+
const eq_token = eatToken(it, .Equal) orelse {
1651+
// `.Name` may also be an enum literal, which is a later rule.
1652+
_ = prevToken(it); // rewind IDENTIFIER
1653+
_ = prevToken(it); // rewind DOT
1654+
return null;
1655+
};
16501656
const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{
16511657
.ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
16521658
});
@@ -2204,10 +2210,8 @@ fn parsePrefixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
22042210
return &node.base;
22052211
}
22062212

2207-
// TODO: last choice allows for `*const volatile volatile const`, `*align(4) align(8) align(4)` etc.
22082213
// TODO: ArrayTypeStart is either an array or a slice, but const/allowzero only work on
2209-
// pointers. (Note: does align(x) work for arrays as well as slices/pointers? Does volatile?)
2210-
// Maybe it would be better to have two separate rules?
2214+
// pointers. Consider updating this rule:
22112215
// ...
22122216
// / ArrayTypeStart
22132217
// / SliceTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
@@ -2255,23 +2259,48 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
22552259
switch (node.cast(Node.PrefixOp).?.op) {
22562260
.ArrayType => {},
22572261
.SliceType => |*slice_type| {
2262+
// Collect pointer qualifiers in any order, but disallow duplicates
22582263
while (true) {
22592264
if (try parseByteAlign(arena, it, tree)) |align_expr| {
2265+
if (slice_type.align_info != null) {
2266+
try tree.errors.push(AstError{
2267+
.ExtraAlignQualifier = AstError.ExtraAlignQualifier{ .token = it.index },
2268+
});
2269+
return Error.UnexpectedToken;
2270+
}
22602271
slice_type.align_info = Node.PrefixOp.PtrInfo.Align{
22612272
.node = align_expr,
22622273
.bit_range = null,
22632274
};
22642275
continue;
22652276
}
22662277
if (eatToken(it, .Keyword_const)) |const_token| {
2278+
if (slice_type.const_token != null) {
2279+
try tree.errors.push(AstError{
2280+
.ExtraConstQualifier = AstError.ExtraConstQualifier{ .token = it.index },
2281+
});
2282+
return Error.UnexpectedToken;
2283+
}
22672284
slice_type.const_token = const_token;
22682285
continue;
22692286
}
22702287
if (eatToken(it, .Keyword_volatile)) |volatile_token| {
2288+
if (slice_type.volatile_token != null) {
2289+
try tree.errors.push(AstError{
2290+
.ExtraVolatileQualifier = AstError.ExtraVolatileQualifier{ .token = it.index },
2291+
});
2292+
return Error.UnexpectedToken;
2293+
}
22712294
slice_type.volatile_token = volatile_token;
22722295
continue;
22732296
}
22742297
if (eatToken(it, .Keyword_allowzero)) |allowzero_token| {
2298+
if (slice_type.allowzero_token != null) {
2299+
try tree.errors.push(AstError{
2300+
.ExtraAllowZeroQualifier = AstError.ExtraAllowZeroQualifier{ .token = it.index },
2301+
});
2302+
return Error.UnexpectedToken;
2303+
}
22752304
slice_type.allowzero_token = allowzero_token;
22762305
continue;
22772306
}

std/zig/parser_test.zig

+15
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,21 @@ test "zig fmt: enum literal" {
1212
);
1313
}
1414

15+
test "zig fmt: enum literal inside array literal" {
16+
try testCanonical(
17+
\\test "enums in arrays" {
18+
\\ var colors = []Color{.Green};
19+
\\ colors = []Colors{ .Green, .Cyan };
20+
\\ colors = []Colors{
21+
\\ .Grey,
22+
\\ .Green,
23+
\\ .Cyan,
24+
\\ };
25+
\\}
26+
\\
27+
);
28+
}
29+
1530
test "zig fmt: character literal larger than u8" {
1631
try testCanonical(
1732
\\const x = '\U01f4a9';

test/stage2/compile_errors.zig

+24
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,28 @@ pub fn addCases(ctx: *TestContext) !void {
2727
\\ return 36893488147419103232;
2828
\\}
2929
, "1.zig", 2, 12, "integer value '36893488147419103232' cannot be stored in type 'c_int'");
30+
31+
try ctx.testCompileError(
32+
\\comptime {
33+
\\ var a: *align(4) align(4) i32 = 0;
34+
\\}
35+
, "1.zig", 2, 22, "Extra align qualifier");
36+
37+
try ctx.testCompileError(
38+
\\comptime {
39+
\\ var b: *const const i32 = 0;
40+
\\}
41+
, "1.zig", 2, 19, "Extra align qualifier");
42+
43+
try ctx.testCompileError(
44+
\\comptime {
45+
\\ var c: *volatile volatile i32 = 0;
46+
\\}
47+
, "1.zig", 2, 22, "Extra align qualifier");
48+
49+
try ctx.testCompileError(
50+
\\comptime {
51+
\\ var d: *allowzero allowzero i32 = 0;
52+
\\}
53+
, "1.zig", 2, 23, "Extra align qualifier");
3054
}

0 commit comments

Comments
 (0)