Recursive rewrite of stage2 parser, part 3

This commit is contained in:
hryx 2019-05-12 02:01:45 -07:00
parent 3787f34286
commit 3a3a738478
No known key found for this signature in database
GPG Key ID: 6A2784E15D7D95D6
6 changed files with 3115 additions and 3772 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,6 +113,7 @@ pub const Tree = struct {
pub const Error = union(enum) {
InvalidToken: InvalidToken,
ExpectedContainerMembers: ExpectedContainerMembers,
ExpectedStringLiteral: ExpectedStringLiteral,
ExpectedIntegerLiteral: ExpectedIntegerLiteral,
ExpectedPubItem: ExpectedPubItem,
@ -140,22 +141,27 @@ pub const Error = union(enum) {
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, // TODO: lame
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),
@ -183,17 +189,21 @@ pub const Error = union(enum) {
@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),
}
}
@ -201,6 +211,7 @@ 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,
@ -228,21 +239,26 @@ pub const Error = union(enum) {
@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 {}");
@ -262,16 +278,20 @@ pub const Error = union(enum) {
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 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");
@ -401,9 +421,7 @@ pub const Node = struct {
Payload,
PointerPayload,
PointerIndexPayload,
StructField,
UnionTag,
EnumTag,
ContainerField,
ErrorTag,
AsmInput,
AsmOutput,
@ -467,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,
@ -730,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| {
@ -779,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();
}
@ -795,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,
@ -1379,7 +1341,7 @@ pub const Node = struct {
inline_token: ?TokenIndex,
for_token: TokenIndex,
array_expr: *Node,
payload: ?*Node,
payload: *Node,
body: *Node,
@"else": ?*Else,
@ -1389,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;
@ -2184,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");
}