Merge pull request #2405 from hryx/stage2-recursive-parser

Recursive stage2 parser
master
Andrew Kelley 2019-05-12 12:53:10 -04:00 committed by GitHub
commit ed5a6d74ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 3185 additions and 3770 deletions

View File

@ -1177,9 +1177,7 @@ pub const Builder = struct {
ast.Node.Id.Payload => return error.Unimplemented,
ast.Node.Id.PointerPayload => return error.Unimplemented,
ast.Node.Id.PointerIndexPayload => return error.Unimplemented,
ast.Node.Id.StructField => return error.Unimplemented,
ast.Node.Id.UnionTag => return error.Unimplemented,
ast.Node.Id.EnumTag => return error.Unimplemented,
ast.Node.Id.ContainerField => return error.Unimplemented,
ast.Node.Id.ErrorTag => return error.Unimplemented,
ast.Node.Id.AsmInput => return error.Unimplemented,
ast.Node.Id.AsmOutput => return error.Unimplemented,

View File

@ -113,12 +113,22 @@ pub const Tree = struct {
pub const Error = union(enum) {
InvalidToken: InvalidToken,
ExpectedContainerMembers: ExpectedContainerMembers,
ExpectedStringLiteral: ExpectedStringLiteral,
ExpectedIntegerLiteral: ExpectedIntegerLiteral,
ExpectedPubItem: ExpectedPubItem,
ExpectedIdentifier: ExpectedIdentifier,
ExpectedStatement: ExpectedStatement,
ExpectedVarDeclOrFn: ExpectedVarDeclOrFn,
ExpectedVarDecl: ExpectedVarDecl,
ExpectedReturnType: ExpectedReturnType,
ExpectedAggregateKw: ExpectedAggregateKw,
UnattachedDocComment: UnattachedDocComment,
ExpectedEqOrSemi: ExpectedEqOrSemi,
ExpectedSemiOrLBrace: ExpectedSemiOrLBrace,
ExpectedSemiOrElse: ExpectedSemiOrElse,
ExpectedLabelOrLBrace: ExpectedLabelOrLBrace,
ExpectedLBrace: ExpectedLBrace,
ExpectedColonOrRParen: ExpectedColonOrRParen,
ExpectedLabelable: ExpectedLabelable,
ExpectedInlinable: ExpectedInlinable,
@ -130,20 +140,43 @@ pub const Error = union(enum) {
ExtraConstQualifier: ExtraConstQualifier,
ExtraVolatileQualifier: ExtraVolatileQualifier,
ExtraAllowZeroQualifier: ExtraAllowZeroQualifier,
ExpectedTypeExpr: ExpectedTypeExpr,
ExpectedPrimaryTypeExpr: ExpectedPrimaryTypeExpr,
ExpectedParamType: ExpectedParamType,
ExpectedExpr: ExpectedExpr,
ExpectedPrimaryExpr: ExpectedPrimaryExpr,
ExpectedToken: ExpectedToken,
ExpectedCommaOrEnd: ExpectedCommaOrEnd,
ExpectedParamList: ExpectedParamList,
ExpectedPayload: ExpectedPayload,
ExpectedBlockOrAssignment: ExpectedBlockOrAssignment,
ExpectedBlockOrExpression: ExpectedBlockOrExpression,
ExpectedExprOrAssignment: ExpectedExprOrAssignment,
ExpectedPrefixExpr: ExpectedPrefixExpr,
ExpectedLoopExpr: ExpectedLoopExpr,
ExpectedDerefOrUnwrap: ExpectedDerefOrUnwrap,
ExpectedSuffixOp: ExpectedSuffixOp,
pub fn render(self: *const Error, tokens: *Tree.TokenList, stream: var) !void {
switch (self.*) {
// TODO https://github.com/ziglang/zig/issues/683
@TagType(Error).InvalidToken => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedContainerMembers => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedStringLiteral => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedIntegerLiteral => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedPubItem => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedIdentifier => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedStatement => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedVarDeclOrFn => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedVarDecl => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedReturnType => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedAggregateKw => |*x| return x.render(tokens, stream),
@TagType(Error).UnattachedDocComment => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedEqOrSemi => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedSemiOrLBrace => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedSemiOrElse => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedLabelOrLBrace => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedLBrace => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedColonOrRParen => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedLabelable => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedInlinable => |*x| return x.render(tokens, stream),
@ -155,9 +188,22 @@ pub const Error = union(enum) {
@TagType(Error).ExtraConstQualifier => |*x| return x.render(tokens, stream),
@TagType(Error).ExtraVolatileQualifier => |*x| return x.render(tokens, stream),
@TagType(Error).ExtraAllowZeroQualifier => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedTypeExpr => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedPrimaryTypeExpr => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedParamType => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedExpr => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedPrimaryExpr => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedToken => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedCommaOrEnd => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedParamList => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedPayload => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedBlockOrAssignment => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedBlockOrExpression => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedExprOrAssignment => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedPrefixExpr => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedLoopExpr => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedDerefOrUnwrap => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedSuffixOp => |*x| return x.render(tokens, stream),
}
}
@ -165,12 +211,22 @@ pub const Error = union(enum) {
switch (self.*) {
// TODO https://github.com/ziglang/zig/issues/683
@TagType(Error).InvalidToken => |x| return x.token,
@TagType(Error).ExpectedContainerMembers => |x| return x.token,
@TagType(Error).ExpectedStringLiteral => |x| return x.token,
@TagType(Error).ExpectedIntegerLiteral => |x| return x.token,
@TagType(Error).ExpectedPubItem => |x| return x.token,
@TagType(Error).ExpectedIdentifier => |x| return x.token,
@TagType(Error).ExpectedStatement => |x| return x.token,
@TagType(Error).ExpectedVarDeclOrFn => |x| return x.token,
@TagType(Error).ExpectedVarDecl => |x| return x.token,
@TagType(Error).ExpectedReturnType => |x| return x.token,
@TagType(Error).ExpectedAggregateKw => |x| return x.token,
@TagType(Error).UnattachedDocComment => |x| return x.token,
@TagType(Error).ExpectedEqOrSemi => |x| return x.token,
@TagType(Error).ExpectedSemiOrLBrace => |x| return x.token,
@TagType(Error).ExpectedSemiOrElse => |x| return x.token,
@TagType(Error).ExpectedLabelOrLBrace => |x| return x.token,
@TagType(Error).ExpectedLBrace => |x| return x.token,
@TagType(Error).ExpectedColonOrRParen => |x| return x.token,
@TagType(Error).ExpectedLabelable => |x| return x.token,
@TagType(Error).ExpectedInlinable => |x| return x.token,
@ -182,25 +238,61 @@ pub const Error = union(enum) {
@TagType(Error).ExtraConstQualifier => |x| return x.token,
@TagType(Error).ExtraVolatileQualifier => |x| return x.token,
@TagType(Error).ExtraAllowZeroQualifier => |x| return x.token,
@TagType(Error).ExpectedTypeExpr => |x| return x.token,
@TagType(Error).ExpectedPrimaryTypeExpr => |x| return x.token,
@TagType(Error).ExpectedParamType => |x| return x.token,
@TagType(Error).ExpectedExpr => |x| return x.token,
@TagType(Error).ExpectedPrimaryExpr => |x| return x.token,
@TagType(Error).ExpectedToken => |x| return x.token,
@TagType(Error).ExpectedCommaOrEnd => |x| return x.token,
@TagType(Error).ExpectedParamList => |x| return x.token,
@TagType(Error).ExpectedPayload => |x| return x.token,
@TagType(Error).ExpectedBlockOrAssignment => |x| return x.token,
@TagType(Error).ExpectedBlockOrExpression => |x| return x.token,
@TagType(Error).ExpectedExprOrAssignment => |x| return x.token,
@TagType(Error).ExpectedPrefixExpr => |x| return x.token,
@TagType(Error).ExpectedLoopExpr => |x| return x.token,
@TagType(Error).ExpectedDerefOrUnwrap => |x| return x.token,
@TagType(Error).ExpectedSuffixOp => |x| return x.token,
}
}
pub const InvalidToken = SingleTokenError("Invalid token {}");
pub const ExpectedContainerMembers = SingleTokenError("Expected test, comptime, var decl, or container field, found {}");
pub const ExpectedStringLiteral = SingleTokenError("Expected string literal, found {}");
pub const ExpectedIntegerLiteral = SingleTokenError("Expected integer literal, found {}");
pub const ExpectedIdentifier = SingleTokenError("Expected identifier, found {}");
pub const ExpectedStatement = SingleTokenError("Expected statement, found {}");
pub const ExpectedVarDeclOrFn = SingleTokenError("Expected variable declaration or function, found {}");
pub const ExpectedVarDecl = SingleTokenError("Expected variable declaration, found {}");
pub const ExpectedReturnType = SingleTokenError("Expected 'var' or return type expression, found {}");
pub const ExpectedAggregateKw = SingleTokenError("Expected " ++ @tagName(Token.Id.Keyword_struct) ++ ", " ++ @tagName(Token.Id.Keyword_union) ++ ", or " ++ @tagName(Token.Id.Keyword_enum) ++ ", found {}");
pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found {}");
pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found {}");
pub const ExpectedSemiOrElse = SingleTokenError("Expected ';' or 'else', found {}");
pub const ExpectedLBrace = SingleTokenError("Expected '{{', found {}");
pub const ExpectedLabelOrLBrace = SingleTokenError("Expected label or '{{', found {}");
pub const ExpectedColonOrRParen = SingleTokenError("Expected ':' or ')', found {}");
pub const ExpectedLabelable = SingleTokenError("Expected 'while', 'for', 'inline', 'suspend', or '{{', found {}");
pub const ExpectedInlinable = SingleTokenError("Expected 'while' or 'for', found {}");
pub const ExpectedAsmOutputReturnOrType = SingleTokenError("Expected '->' or " ++ @tagName(Token.Id.Identifier) ++ ", found {}");
pub const ExpectedSliceOrRBracket = SingleTokenError("Expected ']' or '..', found {}");
pub const ExpectedTypeExpr = SingleTokenError("Expected type expression, found {}");
pub const ExpectedPrimaryTypeExpr = SingleTokenError("Expected primary type expression, found {}");
pub const ExpectedExpr = SingleTokenError("Expected expression, found {}");
pub const ExpectedPrimaryExpr = SingleTokenError("Expected primary expression, found {}");
pub const ExpectedParamList = SingleTokenError("Expected parameter list, found {}");
pub const ExpectedPayload = SingleTokenError("Expected loop payload, found {}");
pub const ExpectedBlockOrAssignment = SingleTokenError("Expected block or assignment, found {}");
pub const ExpectedBlockOrExpression = SingleTokenError("Expected block or expression, found {}");
pub const ExpectedExprOrAssignment = SingleTokenError("Expected expression or assignment, found {}");
pub const ExpectedPrefixExpr = SingleTokenError("Expected prefix expression, found {}");
pub const ExpectedLoopExpr = SingleTokenError("Expected loop expression, found {}");
pub const ExpectedDerefOrUnwrap = SingleTokenError("Expected pointer dereference or optional unwrap, found {}");
pub const ExpectedSuffixOp = SingleTokenError("Expected pointer dereference, optional unwrap, or field access, found {}");
pub const ExpectedParamType = SimpleError("Expected parameter type");
pub const ExpectedPubItem = SimpleError("Pub must be followed by fn decl, var decl, or container member");
pub const UnattachedDocComment = SimpleError("Unattached documentation comment");
pub const ExtraAlignQualifier = SimpleError("Extra align qualifier");
pub const ExtraConstQualifier = SimpleError("Extra const qualifier");
@ -329,9 +421,7 @@ pub const Node = struct {
Payload,
PointerPayload,
PointerIndexPayload,
StructField,
UnionTag,
EnumTag,
ContainerField,
ErrorTag,
AsmInput,
AsmOutput,
@ -395,9 +485,7 @@ pub const Node = struct {
while (true) {
switch (n.id) {
Id.Root,
Id.StructField,
Id.UnionTag,
Id.EnumTag,
Id.ContainerField,
Id.ParamDecl,
Id.Block,
Id.Payload,
@ -658,40 +746,15 @@ pub const Node = struct {
}
};
pub const StructField = struct {
pub const ContainerField = struct {
base: Node,
doc_comments: ?*DocComment,
visib_token: ?TokenIndex,
name_token: TokenIndex,
type_expr: *Node,
pub fn iterate(self: *StructField, index: usize) ?*Node {
var i = index;
if (i < 1) return self.type_expr;
i -= 1;
return null;
}
pub fn firstToken(self: *const StructField) TokenIndex {
if (self.visib_token) |visib_token| return visib_token;
return self.name_token;
}
pub fn lastToken(self: *const StructField) TokenIndex {
return self.type_expr.lastToken();
}
};
pub const UnionTag = struct {
base: Node,
doc_comments: ?*DocComment,
name_token: TokenIndex,
type_expr: ?*Node,
value_expr: ?*Node,
pub fn iterate(self: *UnionTag, index: usize) ?*Node {
pub fn iterate(self: *ContainerField, index: usize) ?*Node {
var i = index;
if (self.type_expr) |type_expr| {
@ -707,11 +770,12 @@ pub const Node = struct {
return null;
}
pub fn firstToken(self: *const UnionTag) TokenIndex {
pub fn firstToken(self: *const ContainerField) TokenIndex {
if (self.visib_token) |visib_token| return visib_token;
return self.name_token;
}
pub fn lastToken(self: *const UnionTag) TokenIndex {
pub fn lastToken(self: *const ContainerField) TokenIndex {
if (self.value_expr) |value_expr| {
return value_expr.lastToken();
}
@ -723,36 +787,6 @@ pub const Node = struct {
}
};
pub const EnumTag = struct {
base: Node,
doc_comments: ?*DocComment,
name_token: TokenIndex,
value: ?*Node,
pub fn iterate(self: *EnumTag, index: usize) ?*Node {
var i = index;
if (self.value) |value| {
if (i < 1) return value;
i -= 1;
}
return null;
}
pub fn firstToken(self: *const EnumTag) TokenIndex {
return self.name_token;
}
pub fn lastToken(self: *const EnumTag) TokenIndex {
if (self.value) |value| {
return value.lastToken();
}
return self.name_token;
}
};
pub const ErrorTag = struct {
base: Node,
doc_comments: ?*DocComment,
@ -1307,7 +1341,7 @@ pub const Node = struct {
inline_token: ?TokenIndex,
for_token: TokenIndex,
array_expr: *Node,
payload: ?*Node,
payload: *Node,
body: *Node,
@"else": ?*Else,
@ -1317,10 +1351,8 @@ pub const Node = struct {
if (i < 1) return self.array_expr;
i -= 1;
if (self.payload) |payload| {
if (i < 1) return payload;
i -= 1;
}
if (i < 1) return self.payload;
i -= 1;
if (i < 1) return self.body;
i -= 1;
@ -2112,7 +2144,7 @@ pub const Node = struct {
pub const OutputList = SegmentedList(*AsmOutput, 2);
pub const InputList = SegmentedList(*AsmInput, 2);
pub const ClobberList = SegmentedList(TokenIndex, 2);
pub const ClobberList = SegmentedList(*Node, 2);
pub fn iterate(self: *Asm, index: usize) ?*Node {
var i = index;

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,21 @@ test "zig fmt: enum literal" {
);
}
test "zig fmt: enum literal inside array literal" {
try testCanonical(
\\test "enums in arrays" {
\\ var colors = []Color{.Green};
\\ colors = []Colors{ .Green, .Cyan };
\\ colors = []Colors{
\\ .Grey,
\\ .Green,
\\ .Cyan,
\\ };
\\}
\\
);
}
test "zig fmt: character literal larger than u8" {
try testCanonical(
\\const x = '\U01f4a9';
@ -1434,7 +1449,7 @@ test "zig fmt: precedence" {
test "zig fmt: prefix operators" {
try testCanonical(
\\test "prefix operators" {
\\ try return --%~!*&0;
\\ try return --%~!&0;
\\}
\\
);
@ -1462,8 +1477,6 @@ test "zig fmt: var args" {
test "zig fmt: var type" {
try testCanonical(
\\fn print(args: var) var {}
\\const Var = var;
\\const i: var = 0;
\\
);
}
@ -1827,15 +1840,6 @@ test "zig fmt: while" {
test "zig fmt: for" {
try testCanonical(
\\test "for" {
\\ for (a) continue;
\\
\\ for (a)
\\ continue;
\\
\\ for (a) {
\\ continue;
\\ }
\\
\\ for (a) |v| {
\\ continue;
\\ }

View File

@ -189,61 +189,31 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i
try renderExpression(allocator, stream, tree, indent, start_col, test_decl.body_node, Space.Newline);
},
ast.Node.Id.StructField => {
const field = @fieldParentPtr(ast.Node.StructField, "base", decl);
ast.Node.Id.ContainerField => {
const field = @fieldParentPtr(ast.Node.ContainerField, "base", decl);
try renderDocComments(tree, stream, field, indent, start_col);
if (field.visib_token) |visib_token| {
try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub
}
try renderToken(tree, stream, field.name_token, indent, start_col, Space.None); // name
try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // :
try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr, Space.Comma); // type,
},
ast.Node.Id.UnionTag => {
const tag = @fieldParentPtr(ast.Node.UnionTag, "base", decl);
try renderDocComments(tree, stream, tag, indent, start_col);
if (tag.type_expr == null and tag.value_expr == null) {
return renderToken(tree, stream, tag.name_token, indent, start_col, Space.Comma); // name,
}
if (tag.type_expr == null) {
try renderToken(tree, stream, tag.name_token, indent, start_col, Space.Space); // name
if (field.type_expr == null and field.value_expr == null) {
return renderToken(tree, stream, field.name_token, indent, start_col, Space.Comma); // name,
} else if (field.type_expr != null and field.value_expr == null) {
try renderToken(tree, stream, field.name_token, indent, start_col, Space.None); // name
try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // :
return renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, Space.Comma); // type,
} else if (field.type_expr == null and field.value_expr != null) {
try renderToken(tree, stream, field.name_token, indent, start_col, Space.Space); // name
try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // =
return renderExpression(allocator, stream, tree, indent, start_col, field.value_expr.?, Space.Comma); // value
} else {
try renderToken(tree, stream, tag.name_token, indent, start_col, Space.None); // name
}
if (tag.type_expr) |type_expr| {
try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, start_col, Space.Space); // :
if (tag.value_expr == null) {
try renderExpression(allocator, stream, tree, indent, start_col, type_expr, Space.Comma); // type,
return;
} else {
try renderExpression(allocator, stream, tree, indent, start_col, type_expr, Space.Space); // type
}
}
const value_expr = tag.value_expr.?;
try renderToken(tree, stream, tree.prevToken(value_expr.firstToken()), indent, start_col, Space.Space); // =
try renderExpression(allocator, stream, tree, indent, start_col, value_expr, Space.Comma); // value,
},
ast.Node.Id.EnumTag => {
const tag = @fieldParentPtr(ast.Node.EnumTag, "base", decl);
try renderDocComments(tree, stream, tag, indent, start_col);
if (tag.value) |value| {
try renderToken(tree, stream, tag.name_token, indent, start_col, Space.Space); // name
try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, start_col, Space.Space); // =
try renderExpression(allocator, stream, tree, indent, start_col, value, Space.Comma);
} else {
try renderToken(tree, stream, tag.name_token, indent, start_col, Space.Comma); // name
try renderToken(tree, stream, field.name_token, indent, start_col, Space.None); // name
try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // :
try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, Space.Space); // type
try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // =
return renderExpression(allocator, stream, tree, indent, start_col, field.value_expr.?, Space.Comma); // value,
}
},
@ -1436,18 +1406,14 @@ fn renderExpression(
const rparen = tree.nextToken(for_node.array_expr.lastToken());
const has_payload = for_node.payload != null;
const body_is_block = for_node.body.id == ast.Node.Id.Block;
const src_one_line_to_body = !body_is_block and tree.tokensOnSameLine(rparen, for_node.body.firstToken());
const body_on_same_line = body_is_block or src_one_line_to_body;
const space_after_rparen = if (has_payload or body_on_same_line) Space.Space else Space.Newline;
try renderToken(tree, stream, rparen, indent, start_col, space_after_rparen); // )
try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // )
if (for_node.payload) |payload| {
const space_after_payload = if (body_on_same_line) Space.Space else Space.Newline;
try renderExpression(allocator, stream, tree, indent, start_col, payload, space_after_payload); // |x|
}
const space_after_payload = if (body_on_same_line) Space.Space else Space.Newline;
try renderExpression(allocator, stream, tree, indent, start_col, for_node.payload, space_after_payload); // |x|
const space_after_body = blk: {
if (for_node.@"else") |@"else"| {
@ -1668,15 +1634,15 @@ fn renderExpression(
var it = asm_node.clobbers.iterator(0);
while (true) {
const clobber_token = it.next().?;
const clobber_node = it.next().?.*;
if (it.peek() == null) {
try renderToken(tree, stream, clobber_token.*, indent_once, start_col, Space.Newline);
try renderExpression(allocator, stream, tree, indent_extra, start_col, clobber_node, Space.Newline);
try stream.writeByteNTimes(' ', indent);
return renderToken(tree, stream, asm_node.rparen, indent, start_col, space);
} else {
try renderToken(tree, stream, clobber_token.*, indent_once, start_col, Space.None);
const comma = tree.nextToken(clobber_token.*);
try renderExpression(allocator, stream, tree, indent_extra, start_col, clobber_node, Space.None);
const comma = tree.nextToken(clobber_node.lastToken());
try renderToken(tree, stream, comma, indent_once, start_col, Space.Space); // ,
}
}
@ -1723,9 +1689,7 @@ fn renderExpression(
return renderToken(tree, stream, enum_literal.name, indent, start_col, space); // name
},
ast.Node.Id.StructField,
ast.Node.Id.UnionTag,
ast.Node.Id.EnumTag,
ast.Node.Id.ContainerField,
ast.Node.Id.Root,
ast.Node.Id.VarDecl,
ast.Node.Id.Use,

View File

@ -27,4 +27,28 @@ pub fn addCases(ctx: *TestContext) !void {
\\ return 36893488147419103232;
\\}
, "1.zig", 2, 12, "integer value '36893488147419103232' cannot be stored in type 'c_int'");
try ctx.testCompileError(
\\comptime {
\\ var a: *align(4) align(4) i32 = 0;
\\}
, "1.zig", 2, 22, "Extra align qualifier");
try ctx.testCompileError(
\\comptime {
\\ var b: *const const i32 = 0;
\\}
, "1.zig", 2, 19, "Extra align qualifier");
try ctx.testCompileError(
\\comptime {
\\ var c: *volatile volatile i32 = 0;
\\}
, "1.zig", 2, 22, "Extra align qualifier");
try ctx.testCompileError(
\\comptime {
\\ var d: *allowzero allowzero i32 = 0;
\\}
, "1.zig", 2, 23, "Extra align qualifier");
}