std.zig.parser now parses for loops

master
Jimmi Holst Christensen 2018-04-09 11:48:25 +02:00
parent e24409ebe0
commit 7dd55a8007
2 changed files with 319 additions and 33 deletions

View File

@ -20,12 +20,15 @@ pub const Node = struct {
FnProto, FnProto,
ParamDecl, ParamDecl,
Block, Block,
Payload, ErrorPayload,
ValuePayload,
ValueIndexPayload,
Else, Else,
Switch, Switch,
SwitchCase, SwitchCase,
SwitchElse, SwitchElse,
While, While,
For,
InfixOp, InfixOp,
PrefixOp, PrefixOp,
SuffixOp, SuffixOp,
@ -61,12 +64,15 @@ pub const Node = struct {
Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).iterate(index), Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).iterate(index),
Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).iterate(index), Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).iterate(index),
Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index), Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),
Id.Payload => @fieldParentPtr(NodePayload, "base", base).iterate(index), Id.ErrorPayload => @fieldParentPtr(NodeErrorPayload, "base", base).iterate(index),
Id.ValuePayload => @fieldParentPtr(NodeValuePayload, "base", base).iterate(index),
Id.ValueIndexPayload => @fieldParentPtr(NodeValueIndexPayload, "base", base).iterate(index),
Id.Else => @fieldParentPtr(NodeSwitch, "base", base).iterate(index), Id.Else => @fieldParentPtr(NodeSwitch, "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.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).iterate(index),
Id.While => @fieldParentPtr(NodeWhile, "base", base).iterate(index), Id.While => @fieldParentPtr(NodeWhile, "base", base).iterate(index),
Id.For => @fieldParentPtr(NodeFor, "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),
@ -103,12 +109,15 @@ pub const Node = struct {
Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).firstToken(), Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).firstToken(),
Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).firstToken(), Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).firstToken(),
Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(), Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(),
Id.Payload => @fieldParentPtr(NodePayload, "base", base).firstToken(), Id.ErrorPayload => @fieldParentPtr(NodeErrorPayload, "base", base).firstToken(),
Id.ValuePayload => @fieldParentPtr(NodeValuePayload, "base", base).firstToken(),
Id.ValueIndexPayload => @fieldParentPtr(NodeValueIndexPayload, "base", base).firstToken(),
Id.Else => @fieldParentPtr(NodeSwitch, "base", base).firstToken(), Id.Else => @fieldParentPtr(NodeSwitch, "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.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).firstToken(),
Id.While => @fieldParentPtr(NodeWhile, "base", base).firstToken(), Id.While => @fieldParentPtr(NodeWhile, "base", base).firstToken(),
Id.For => @fieldParentPtr(NodeFor, "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(),
@ -145,12 +154,15 @@ pub const Node = struct {
Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).lastToken(), Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).lastToken(),
Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).lastToken(), Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).lastToken(),
Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(), Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(),
Id.Payload => @fieldParentPtr(NodePayload, "base", base).lastToken(), Id.ErrorPayload => @fieldParentPtr(NodeErrorPayload, "base", base).lastToken(),
Id.ValuePayload => @fieldParentPtr(NodeValuePayload, "base", base).lastToken(),
Id.ValueIndexPayload => @fieldParentPtr(NodeValueIndexPayload, "base", base).lastToken(),
Id.Else => @fieldParentPtr(NodeElse, "base", base).lastToken(), Id.Else => @fieldParentPtr(NodeElse, "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).lastToken(), Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).lastToken(),
Id.While => @fieldParentPtr(NodeWhile, "base", base).lastToken(), Id.While => @fieldParentPtr(NodeWhile, "base", base).lastToken(),
Id.For => @fieldParentPtr(NodeFor, "base", base).lastToken(),
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(),
@ -557,27 +569,82 @@ pub const NodeBlock = struct {
} }
}; };
pub const NodePayload = struct { pub const NodeErrorPayload = struct {
base: Node, base: Node,
lpipe: Token, lpipe: Token,
is_ptr: bool, error_symbol: &NodeIdentifier,
symbol: &NodeIdentifier,
rpipe: Token, rpipe: Token,
pub fn iterate(self: &NodePayload, index: usize) ?&Node { pub fn iterate(self: &NodeErrorPayload, index: usize) ?&Node {
var i = index; var i = index;
if (i < 1) return &self.symbol.base; if (i < 1) return &self.error_symbol.base;
i -= 1; i -= 1;
return null; return null;
} }
pub fn firstToken(self: &NodePayload) Token { pub fn firstToken(self: &NodeErrorPayload) Token {
return self.lpipe; return self.lpipe;
} }
pub fn lastToken(self: &NodePayload) Token { pub fn lastToken(self: &NodeErrorPayload) Token {
return self.rpipe;
}
};
pub const NodeValuePayload = struct {
base: Node,
lpipe: Token,
is_ptr: bool,
value_symbol: &NodeIdentifier,
rpipe: Token,
pub fn iterate(self: &NodeValuePayload, index: usize) ?&Node {
var i = index;
if (i < 1) return &self.value_symbol.base;
i -= 1;
return null;
}
pub fn firstToken(self: &NodeValuePayload) Token {
return self.lpipe;
}
pub fn lastToken(self: &NodeValuePayload) Token {
return self.rpipe;
}
};
pub const NodeValueIndexPayload = struct {
base: Node,
lpipe: Token,
is_ptr: bool,
value_symbol: &NodeIdentifier,
index_symbol: ?&NodeIdentifier,
rpipe: Token,
pub fn iterate(self: &NodeValueIndexPayload, index: usize) ?&Node {
var i = index;
if (i < 1) return &self.value_symbol.base;
i -= 1;
if (self.index_symbol) |index_symbol| {
if (i < 1) return &index_symbol.base;
i -= 1;
}
return null;
}
pub fn firstToken(self: &NodeValueIndexPayload) Token {
return self.lpipe;
}
pub fn lastToken(self: &NodeValueIndexPayload) Token {
return self.rpipe; return self.rpipe;
} }
}; };
@ -585,7 +652,7 @@ pub const NodePayload = struct {
pub const NodeElse = struct { pub const NodeElse = struct {
base: Node, base: Node,
else_token: Token, else_token: Token,
payload: ?&NodePayload, payload: ?&NodeErrorPayload,
body: &Node, body: &Node,
pub fn iterate(self: &NodeElse, index: usize) ?&Node { pub fn iterate(self: &NodeElse, index: usize) ?&Node {
@ -642,7 +709,7 @@ pub const NodeSwitch = struct {
pub const NodeSwitchCase = struct { pub const NodeSwitchCase = struct {
base: Node, base: Node,
items: ArrayList(&Node), items: ArrayList(&Node),
payload: ?&NodePayload, payload: ?&NodeValuePayload,
expr: &Node, expr: &Node,
pub fn iterate(self: &NodeSwitchCase, index: usize) ?&Node { pub fn iterate(self: &NodeSwitchCase, index: usize) ?&Node {
@ -694,7 +761,7 @@ pub const NodeWhile = struct {
inline_token: ?Token, inline_token: ?Token,
while_token: Token, while_token: Token,
condition: &Node, condition: &Node,
payload: ?&NodePayload, payload: ?&NodeValuePayload,
continue_expr: ?&Node, continue_expr: ?&Node,
body: &Node, body: &Node,
@"else": ?&NodeElse, @"else": ?&NodeElse,
@ -747,6 +814,59 @@ pub const NodeWhile = struct {
} }
}; };
pub const NodeFor = struct {
base: Node,
label: ?Token,
inline_token: ?Token,
for_token: Token,
array_expr: &Node,
payload: ?&NodeValueIndexPayload,
body: &Node,
@"else": ?&NodeElse,
pub fn iterate(self: &NodeFor, index: usize) ?&Node {
var i = index;
if (i < 1) return self.array_expr;
i -= 1;
if (self.payload) |payload| {
if (i < 1) return &payload.base;
i -= 1;
}
if (i < 1) return self.body;
i -= 1;
if (self.@"else") |@"else"| {
if (i < 1) return &@"else".base;
i -= 1;
}
return null;
}
pub fn firstToken(self: &NodeFor) Token {
if (self.label) |label| {
return label;
}
if (self.inline_token) |inline_token| {
return inline_token;
}
return self.for_token;
}
pub fn lastToken(self: &NodeFor) Token {
if (self.@"else") |@"else"| {
return @"else".body.lastToken();
}
return self.body.lastToken();
}
};
pub const NodeInfixOp = struct { pub const NodeInfixOp = struct {
base: Node, base: Node,
op_token: Token, op_token: Token,
@ -781,7 +901,7 @@ pub const NodeInfixOp = struct {
BitXor, BitXor,
BoolAnd, BoolAnd,
BoolOr, BoolOr,
Catch: ?&NodePayload, Catch: ?&NodeErrorPayload,
Div, Div,
EqualEqual, EqualEqual,
ErrorUnion, ErrorUnion,

View File

@ -170,7 +170,9 @@ pub const Parser = struct {
FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer), FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer),
FieldListCommaOrEnd: &ast.NodeContainerDecl, FieldListCommaOrEnd: &ast.NodeContainerDecl,
SwitchCaseOrEnd: ListSave(&ast.NodeSwitchCase), SwitchCaseOrEnd: ListSave(&ast.NodeSwitchCase),
Payload: &?&ast.NodePayload, ErrorPayload: &?&ast.NodeErrorPayload,
ValuePayload: &?&ast.NodeValuePayload,
ValueIndexPayload: &?&ast.NodeValueIndexPayload,
SwitchCaseCommaOrEnd: ListSave(&ast.NodeSwitchCase), SwitchCaseCommaOrEnd: ListSave(&ast.NodeSwitchCase),
SwitchCaseItem: &ArrayList(&ast.Node), SwitchCaseItem: &ArrayList(&ast.Node),
SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node), SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node),
@ -769,7 +771,7 @@ pub const Parser = struct {
stack.append(State { .UnwrapExpressionEnd = dest_ptr }) catch unreachable; stack.append(State { .UnwrapExpressionEnd = dest_ptr }) catch unreachable;
try stack.append(State { .Expression = DestPtr { .Field = &node.rhs } }); try stack.append(State { .Expression = DestPtr { .Field = &node.rhs } });
try stack.append(State { .Payload = &node.op.Catch }); try stack.append(State { .ErrorPayload = &node.op.Catch });
continue; continue;
}, },
Token.Id.QuestionMarkQuestionMark => { Token.Id.QuestionMarkQuestionMark => {
@ -1471,7 +1473,15 @@ pub const Parser = struct {
continue; continue;
}, },
Token.Id.Keyword_for => { Token.Id.Keyword_for => {
@panic("TODO: inline for"); stack.append(State {
.For = LoopCtx {
.label = null,
.inline_token = null,
.loop_token = token,
.dest_ptr = dest_ptr,
}
}) catch unreachable;
continue;
}, },
Token.Id.Keyword_switch => { Token.Id.Keyword_switch => {
const node = try arena.create(ast.NodeSwitch); const node = try arena.create(ast.NodeSwitch);
@ -1614,7 +1624,7 @@ pub const Parser = struct {
try list_state.list.append(node); try list_state.list.append(node);
stack.append(State { .SwitchCaseCommaOrEnd = list_state }) catch unreachable; stack.append(State { .SwitchCaseCommaOrEnd = list_state }) catch unreachable;
try stack.append(State { .Expression = DestPtr{ .Field = &node.expr } }); try stack.append(State { .Expression = DestPtr{ .Field = &node.expr } });
try stack.append(State { .Payload = &node.payload }); try stack.append(State { .ValuePayload = &node.payload });
const maybe_else = self.getNextToken(); const maybe_else = self.getNextToken();
if (maybe_else.id == Token.Id.Keyword_else) { if (maybe_else.id == Token.Id.Keyword_else) {
@ -1681,7 +1691,7 @@ pub const Parser = struct {
*dest = node; *dest = node;
stack.append(State { .Expression = DestPtr { .Field = &node.body } }) catch unreachable; stack.append(State { .Expression = DestPtr { .Field = &node.body } }) catch unreachable;
try stack.append(State { .Payload = &node.payload }); try stack.append(State { .ErrorPayload = &node.payload });
}, },
State.WhileContinueExpr => |dest| { State.WhileContinueExpr => |dest| {
@ -1696,7 +1706,26 @@ pub const Parser = struct {
try stack.append(State { .Expression = DestPtr { .NullableField = dest } }); try stack.append(State { .Expression = DestPtr { .NullableField = dest } });
}, },
State.Payload => |dest| { State.ErrorPayload => |dest| {
const lpipe = self.getNextToken();
if (lpipe.id != Token.Id.Pipe) {
self.putBackToken(lpipe);
continue;
}
const error_symbol = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue;
const node = try arena.create(ast.NodeErrorPayload);
*node = ast.NodeErrorPayload {
.base = self.initNode(ast.Node.Id.ErrorPayload),
.lpipe = lpipe,
.error_symbol = try self.createIdentifier(arena, error_symbol),
.rpipe = rpipe
};
*dest = node;
},
State.ValuePayload => |dest| {
const lpipe = self.getNextToken(); const lpipe = self.getNextToken();
if (lpipe.id != Token.Id.Pipe) { if (lpipe.id != Token.Id.Pipe) {
self.putBackToken(lpipe); self.putBackToken(lpipe);
@ -1713,14 +1742,56 @@ pub const Parser = struct {
} }
}; };
const ident = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue; const value_symbol = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue; const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue;
const node = try arena.create(ast.NodePayload); const node = try arena.create(ast.NodeValuePayload);
*node = ast.NodePayload { *node = ast.NodeValuePayload {
.base = self.initNode(ast.Node.Id.Payload), .base = self.initNode(ast.Node.Id.ValuePayload),
.lpipe = lpipe, .lpipe = lpipe,
.is_ptr = is_ptr, .is_ptr = is_ptr,
.symbol = try self.createIdentifier(arena, ident), .value_symbol = try self.createIdentifier(arena, value_symbol),
.rpipe = rpipe
};
*dest = node;
},
State.ValueIndexPayload => |dest| {
const lpipe = self.getNextToken();
if (lpipe.id != Token.Id.Pipe) {
self.putBackToken(lpipe);
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 value_symbol = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
const index_symbol = blk: {
const comma = self.getNextToken();
if (comma.id != Token.Id.Comma) {
self.putBackToken(comma);
break :blk null;
}
const symbol = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
break :blk try self.createIdentifier(arena, symbol);
};
const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue;
const node = try arena.create(ast.NodeValueIndexPayload);
*node = ast.NodeValueIndexPayload {
.base = self.initNode(ast.Node.Id.ValueIndexPayload),
.lpipe = lpipe,
.is_ptr = is_ptr,
.value_symbol = try self.createIdentifier(arena, value_symbol),
.index_symbol = index_symbol,
.rpipe = rpipe .rpipe = rpipe
}; };
*dest = node; *dest = node;
@ -1986,13 +2057,32 @@ pub const Parser = struct {
stack.append(State { .Else = &node.@"else" }) catch unreachable; stack.append(State { .Else = &node.@"else" }) catch unreachable;
try stack.append(State { .Expression = DestPtr { .Field = &node.body } }); try stack.append(State { .Expression = DestPtr { .Field = &node.body } });
try stack.append(State { .WhileContinueExpr = &node.continue_expr }); try stack.append(State { .WhileContinueExpr = &node.continue_expr });
try stack.append(State { .Payload = &node.payload }); try stack.append(State { .ValuePayload = &node.payload });
try stack.append(State { .ExpectToken = Token.Id.RParen }); try stack.append(State { .ExpectToken = Token.Id.RParen });
try stack.append(State { .Expression = DestPtr { .Field = &node.condition } }); try stack.append(State { .Expression = DestPtr { .Field = &node.condition } });
try stack.append(State { .ExpectToken = Token.Id.LParen }); try stack.append(State { .ExpectToken = Token.Id.LParen });
}, },
State.For => |ctx| { State.For => |ctx| {
const node = try arena.create(ast.NodeFor);
*node = ast.NodeFor {
.base = self.initNode(ast.Node.Id.For),
.label = ctx.label,
.inline_token = ctx.inline_token,
.for_token = ctx.loop_token,
.array_expr = undefined,
.payload = null,
.body = undefined,
.@"else" = null,
};
ctx.dest_ptr.store(&node.base);
stack.append(State { .Else = &node.@"else" }) catch unreachable;
try stack.append(State { .Expression = DestPtr { .Field = &node.body } });
try stack.append(State { .ValueIndexPayload = &node.payload });
try stack.append(State { .ExpectToken = Token.Id.RParen });
try stack.append(State { .Expression = DestPtr { .Field = &node.array_expr } });
try stack.append(State { .ExpectToken = Token.Id.LParen });
}, },
State.Block => |block| { State.Block => |block| {
@ -2071,7 +2161,9 @@ pub const Parser = struct {
ast.Node.Id.EnumTag, ast.Node.Id.EnumTag,
ast.Node.Id.ParamDecl, ast.Node.Id.ParamDecl,
ast.Node.Id.Block, ast.Node.Id.Block,
ast.Node.Id.Payload, ast.Node.Id.ErrorPayload,
ast.Node.Id.ValuePayload,
ast.Node.Id.ValueIndexPayload,
ast.Node.Id.Switch, ast.Node.Id.Switch,
ast.Node.Id.SwitchCase, ast.Node.Id.SwitchCase,
ast.Node.Id.SwitchElse, ast.Node.Id.SwitchElse,
@ -2087,6 +2179,15 @@ pub const Parser = struct {
n = while_node.body; n = while_node.body;
}, },
ast.Node.Id.For => {
const for_node = @fieldParentPtr(ast.NodeFor, "base", n);
if (for_node.@"else") |@"else"| {
n = @"else".base;
continue;
}
n = for_node.body;
},
ast.Node.Id.Else => { ast.Node.Id.Else => {
const else_node = @fieldParentPtr(ast.NodeElse, "base", n); const else_node = @fieldParentPtr(ast.NodeElse, "base", n);
n = else_node.body; n = else_node.body;
@ -2982,10 +3083,33 @@ pub const Parser = struct {
try stack.append(RenderState { .Expression = rhs }); try stack.append(RenderState { .Expression = rhs });
} }
}, },
ast.Node.Id.Payload => { ast.Node.Id.ErrorPayload => {
const payload = @fieldParentPtr(ast.NodePayload, "base", base); const payload = @fieldParentPtr(ast.NodeErrorPayload, "base", base);
try stack.append(RenderState { .Text = "|"}); try stack.append(RenderState { .Text = "|"});
try stack.append(RenderState { .Expression = &payload.symbol.base }); try stack.append(RenderState { .Expression = &payload.error_symbol.base });
try stack.append(RenderState { .Text = "|"});
},
ast.Node.Id.ValuePayload => {
const payload = @fieldParentPtr(ast.NodeValuePayload, "base", base);
try stack.append(RenderState { .Text = "|"});
try stack.append(RenderState { .Expression = &payload.value_symbol.base });
if (payload.is_ptr) {
try stack.append(RenderState { .Text = "*"});
}
try stack.append(RenderState { .Text = "|"});
},
ast.Node.Id.ValueIndexPayload => {
const payload = @fieldParentPtr(ast.NodeValueIndexPayload, "base", base);
try stack.append(RenderState { .Text = "|"});
if (payload.index_symbol) |index_symbol| {
try stack.append(RenderState { .Expression = &index_symbol.base });
try stack.append(RenderState { .Text = ", "});
}
try stack.append(RenderState { .Expression = &payload.value_symbol.base });
if (payload.is_ptr) { if (payload.is_ptr) {
try stack.append(RenderState { .Text = "*"}); try stack.append(RenderState { .Text = "*"});
@ -3303,6 +3427,48 @@ pub const Parser = struct {
try stack.append(RenderState { .Expression = while_node.condition }); try stack.append(RenderState { .Expression = while_node.condition });
try stack.append(RenderState { .Text = "(" }); try stack.append(RenderState { .Text = "(" });
}, },
ast.Node.Id.For => {
const for_node = @fieldParentPtr(ast.NodeFor, "base", base);
if (for_node.label) |label| {
try stream.print("{}: ", self.tokenizer.getTokenSlice(label));
}
if (for_node.inline_token) |inline_token| {
try stream.print("{} ", self.tokenizer.getTokenSlice(inline_token));
}
try stream.print("{} ", self.tokenizer.getTokenSlice(for_node.for_token));
if (for_node.@"else") |@"else"| {
try stack.append(RenderState { .Expression = &@"else".base });
if (for_node.body.id == ast.Node.Id.Block) {
try stack.append(RenderState { .Text = " " });
} else {
try stack.append(RenderState { .Text = "\n" });
}
}
if (for_node.body.id == ast.Node.Id.Block) {
try stack.append(RenderState { .Expression = for_node.body });
try stack.append(RenderState { .Text = " " });
} else {
try stack.append(RenderState { .Indent = indent });
try stack.append(RenderState { .Expression = for_node.body });
try stack.append(RenderState.PrintIndent);
try stack.append(RenderState { .Indent = indent + indent_delta });
try stack.append(RenderState { .Text = "\n" });
}
if (for_node.payload) |payload| {
try stack.append(RenderState { .Expression = &payload.base });
try stack.append(RenderState { .Text = " " });
}
try stack.append(RenderState { .Text = ")" });
try stack.append(RenderState { .Expression = for_node.array_expr });
try stack.append(RenderState { .Text = "(" });
},
ast.Node.Id.StructField, ast.Node.Id.StructField,
ast.Node.Id.UnionTag, ast.Node.Id.UnionTag,
@ -4022,10 +4188,10 @@ test "zig fmt: for" {
\\ continue; \\ continue;
\\ \\
\\ const res = for (a) |v, i| { \\ const res = for (a) |v, i| {
\\ breal v; \\ break v;
\\ } else { \\ } else {
\\ unreachable; \\ unreachable;
\\ } \\ };
\\ \\
\\ var num: usize = 0; \\ var num: usize = 0;
\\ inline for (a) |v, i| { \\ inline for (a) |v, i| {