std.zig.parser now parses switch
parent
820de1716b
commit
bdff5bfa3e
|
@ -22,6 +22,7 @@ pub const Node = struct {
|
||||||
Block,
|
Block,
|
||||||
Switch,
|
Switch,
|
||||||
SwitchCase,
|
SwitchCase,
|
||||||
|
SwitchElse,
|
||||||
InfixOp,
|
InfixOp,
|
||||||
PrefixOp,
|
PrefixOp,
|
||||||
SuffixOp,
|
SuffixOp,
|
||||||
|
@ -59,6 +60,7 @@ pub const Node = struct {
|
||||||
Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),
|
Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),
|
||||||
Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).iterate(index),
|
Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).iterate(index),
|
||||||
Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).iterate(index),
|
Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).iterate(index),
|
||||||
|
Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).iterate(index),
|
||||||
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).iterate(index),
|
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).iterate(index),
|
||||||
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).iterate(index),
|
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).iterate(index),
|
||||||
Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).iterate(index),
|
Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).iterate(index),
|
||||||
|
@ -97,6 +99,7 @@ pub const Node = struct {
|
||||||
Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(),
|
Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(),
|
||||||
Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).firstToken(),
|
Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).firstToken(),
|
||||||
Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).firstToken(),
|
Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).firstToken(),
|
||||||
|
Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).firstToken(),
|
||||||
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).firstToken(),
|
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).firstToken(),
|
||||||
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).firstToken(),
|
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).firstToken(),
|
||||||
Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).firstToken(),
|
Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).firstToken(),
|
||||||
|
@ -135,6 +138,7 @@ pub const Node = struct {
|
||||||
Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(),
|
Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(),
|
||||||
Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).lastToken(),
|
Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).lastToken(),
|
||||||
Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).lastToken(),
|
Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).lastToken(),
|
||||||
|
Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).firstToken(),
|
||||||
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).lastToken(),
|
Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).lastToken(),
|
||||||
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).lastToken(),
|
Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).lastToken(),
|
||||||
Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).lastToken(),
|
Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).lastToken(),
|
||||||
|
@ -606,6 +610,23 @@ pub const NodeSwitchCase = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const NodeSwitchElse = struct {
|
||||||
|
base: Node,
|
||||||
|
token: Token,
|
||||||
|
|
||||||
|
pub fn iterate(self: &NodeSwitchElse, index: usize) ?&Node {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn firstToken(self: &NodeSwitchElse) Token {
|
||||||
|
return self.token;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lastToken(self: &NodeSwitchElse) Token {
|
||||||
|
return self.token;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
pub const NodeInfixOp = struct {
|
pub const NodeInfixOp = struct {
|
||||||
base: Node,
|
base: Node,
|
||||||
op_token: Token,
|
op_token: Token,
|
||||||
|
|
|
@ -98,10 +98,15 @@ pub const Parser = struct {
|
||||||
ptr: &?&ast.Node,
|
ptr: &?&ast.Node,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn ListState(comptime T: type) type {
|
const ExprListCtx = struct {
|
||||||
|
list: &ArrayList(&ast.Node),
|
||||||
|
end: Token.Id,
|
||||||
|
ptr: &Token,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn ListSave(comptime T: type) type {
|
||||||
return struct {
|
return struct {
|
||||||
list: &ArrayList(T),
|
list: &ArrayList(T),
|
||||||
end: Token.Id,
|
|
||||||
ptr: &Token,
|
ptr: &Token,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -129,11 +134,16 @@ pub const Parser = struct {
|
||||||
FnDef: &ast.NodeFnProto,
|
FnDef: &ast.NodeFnProto,
|
||||||
Block: &ast.NodeBlock,
|
Block: &ast.NodeBlock,
|
||||||
Statement: &ast.NodeBlock,
|
Statement: &ast.NodeBlock,
|
||||||
ExprListItemOrEnd: ListState(&ast.Node),
|
ExprListItemOrEnd: ExprListCtx,
|
||||||
ExprListCommaOrEnd: ListState(&ast.Node),
|
ExprListCommaOrEnd: ExprListCtx,
|
||||||
FieldInitListItemOrEnd: ListState(&ast.NodeFieldInitializer),
|
FieldInitListItemOrEnd: ListSave(&ast.NodeFieldInitializer),
|
||||||
FieldInitListCommaOrEnd: ListState(&ast.NodeFieldInitializer),
|
FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer),
|
||||||
FieldListCommaOrEnd: &ast.NodeContainerDecl,
|
FieldListCommaOrEnd: &ast.NodeContainerDecl,
|
||||||
|
SwitchCaseOrEnd: ListSave(&ast.NodeSwitchCase),
|
||||||
|
SwitchCaseCapture: &?ast.NodeSwitchCase.Capture,
|
||||||
|
SwitchCaseCommaOrEnd: ListSave(&ast.NodeSwitchCase),
|
||||||
|
SwitchCaseItem: &ArrayList(&ast.Node),
|
||||||
|
SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node),
|
||||||
|
|
||||||
/// A state that can be appended before any other State. If an error occures,
|
/// A state that can be appended before any other State. If an error occures,
|
||||||
/// the parser will first try looking for the closest optional state. If an
|
/// the parser will first try looking for the closest optional state. If an
|
||||||
|
@ -245,17 +255,8 @@ pub const Parser = struct {
|
||||||
Token.Id.Keyword_test => {
|
Token.Id.Keyword_test => {
|
||||||
stack.append(State.TopLevel) catch unreachable;
|
stack.append(State.TopLevel) catch unreachable;
|
||||||
|
|
||||||
const name_token = self.getNextToken();
|
const name_token = (try self.eatToken(&stack, Token.Id.StringLiteral)) ?? continue;
|
||||||
if (name_token.id != Token.Id.StringLiteral) {
|
const lbrace = (try self.eatToken(&stack, Token.Id.LBrace)) ?? continue;
|
||||||
try self.parseError(&stack, token, "expected {}, found {}", @tagName(Token.Id.StringLiteral), @tagName(name_token.id));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const lbrace = self.getNextToken();
|
|
||||||
if (lbrace.id != Token.Id.LBrace) {
|
|
||||||
try self.parseError(&stack, token, "expected {}, found {}", @tagName(Token.Id.LBrace), @tagName(name_token.id));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const name = try self.createStringLiteral(arena, name_token);
|
const name = try self.createStringLiteral(arena, name_token);
|
||||||
const block = try self.createBlock(arena, (?Token)(null), token);
|
const block = try self.createBlock(arena, (?Token)(null), token);
|
||||||
|
@ -974,9 +975,8 @@ pub const Parser = struct {
|
||||||
|
|
||||||
stack.append(State { .CurlySuffixExpressionEnd = dest_ptr }) catch unreachable;
|
stack.append(State { .CurlySuffixExpressionEnd = dest_ptr }) catch unreachable;
|
||||||
try stack.append(State {
|
try stack.append(State {
|
||||||
.FieldInitListItemOrEnd = ListState(&ast.NodeFieldInitializer) {
|
.FieldInitListItemOrEnd = ListSave(&ast.NodeFieldInitializer) {
|
||||||
.list = &node.op.StructInitializer,
|
.list = &node.op.StructInitializer,
|
||||||
.end = Token.Id.RBrace,
|
|
||||||
.ptr = &node.rtoken,
|
.ptr = &node.rtoken,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -992,7 +992,7 @@ pub const Parser = struct {
|
||||||
|
|
||||||
stack.append(State { .CurlySuffixExpressionEnd = dest_ptr }) catch unreachable;
|
stack.append(State { .CurlySuffixExpressionEnd = dest_ptr }) catch unreachable;
|
||||||
try stack.append(State {
|
try stack.append(State {
|
||||||
.ExprListItemOrEnd = ListState(&ast.Node) {
|
.ExprListItemOrEnd = ExprListCtx {
|
||||||
.list = &node.op.ArrayInitializer,
|
.list = &node.op.ArrayInitializer,
|
||||||
.end = Token.Id.RBrace,
|
.end = Token.Id.RBrace,
|
||||||
.ptr = &node.rtoken,
|
.ptr = &node.rtoken,
|
||||||
|
@ -1084,7 +1084,7 @@ pub const Parser = struct {
|
||||||
|
|
||||||
stack.append(State { .SuffixOpExpressionEnd = dest_ptr }) catch unreachable;
|
stack.append(State { .SuffixOpExpressionEnd = dest_ptr }) catch unreachable;
|
||||||
try stack.append(State {
|
try stack.append(State {
|
||||||
.ExprListItemOrEnd = ListState(&ast.Node) {
|
.ExprListItemOrEnd = ExprListCtx {
|
||||||
.list = &node.op.Call.params,
|
.list = &node.op.Call.params,
|
||||||
.end = Token.Id.RParen,
|
.end = Token.Id.RParen,
|
||||||
.ptr = &node.rtoken,
|
.ptr = &node.rtoken,
|
||||||
|
@ -1238,7 +1238,7 @@ pub const Parser = struct {
|
||||||
};
|
};
|
||||||
dest_ptr.store(&node.base);
|
dest_ptr.store(&node.base);
|
||||||
stack.append(State {
|
stack.append(State {
|
||||||
.ExprListItemOrEnd = ListState(&ast.Node) {
|
.ExprListItemOrEnd = ExprListCtx {
|
||||||
.list = &node.params,
|
.list = &node.params,
|
||||||
.end = Token.Id.RParen,
|
.end = Token.Id.RParen,
|
||||||
.ptr = &node.rparen_token,
|
.ptr = &node.rparen_token,
|
||||||
|
@ -1400,6 +1400,43 @@ pub const Parser = struct {
|
||||||
Token.Id.Keyword_asm => {
|
Token.Id.Keyword_asm => {
|
||||||
@panic("TODO: inline asm");
|
@panic("TODO: inline asm");
|
||||||
},
|
},
|
||||||
|
Token.Id.Keyword_if => {
|
||||||
|
@panic("TODO: inline if");
|
||||||
|
},
|
||||||
|
Token.Id.Keyword_while => {
|
||||||
|
@panic("TODO: inline while");
|
||||||
|
},
|
||||||
|
Token.Id.Keyword_for => {
|
||||||
|
@panic("TODO: inline for");
|
||||||
|
},
|
||||||
|
Token.Id.Keyword_switch => {
|
||||||
|
const node = try arena.create(ast.NodeSwitch);
|
||||||
|
*node = ast.NodeSwitch {
|
||||||
|
.base = self.initNode(ast.Node.Id.Switch),
|
||||||
|
.switch_token = token,
|
||||||
|
.expr = undefined,
|
||||||
|
.cases = ArrayList(&ast.NodeSwitchCase).init(arena),
|
||||||
|
.rbrace = undefined,
|
||||||
|
};
|
||||||
|
dest_ptr.store(&node.base);
|
||||||
|
|
||||||
|
stack.append(State {
|
||||||
|
.SwitchCaseOrEnd = ListSave(&ast.NodeSwitchCase) {
|
||||||
|
.list = &node.cases,
|
||||||
|
.ptr = &node.rbrace,
|
||||||
|
},
|
||||||
|
}) catch unreachable;
|
||||||
|
try stack.append(State { .ExpectToken = Token.Id.LBrace });
|
||||||
|
try stack.append(State { .ExpectToken = Token.Id.RParen });
|
||||||
|
try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });
|
||||||
|
try stack.append(State { .ExpectToken = Token.Id.LParen });
|
||||||
|
},
|
||||||
|
Token.Id.Keyword_comptime => {
|
||||||
|
@panic("TODO: inline comptime");
|
||||||
|
},
|
||||||
|
Token.Id.Keyword_suspend => {
|
||||||
|
@panic("TODO: inline suspend");
|
||||||
|
},
|
||||||
else => {
|
else => {
|
||||||
try self.parseError(&stack, token, "expected primary expression, found {}", @tagName(token.id));
|
try self.parseError(&stack, token, "expected primary expression, found {}", @tagName(token.id));
|
||||||
continue;
|
continue;
|
||||||
|
@ -1463,8 +1500,7 @@ pub const Parser = struct {
|
||||||
State.FieldInitListItemOrEnd => |list_state| {
|
State.FieldInitListItemOrEnd => |list_state| {
|
||||||
var token = self.getNextToken();
|
var token = self.getNextToken();
|
||||||
|
|
||||||
const IdTag = @TagType(Token.Id);
|
if (token.id == Token.Id.RBrace){
|
||||||
if (IdTag(list_state.end) == token.id){
|
|
||||||
*list_state.ptr = token;
|
*list_state.ptr = token;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1497,13 +1533,82 @@ pub const Parser = struct {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
State.SwitchCaseOrEnd => |list_state| {
|
||||||
|
var token = self.getNextToken();
|
||||||
|
|
||||||
|
if (token.id == Token.Id.RBrace){
|
||||||
|
*list_state.ptr = token;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.putBackToken(token);
|
||||||
|
|
||||||
|
const node = try arena.create(ast.NodeSwitchCase);
|
||||||
|
*node = ast.NodeSwitchCase {
|
||||||
|
.base = self.initNode(ast.Node.Id.SwitchCase),
|
||||||
|
.items = ArrayList(&ast.Node).init(arena),
|
||||||
|
.capture = null,
|
||||||
|
.expr = undefined,
|
||||||
|
};
|
||||||
|
try list_state.list.append(node);
|
||||||
|
stack.append(State { .SwitchCaseCommaOrEnd = list_state }) catch unreachable;
|
||||||
|
try stack.append(State { .Expression = DestPtr{ .Field = &node.expr } });
|
||||||
|
try stack.append(State { .SwitchCaseCapture = &node.capture });
|
||||||
|
|
||||||
|
const maybe_else = self.getNextToken();
|
||||||
|
if (maybe_else.id == Token.Id.Keyword_else) {
|
||||||
|
const else_node = try arena.create(ast.NodeSwitchElse);
|
||||||
|
*else_node = ast.NodeSwitchElse {
|
||||||
|
.base = self.initNode(ast.Node.Id.SwitchElse),
|
||||||
|
.token = maybe_else,
|
||||||
|
};
|
||||||
|
try node.items.append(&else_node.base);
|
||||||
|
try stack.append(State { .ExpectToken = Token.Id.EqualAngleBracketRight });
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
self.putBackToken(maybe_else);
|
||||||
|
try stack.append(State { .SwitchCaseItem = &node.items });
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
State.SwitchCaseCapture => |capture| {
|
||||||
|
const token = self.getNextToken();
|
||||||
|
if (token.id != Token.Id.Pipe) {
|
||||||
|
self.putBackToken(token);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const is_ptr = blk: {
|
||||||
|
const asterik = self.getNextToken();
|
||||||
|
if (asterik.id == Token.Id.Asterisk) {
|
||||||
|
break :blk true;
|
||||||
|
} else {
|
||||||
|
self.putBackToken(asterik);
|
||||||
|
break :blk false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const ident = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
|
||||||
|
_ = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue;
|
||||||
|
*capture = ast.NodeSwitchCase.Capture {
|
||||||
|
.symbol = try self.createIdentifier(arena, ident),
|
||||||
|
.is_ptr = is_ptr
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
State.SwitchCaseItem => |case_items| {
|
||||||
|
stack.append(State { .SwitchCaseItemCommaOrEnd = case_items }) catch unreachable;
|
||||||
|
try stack.append(State { .RangeExpressionBegin = DestPtr{ .Field = try case_items.addOne() } });
|
||||||
|
},
|
||||||
|
|
||||||
State.ExprListCommaOrEnd => |list_state| {
|
State.ExprListCommaOrEnd => |list_state| {
|
||||||
try self.commaOrEnd(&stack, list_state.end, list_state.ptr, State { .ExprListItemOrEnd = list_state });
|
try self.commaOrEnd(&stack, list_state.end, list_state.ptr, State { .ExprListItemOrEnd = list_state });
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
|
|
||||||
State.FieldInitListCommaOrEnd => |list_state| {
|
State.FieldInitListCommaOrEnd => |list_state| {
|
||||||
try self.commaOrEnd(&stack, list_state.end, list_state.ptr, State { .FieldInitListItemOrEnd = list_state });
|
try self.commaOrEnd(&stack, Token.Id.RBrace, list_state.ptr, State { .FieldInitListItemOrEnd = list_state });
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1513,6 +1618,16 @@ pub const Parser = struct {
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
State.SwitchCaseCommaOrEnd => |list_state| {
|
||||||
|
try self.commaOrEnd(&stack, Token.Id.RBrace, list_state.ptr, State { .SwitchCaseOrEnd = list_state });
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
|
||||||
|
State.SwitchCaseItemCommaOrEnd => |case_items| {
|
||||||
|
try self.commaOrEnd(&stack, Token.Id.EqualAngleBracketRight, null, State { .SwitchCaseItem = case_items });
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
|
||||||
State.AddrOfModifiers => |addr_of_info| {
|
State.AddrOfModifiers => |addr_of_info| {
|
||||||
var token = self.getNextToken();
|
var token = self.getNextToken();
|
||||||
switch (token.id) {
|
switch (token.id) {
|
||||||
|
@ -1741,6 +1856,11 @@ pub const Parser = struct {
|
||||||
stack.append(State { .Block = inner_block }) catch unreachable;
|
stack.append(State { .Block = inner_block }) catch unreachable;
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
|
Token.Id.Keyword_switch => {
|
||||||
|
self.putBackToken(next);
|
||||||
|
stack.append(State { .Expression = DestPtr{.Field = try block.statements.addOne() } }) catch unreachable;
|
||||||
|
continue;
|
||||||
|
},
|
||||||
else => {
|
else => {
|
||||||
self.putBackToken(next);
|
self.putBackToken(next);
|
||||||
stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable;
|
stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable;
|
||||||
|
@ -1754,7 +1874,7 @@ pub const Parser = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn commaOrEnd(self: &Parser, stack: &ArrayList(State), end: &const Token.Id, ptr: &Token, state_after_comma: &const State) !void {
|
fn commaOrEnd(self: &Parser, stack: &ArrayList(State), end: &const Token.Id, maybe_ptr: ?&Token, state_after_comma: &const State) !void {
|
||||||
var token = self.getNextToken();
|
var token = self.getNextToken();
|
||||||
switch (token.id) {
|
switch (token.id) {
|
||||||
Token.Id.Comma => {
|
Token.Id.Comma => {
|
||||||
|
@ -1763,7 +1883,9 @@ pub const Parser = struct {
|
||||||
else => {
|
else => {
|
||||||
const IdTag = @TagType(Token.Id);
|
const IdTag = @TagType(Token.Id);
|
||||||
if (IdTag(*end) == token.id) {
|
if (IdTag(*end) == token.id) {
|
||||||
*ptr = token;
|
if (maybe_ptr) |ptr| {
|
||||||
|
*ptr = token;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2498,7 +2620,8 @@ pub const Parser = struct {
|
||||||
ast.NodeInfixOp.InfixOp.Sub => " - ",
|
ast.NodeInfixOp.InfixOp.Sub => " - ",
|
||||||
ast.NodeInfixOp.InfixOp.SubWrap => " -% ",
|
ast.NodeInfixOp.InfixOp.SubWrap => " -% ",
|
||||||
ast.NodeInfixOp.InfixOp.UnwrapMaybe => " ?? ",
|
ast.NodeInfixOp.InfixOp.UnwrapMaybe => " ?? ",
|
||||||
else => unreachable,
|
ast.NodeInfixOp.InfixOp.Range => " ... ",
|
||||||
|
ast.NodeInfixOp.InfixOp.Catch => unreachable,
|
||||||
};
|
};
|
||||||
|
|
||||||
try stack.append(RenderState { .Text = text });
|
try stack.append(RenderState { .Text = text });
|
||||||
|
@ -2821,8 +2944,73 @@ pub const Parser = struct {
|
||||||
},
|
},
|
||||||
ast.Node.Id.FnProto => @panic("TODO fn proto in an expression"),
|
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.LineComment => @panic("TODO render line comment in an expression"),
|
||||||
ast.Node.Id.Switch => @panic("TODO switch"),
|
ast.Node.Id.Switch => {
|
||||||
ast.Node.Id.SwitchCase => @panic("TODO switch case"),
|
const switch_node = @fieldParentPtr(ast.NodeSwitch, "base", base);
|
||||||
|
try stream.print("{} (", self.tokenizer.getTokenSlice(switch_node.switch_token));
|
||||||
|
|
||||||
|
try stack.append(RenderState { .Text = "}"});
|
||||||
|
try stack.append(RenderState.PrintIndent);
|
||||||
|
try stack.append(RenderState { .Indent = indent });
|
||||||
|
try stack.append(RenderState { .Text = "\n"});
|
||||||
|
|
||||||
|
const cases = switch_node.cases.toSliceConst();
|
||||||
|
var i = cases.len;
|
||||||
|
while (i != 0) {
|
||||||
|
i -= 1;
|
||||||
|
const node = cases[i];
|
||||||
|
try stack.append(RenderState { .Expression = &node.base});
|
||||||
|
try stack.append(RenderState.PrintIndent);
|
||||||
|
try stack.append(RenderState {
|
||||||
|
.Text = blk: {
|
||||||
|
if (i != 0) {
|
||||||
|
const prev_node = cases[i - 1];
|
||||||
|
const loc = self.tokenizer.getTokenLocation(prev_node.lastToken().end, node.firstToken());
|
||||||
|
if (loc.line >= 2) {
|
||||||
|
break :blk "\n\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break :blk "\n";
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (i != 0) {
|
||||||
|
try stack.append(RenderState { .Text = "," });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try stack.append(RenderState { .Indent = indent + indent_delta});
|
||||||
|
try stack.append(RenderState { .Text = ") {"});
|
||||||
|
try stack.append(RenderState { .Expression = switch_node.expr });
|
||||||
|
},
|
||||||
|
ast.Node.Id.SwitchCase => {
|
||||||
|
const switch_case = @fieldParentPtr(ast.NodeSwitchCase, "base", base);
|
||||||
|
|
||||||
|
try stack.append(RenderState { .Expression = switch_case.expr });
|
||||||
|
if (switch_case.capture) |capture| {
|
||||||
|
try stack.append(RenderState { .Text = "| "});
|
||||||
|
try stack.append(RenderState { .Expression = &capture.symbol.base });
|
||||||
|
|
||||||
|
if (capture.is_ptr) {
|
||||||
|
try stack.append(RenderState { .Text = "*"});
|
||||||
|
}
|
||||||
|
try stack.append(RenderState { .Text = "|"});
|
||||||
|
}
|
||||||
|
try stack.append(RenderState { .Text = " => "});
|
||||||
|
|
||||||
|
const items = switch_case.items.toSliceConst();
|
||||||
|
var i = items.len;
|
||||||
|
while (i != 0) {
|
||||||
|
i -= 1;
|
||||||
|
try stack.append(RenderState { .Expression = items[i] });
|
||||||
|
|
||||||
|
if (i != 0) {
|
||||||
|
try stack.append(RenderState { .Text = ", " });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ast.Node.Id.SwitchElse => {
|
||||||
|
const switch_else = @fieldParentPtr(ast.NodeSwitchElse, "base", base);
|
||||||
|
try stream.print("{}", self.tokenizer.getTokenSlice(switch_else.token));
|
||||||
|
},
|
||||||
|
|
||||||
ast.Node.Id.StructField,
|
ast.Node.Id.StructField,
|
||||||
ast.Node.Id.UnionTag,
|
ast.Node.Id.UnionTag,
|
||||||
|
@ -2867,7 +3055,7 @@ pub const Parser = struct {
|
||||||
const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", base);
|
const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", base);
|
||||||
try stack.append(RenderState { .VarDecl = var_decl});
|
try stack.append(RenderState { .VarDecl = var_decl});
|
||||||
},
|
},
|
||||||
ast.Node.Id.Block => {
|
ast.Node.Id.Block, ast.Node.Id.Switch => {
|
||||||
try stack.append(RenderState { .Expression = base});
|
try stack.append(RenderState { .Expression = base});
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
|
@ -3436,24 +3624,24 @@ test "zig fmt: switch" {
|
||||||
\\ else => {
|
\\ else => {
|
||||||
\\ const a = 1;
|
\\ const a = 1;
|
||||||
\\ const b = a;
|
\\ const b = a;
|
||||||
\\ },
|
\\ }
|
||||||
\\ }
|
\\ }
|
||||||
\\
|
\\
|
||||||
\\ const res = switch (0) {
|
\\ const res = switch (0) {
|
||||||
\\ 0 => 0,
|
\\ 0 => 0,
|
||||||
\\ 1 => 2,
|
\\ 1 => 2,
|
||||||
\\ else => 4,
|
\\ else => 4
|
||||||
\\ };
|
\\ };
|
||||||
\\
|
\\
|
||||||
\\ const Union = union(enum) {
|
\\ const Union = union(enum) {
|
||||||
\\ Int: i64,
|
\\ Int: i64,
|
||||||
\\ Float: f64,
|
\\ Float: f64
|
||||||
\\ };
|
\\ };
|
||||||
\\
|
\\
|
||||||
\\ const u = Union { .Int = 0 };
|
\\ const u = Union{ .Int = 0 };
|
||||||
\\ switch (u) {
|
\\ switch (u) {
|
||||||
\\ Union.Int => |int| {},
|
\\ Union.Int => |int| {},
|
||||||
\\ Union.Float => |*float| unreachable,
|
\\ Union.Float => |*float| unreachable
|
||||||
\\ }
|
\\ }
|
||||||
\\}
|
\\}
|
||||||
\\
|
\\
|
||||||
|
|
|
@ -86,6 +86,7 @@ pub const Token = struct {
|
||||||
PipeEqual,
|
PipeEqual,
|
||||||
Equal,
|
Equal,
|
||||||
EqualEqual,
|
EqualEqual,
|
||||||
|
EqualAngleBracketRight,
|
||||||
BangEqual,
|
BangEqual,
|
||||||
LParen,
|
LParen,
|
||||||
RParen,
|
RParen,
|
||||||
|
@ -688,6 +689,11 @@ pub const Tokenizer = struct {
|
||||||
self.index += 1;
|
self.index += 1;
|
||||||
break;
|
break;
|
||||||
},
|
},
|
||||||
|
'>' => {
|
||||||
|
result.id = Token.Id.EqualAngleBracketRight;
|
||||||
|
self.index += 1;
|
||||||
|
break;
|
||||||
|
},
|
||||||
else => {
|
else => {
|
||||||
result.id = Token.Id.Equal;
|
result.id = Token.Id.Equal;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue