Commit 820de1716b
Changed files (2)
std
std/zig/ast.zig
@@ -20,6 +20,8 @@ pub const Node = struct {
FnProto,
ParamDecl,
Block,
+ Switch,
+ SwitchCase,
InfixOp,
PrefixOp,
SuffixOp,
@@ -55,6 +57,8 @@ pub const Node = struct {
Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).iterate(index),
Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).iterate(index),
Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),
+ Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).iterate(index),
+ Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).iterate(index),
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).iterate(index),
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).iterate(index),
Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).iterate(index),
@@ -91,6 +95,8 @@ pub const Node = struct {
Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).firstToken(),
Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).firstToken(),
Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(),
+ Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).firstToken(),
+ Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).firstToken(),
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).firstToken(),
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).firstToken(),
Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).firstToken(),
@@ -127,6 +133,8 @@ pub const Node = struct {
Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).lastToken(),
Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).lastToken(),
Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(),
+ Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).lastToken(),
+ Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).lastToken(),
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).lastToken(),
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).lastToken(),
Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).lastToken(),
@@ -506,9 +514,10 @@ pub const NodeParamDecl = struct {
pub const NodeBlock = struct {
base: Node,
- begin_token: Token,
- end_token: Token,
+ label: ?Token,
+ lbrace: Token,
statements: ArrayList(&Node),
+ rbrace: Token,
pub fn iterate(self: &NodeBlock, index: usize) ?&Node {
var i = index;
@@ -520,11 +529,80 @@ pub const NodeBlock = struct {
}
pub fn firstToken(self: &NodeBlock) Token {
- return self.begin_token;
+ if (self.label) |label| {
+ return label;
+ }
+
+ return self.lbrace;
}
pub fn lastToken(self: &NodeBlock) Token {
- return self.end_token;
+ return self.rbrace;
+ }
+};
+
+pub const NodeSwitch = struct {
+ base: Node,
+ switch_token: Token,
+ expr: &Node,
+ cases: ArrayList(&NodeSwitchCase),
+ rbrace: Token,
+
+ pub fn iterate(self: &NodeSwitch, index: usize) ?&Node {
+ var i = index;
+
+ if (i < 1) return self.expr;
+ i -= 1;
+
+ if (i < self.cases.len) return self.cases.at(i);
+ i -= self.cases.len;
+
+ return null;
+ }
+
+ pub fn firstToken(self: &NodeSwitch) Token {
+ return self.switch_token;
+ }
+
+ pub fn lastToken(self: &NodeSwitch) Token {
+ return self.rbrace;
+ }
+};
+
+pub const NodeSwitchCase = struct {
+ base: Node,
+ items: ArrayList(&Node),
+ capture: ?Capture,
+ expr: &Node,
+
+ const Capture = struct {
+ symbol: &NodeIdentifier,
+ is_ptr: bool,
+ };
+
+ pub fn iterate(self: &NodeSwitchCase, index: usize) ?&Node {
+ var i = index;
+
+ if (i < self.items.len) return self.items.at(i);
+ i -= self.items.len;
+
+ if (self.capture) |capture| {
+ if (i < 1) return &capture.base;
+ i -= 1;
+ }
+
+ if (i < 1) return self.expr;
+ i -= 1;
+
+ return null;
+ }
+
+ pub fn firstToken(self: &NodeSwitchCase) Token {
+ return self.items.at(0).firstToken();
+ }
+
+ pub fn lastToken(self: &NodeSwitchCase) Token {
+ return self.expr.lastToken();
}
};
@@ -575,6 +653,7 @@ pub const NodeInfixOp = struct {
Mult,
MultWrap,
Period,
+ Range,
Sub,
SubWrap,
UnwrapMaybe,
@@ -625,6 +704,7 @@ pub const NodeInfixOp = struct {
InfixOp.Mult,
InfixOp.MultWrap,
InfixOp.Period,
+ InfixOp.Range,
InfixOp.Sub,
InfixOp.SubWrap,
InfixOp.UnwrapMaybe => {},
std/zig/parser.zig
@@ -146,6 +146,8 @@ pub const Parser = struct {
Required,
Expression: DestPtr,
+ RangeExpressionBegin: DestPtr,
+ RangeExpressionEnd: DestPtr,
AssignmentExpressionBegin: DestPtr,
AssignmentExpressionEnd: DestPtr,
UnwrapExpressionBegin: DestPtr,
@@ -256,7 +258,7 @@ pub const Parser = struct {
}
const name = try self.createStringLiteral(arena, name_token);
- const block = try self.createBlock(arena, token);
+ const block = try self.createBlock(arena, (?Token)(null), token);
const test_decl = try self.createAttachTestDecl(arena, &root_node.decls, token, &name.base, block);
stack.append(State { .Block = block }) catch unreachable;
continue;
@@ -643,6 +645,27 @@ pub const Parser = struct {
}
},
+ State.RangeExpressionBegin => |dest_ptr| {
+ stack.append(State { .RangeExpressionEnd = dest_ptr }) catch unreachable;
+ try stack.append(State { .Expression = dest_ptr });
+ continue;
+ },
+
+ State.RangeExpressionEnd => |dest_ptr| {
+ const token = self.getNextToken();
+ if (token.id == Token.Id.Ellipsis3) {
+ const node = try self.createInfixOp(arena, token, ast.NodeInfixOp.InfixOp.Range);
+ node.lhs = dest_ptr.get();
+ dest_ptr.store(&node.base);
+
+ stack.append(State { .Expression = DestPtr { .Field = &node.rhs } }) catch unreachable;
+ continue;
+ } else {
+ self.putBackToken(token);
+ continue;
+ }
+ },
+
State.AssignmentExpressionBegin => |dest_ptr| {
stack.append(State { .AssignmentExpressionEnd = dest_ptr }) catch unreachable;
try stack.append(State { .UnwrapExpressionBegin = dest_ptr });
@@ -1205,10 +1228,6 @@ pub const Parser = struct {
try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });
continue;
},
- Token.Id.Identifier => {
- dest_ptr.store(&(try self.createIdentifier(arena, token)).base);
- continue;
- },
Token.Id.Builtin => {
const node = try arena.create(ast.NodeBuiltinCall);
*node = ast.NodeBuiltinCall {
@@ -1348,8 +1367,32 @@ pub const Parser = struct {
},
}) catch unreachable;
},
+ Token.Id.Identifier => {
+ const next = self.getNextToken();
+ if (next.id != Token.Id.Colon) {
+ self.putBackToken(next);
+ dest_ptr.store(&(try self.createIdentifier(arena, token)).base);
+ continue;
+ }
+
+ const block = try self.createBlock(arena, (?Token)(token), Token(undefined));
+ dest_ptr.store(&block.base);
+
+ stack.append(State { .Block = block }) catch unreachable;
+ try stack.append(State {
+ .ExpectTokenSave = ExpectTokenSave {
+ .id = Token.Id.LBrace,
+ .ptr = &block.lbrace,
+ }
+ });
+ continue;
+ },
Token.Id.LBrace => {
- @panic("TODO: Block expr");
+ const block = try self.createBlock(arena, (?Token)(null), token);
+ dest_ptr.store(&block.base);
+
+ stack.append(State { .Block = block }) catch unreachable;
+ continue;
},
Token.Id.Keyword_fn => {
@panic("TODO: fn proto");
@@ -1618,7 +1661,7 @@ pub const Parser = struct {
const token = self.getNextToken();
switch(token.id) {
Token.Id.LBrace => {
- const block = try self.createBlock(arena, token);
+ const block = try self.createBlock(arena, (?Token)(null), token);
fn_proto.body_node = &block.base;
stack.append(State { .Block = block }) catch unreachable;
continue;
@@ -1635,7 +1678,7 @@ pub const Parser = struct {
const token = self.getNextToken();
switch (token.id) {
Token.Id.RBrace => {
- block.end_token = token;
+ block.rbrace = token;
continue;
},
else => {
@@ -1648,38 +1691,64 @@ pub const Parser = struct {
},
State.Statement => |block| {
- {
- // Look for comptime var, comptime const
- const comptime_token = self.getNextToken();
- if (comptime_token.id == Token.Id.Keyword_comptime) {
+ const next = self.getNextToken();
+ switch (next.id) {
+ Token.Id.Keyword_comptime => {
const mut_token = self.getNextToken();
if (mut_token.id == Token.Id.Keyword_var or mut_token.id == Token.Id.Keyword_const) {
// TODO shouldn't need these casts
const var_decl = try self.createAttachVarDecl(arena, &block.statements, (?Token)(null),
- mut_token, (?Token)(comptime_token), (?Token)(null), null);
+ mut_token, (?Token)(next), (?Token)(null), null);
stack.append(State { .VarDecl = var_decl }) catch unreachable;
continue;
+ } else {
+ self.putBackToken(mut_token);
+ @panic("TODO: comptime block");
}
- self.putBackToken(mut_token);
- }
- self.putBackToken(comptime_token);
- }
- {
- // Look for const, var
- const mut_token = self.getNextToken();
- if (mut_token.id == Token.Id.Keyword_var or mut_token.id == Token.Id.Keyword_const) {
- // TODO shouldn't need these casts
+ },
+ Token.Id.Keyword_var, Token.Id.Keyword_const => {
const var_decl = try self.createAttachVarDecl(arena, &block.statements, (?Token)(null),
- mut_token, (?Token)(null), (?Token)(null), null);
+ next, (?Token)(null), (?Token)(null), null);
stack.append(State { .VarDecl = var_decl }) catch unreachable;
continue;
+ },
+ Token.Id.Identifier => {
+ const maybe_colon = self.getNextToken();
+ if (maybe_colon.id != Token.Id.Colon) {
+ self.putBackToken(maybe_colon);
+ self.putBackToken(next);
+ stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable;
+ try stack.append(State { .Expression = DestPtr{.Field = try block.statements.addOne() } });
+ continue;
+ }
+
+ const inner_block = try self.createBlock(arena, (?Token)(next), Token(undefined));
+ try block.statements.append(&inner_block.base);
+
+ stack.append(State { .Block = inner_block }) catch unreachable;
+ try stack.append(State {
+ .ExpectTokenSave = ExpectTokenSave {
+ .id = Token.Id.LBrace,
+ .ptr = &inner_block.lbrace,
+ }
+ });
+ continue;
+ },
+ Token.Id.LBrace => {
+ const inner_block = try self.createBlock(arena, (?Token)(null), next);
+ try block.statements.append(&inner_block.base);
+
+ stack.append(State { .Block = inner_block }) catch unreachable;
+ continue;
+ },
+ else => {
+ self.putBackToken(next);
+ stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable;
+ try stack.append(State { .Expression = DestPtr{.Field = try block.statements.addOne() } });
+ continue;
}
- self.putBackToken(mut_token);
}
- stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable;
- try stack.append(State { .Expression = DestPtr{.Field = try block.statements.addOne() } });
- continue;
},
}
}
@@ -1905,14 +1974,15 @@ pub const Parser = struct {
return node;
}
- fn createBlock(self: &Parser, arena: &mem.Allocator, begin_token: &const Token) !&ast.NodeBlock {
+ fn createBlock(self: &Parser, arena: &mem.Allocator, label: &const ?Token, lbrace: &const Token) !&ast.NodeBlock {
const node = try arena.create(ast.NodeBlock);
*node = ast.NodeBlock {
.base = self.initNode(ast.Node.Id.Block),
- .begin_token = *begin_token,
- .end_token = undefined,
+ .label = *label,
+ .lbrace = *lbrace,
.statements = ArrayList(&ast.Node).init(arena),
+ .rbrace = undefined,
};
return node;
}
@@ -2340,6 +2410,10 @@ pub const Parser = struct {
},
ast.Node.Id.Block => {
const block = @fieldParentPtr(ast.NodeBlock, "base", base);
+ if (block.label) |label| {
+ try stream.print("{}: ", self.tokenizer.getTokenSlice(label));
+ }
+
if (block.statements.len == 0) {
try stream.write("{}");
} else {
@@ -2747,6 +2821,8 @@ pub const Parser = struct {
},
ast.Node.Id.FnProto => @panic("TODO fn proto in an expression"),
ast.Node.Id.LineComment => @panic("TODO render line comment in an expression"),
+ ast.Node.Id.Switch => @panic("TODO switch"),
+ ast.Node.Id.SwitchCase => @panic("TODO switch case"),
ast.Node.Id.StructField,
ast.Node.Id.UnionTag,
@@ -2791,6 +2867,9 @@ pub const Parser = struct {
const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", base);
try stack.append(RenderState { .VarDecl = var_decl});
},
+ ast.Node.Id.Block => {
+ try stack.append(RenderState { .Expression = base});
+ },
else => {
try stack.append(RenderState { .Text = ";"});
try stack.append(RenderState { .Expression = base});
@@ -3323,6 +3402,28 @@ test "zig fmt: catch" {
);
}
+test "zig fmt: blocks" {
+ try testCanonical(
+ \\test "blocks" {
+ \\ {
+ \\ const a = 0;
+ \\ const b = 0;
+ \\ }
+ \\
+ \\ blk: {
+ \\ const a = 0;
+ \\ const b = 0;
+ \\ }
+ \\
+ \\ const r = blk: {
+ \\ const a = 0;
+ \\ const b = 0;
+ \\ };
+ \\}
+ \\
+ );
+}
+
test "zig fmt: switch" {
try testCanonical(
\\test "switch" {