Skip to content

Commit

Permalink
zig fmt: support aligned ptr with bit fields
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewrk committed May 25, 2018
1 parent b74dda3 commit e6afea9
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 24 deletions.
22 changes: 17 additions & 5 deletions std/zig/ast.zig
Expand Up @@ -98,6 +98,7 @@ pub const Error = union(enum) {
UnattachedDocComment: UnattachedDocComment,
ExpectedEqOrSemi: ExpectedEqOrSemi,
ExpectedSemiOrLBrace: ExpectedSemiOrLBrace,
ExpectedColonOrRParen: ExpectedColonOrRParen,
ExpectedLabelable: ExpectedLabelable,
ExpectedInlinable: ExpectedInlinable,
ExpectedAsmOutputReturnOrType: ExpectedAsmOutputReturnOrType,
Expand All @@ -120,6 +121,7 @@ pub const Error = union(enum) {
@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).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),
@TagType(Error).ExpectedAsmOutputReturnOrType => |*x| return x.render(tokens, stream),
Expand All @@ -144,6 +146,7 @@ pub const Error = union(enum) {
@TagType(Error).UnattachedDocComment => |x| return x.token,
@TagType(Error).ExpectedEqOrSemi => |x| return x.token,
@TagType(Error).ExpectedSemiOrLBrace => |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,
@TagType(Error).ExpectedAsmOutputReturnOrType => |x| return x.token,
Expand All @@ -164,6 +167,7 @@ pub const Error = union(enum) {
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 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 {}");
Expand Down Expand Up @@ -1487,7 +1491,7 @@ pub const Node = struct {
op: Op,
rhs: &Node,

const Op = union(enum) {
pub const Op = union(enum) {
AddrOf: AddrOfInfo,
ArrayType: &Node,
Await,
Expand All @@ -1504,12 +1508,20 @@ pub const Node = struct {
UnwrapMaybe,
};

const AddrOfInfo = struct {
align_expr: ?&Node,
bit_offset_start_token: ?TokenIndex,
bit_offset_end_token: ?TokenIndex,
pub const AddrOfInfo = struct {
align_info: ?Align,
const_token: ?TokenIndex,
volatile_token: ?TokenIndex,

pub const Align = struct {
node: &Node,
bit_range: ?BitRange,

pub const BitRange = struct {
start: &Node,
end: &Node,
};
};
};

pub fn iterate(self: &PrefixOp, index: usize) ?&Node {
Expand Down
48 changes: 39 additions & 9 deletions std/zig/parse.zig
Expand Up @@ -1450,9 +1450,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
State.SliceOrArrayType => |node| {
if (eatToken(&tok_it, &tree, Token.Id.RBracket)) |_| {
node.op = ast.Node.PrefixOp.Op{ .SliceType = ast.Node.PrefixOp.AddrOfInfo{
.align_expr = null,
.bit_offset_start_token = null,
.bit_offset_end_token = null,
.align_info = null,
.const_token = null,
.volatile_token = null,
} };
Expand All @@ -1467,19 +1465,27 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.op.ArrayType } });
continue;
},

State.AddrOfModifiers => |addr_of_info| {
const token = nextToken(&tok_it, &tree);
const token_index = token.index;
const token_ptr = token.ptr;
switch (token_ptr.id) {
Token.Id.Keyword_align => {
stack.append(state) catch unreachable;
if (addr_of_info.align_expr != null) {
if (addr_of_info.align_info != null) {
((try tree.errors.addOne())).* = Error{ .ExtraAlignQualifier = Error.ExtraAlignQualifier{ .token = token_index } };
return tree;
}
try stack.append(State{ .ExpectToken = Token.Id.RParen });
try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &addr_of_info.align_expr } });
addr_of_info.align_info = ast.Node.PrefixOp.AddrOfInfo.Align {
.node = undefined,
.bit_range = null,
};
// TODO https://github.com/ziglang/zig/issues/1022
const align_info = &??addr_of_info.align_info;

try stack.append(State{ .AlignBitRange = align_info });
try stack.append(State{ .Expression = OptionalCtx{ .Required = &align_info.node } });
try stack.append(State{ .ExpectToken = Token.Id.LParen });
continue;
},
Expand Down Expand Up @@ -1508,6 +1514,31 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
}
},

State.AlignBitRange => |align_info| {
const token = nextToken(&tok_it, &tree);
switch (token.ptr.id) {
Token.Id.Colon => {
align_info.bit_range = ast.Node.PrefixOp.AddrOfInfo.Align.BitRange(undefined);
const bit_range = &??align_info.bit_range;

try stack.append(State{ .ExpectToken = Token.Id.RParen });
try stack.append(State{ .Expression = OptionalCtx{ .Required = &bit_range.end } });
try stack.append(State{ .ExpectToken = Token.Id.Colon });
try stack.append(State{ .Expression = OptionalCtx{ .Required = &bit_range.start } });
continue;
},
Token.Id.RParen => continue,
else => {
(try tree.errors.addOne()).* = Error{
.ExpectedColonOrRParen = Error.ExpectedColonOrRParen{
.token = token.index,
}
};
return tree;
},
}
},

State.Payload => |opt_ctx| {
const token = nextToken(&tok_it, &tree);
const token_index = token.index;
Expand Down Expand Up @@ -2801,6 +2832,7 @@ const State = union(enum) {
SliceOrArrayAccess: &ast.Node.SuffixOp,
SliceOrArrayType: &ast.Node.PrefixOp,
AddrOfModifiers: &ast.Node.PrefixOp.AddrOfInfo,
AlignBitRange: &ast.Node.PrefixOp.AddrOfInfo.Align,

Payload: OptionalCtx,
PointerPayload: OptionalCtx,
Expand Down Expand Up @@ -3120,9 +3152,7 @@ fn tokenIdToPrefixOp(id: @TagType(Token.Id)) ?ast.Node.PrefixOp.Op {
Token.Id.Asterisk,
Token.Id.AsteriskAsterisk => ast.Node.PrefixOp.Op{ .PointerType = void{} },
Token.Id.Ampersand => ast.Node.PrefixOp.Op{ .AddrOf = ast.Node.PrefixOp.AddrOfInfo{
.align_expr = null,
.bit_offset_start_token = null,
.bit_offset_end_token = null,
.align_info = null,
.const_token = null,
.volatile_token = null,
} },
Expand Down
9 changes: 9 additions & 0 deletions std/zig/parser_test.zig
@@ -1,3 +1,12 @@
test "zig fmt: float literal with exponent" {
try testCanonical(
\\test "bit field alignment" {
\\ assert(@typeOf(&blah.b) == &align(1:3:6) const u3);
\\}
\\
);
}

test "zig fmt: float literal with exponent" {
try testCanonical(
\\test "aoeu" {
Expand Down
48 changes: 38 additions & 10 deletions std/zig/render.zig
Expand Up @@ -253,17 +253,30 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
switch (prefix_op_node.op) {
ast.Node.PrefixOp.Op.AddrOf => |addr_of_info| {
try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // &
if (addr_of_info.align_expr) |align_expr| {
if (addr_of_info.align_info) |align_info| {
const align_token = tree.nextToken(prefix_op_node.op_token);
try renderToken(tree, stream, align_token, indent, Space.None); // align

const lparen_token = tree.prevToken(align_expr.firstToken());
const lparen_token = tree.prevToken(align_info.node.firstToken());
try renderToken(tree, stream, lparen_token, indent, Space.None); // (

try renderExpression(allocator, stream, tree, indent, align_expr, Space.None);
try renderExpression(allocator, stream, tree, indent, align_info.node, Space.None);

const rparen_token = tree.nextToken(align_expr.lastToken());
try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
if (align_info.bit_range) |bit_range| {
const colon1 = tree.prevToken(bit_range.start.firstToken());
const colon2 = tree.prevToken(bit_range.end.firstToken());

try renderToken(tree, stream, colon1, indent, Space.None); // :
try renderExpression(allocator, stream, tree, indent, bit_range.start, Space.None);
try renderToken(tree, stream, colon2, indent, Space.None); // :
try renderExpression(allocator, stream, tree, indent, bit_range.end, Space.None);

const rparen_token = tree.nextToken(bit_range.end.lastToken());
try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
} else {
const rparen_token = tree.nextToken(align_info.node.lastToken());
try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
}
}
if (addr_of_info.const_token) |const_token| {
try renderToken(tree, stream, const_token, indent, Space.Space); // const
Expand All @@ -272,21 +285,35 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
try renderToken(tree, stream, volatile_token, indent, Space.Space); // volatile
}
},

ast.Node.PrefixOp.Op.SliceType => |addr_of_info| {
try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [
try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, Space.None); // ]

if (addr_of_info.align_expr) |align_expr| {
if (addr_of_info.align_info) |align_info| {
const align_token = tree.nextToken(prefix_op_node.op_token);
try renderToken(tree, stream, align_token, indent, Space.None); // align

const lparen_token = tree.prevToken(align_expr.firstToken());
const lparen_token = tree.prevToken(align_info.node.firstToken());
try renderToken(tree, stream, lparen_token, indent, Space.None); // (

try renderExpression(allocator, stream, tree, indent, align_expr, Space.None);
try renderExpression(allocator, stream, tree, indent, align_info.node, Space.None);

const rparen_token = tree.nextToken(align_expr.lastToken());
try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
if (align_info.bit_range) |bit_range| {
const colon1 = tree.prevToken(bit_range.start.firstToken());
const colon2 = tree.prevToken(bit_range.end.firstToken());

try renderToken(tree, stream, colon1, indent, Space.None); // :
try renderExpression(allocator, stream, tree, indent, bit_range.start, Space.None);
try renderToken(tree, stream, colon2, indent, Space.None); // :
try renderExpression(allocator, stream, tree, indent, bit_range.end, Space.None);

const rparen_token = tree.nextToken(bit_range.end.lastToken());
try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
} else {
const rparen_token = tree.nextToken(align_info.node.lastToken());
try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
}
}
if (addr_of_info.const_token) |const_token| {
try renderToken(tree, stream, const_token, indent, Space.Space);
Expand All @@ -295,6 +322,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
try renderToken(tree, stream, volatile_token, indent, Space.Space);
}
},

ast.Node.PrefixOp.Op.ArrayType => |array_index| {
try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [
try renderExpression(allocator, stream, tree, indent, array_index, Space.None);
Expand Down

0 comments on commit e6afea9

Please sign in to comment.