From c19f5a2356b441e3dde95e85e029fec6ef4f836d Mon Sep 17 00:00:00 2001 From: Jimmi Holst Christensen Date: Mon, 9 Apr 2018 12:51:18 +0200 Subject: std.zig.parser now parses if statements --- std/zig/ast.zig | 47 +++++++++++++++++++++++++ std/zig/parser.zig | 101 +++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 137 insertions(+), 11 deletions(-) (limited to 'std') diff --git a/std/zig/ast.zig b/std/zig/ast.zig index c97e33ba10..9e077a3567 100644 --- a/std/zig/ast.zig +++ b/std/zig/ast.zig @@ -29,6 +29,7 @@ pub const Node = struct { SwitchElse, While, For, + If, InfixOp, PrefixOp, SuffixOp, @@ -73,6 +74,7 @@ pub const Node = struct { Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).iterate(index), Id.While => @fieldParentPtr(NodeWhile, "base", base).iterate(index), Id.For => @fieldParentPtr(NodeFor, "base", base).iterate(index), + Id.If => @fieldParentPtr(NodeIf, "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), @@ -118,6 +120,7 @@ pub const Node = struct { Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).firstToken(), Id.While => @fieldParentPtr(NodeWhile, "base", base).firstToken(), Id.For => @fieldParentPtr(NodeFor, "base", base).firstToken(), + Id.If => @fieldParentPtr(NodeIf, "base", base).firstToken(), Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).firstToken(), Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).firstToken(), Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).firstToken(), @@ -163,6 +166,7 @@ pub const Node = struct { Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).lastToken(), Id.While => @fieldParentPtr(NodeWhile, "base", base).lastToken(), Id.For => @fieldParentPtr(NodeFor, "base", base).lastToken(), + Id.If => @fieldParentPtr(NodeIf, "base", base).lastToken(), Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).lastToken(), Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).lastToken(), Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).lastToken(), @@ -867,6 +871,49 @@ pub const NodeFor = struct { } }; +pub const NodeIf = struct { + base: Node, + if_token: Token, + condition: &Node, + payload: ?&NodeValuePayload, + body: &Node, + @"else": ?&NodeElse, + + pub fn iterate(self: &NodeIf, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.condition; + 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: &NodeIf) Token { + return self.if_token; + } + + pub fn lastToken(self: &NodeIf) Token { + if (self.@"else") |@"else"| { + return @"else".body.lastToken(); + } + + return self.body.lastToken(); + } +}; + pub const NodeInfixOp = struct { base: Node, op_token: Token, diff --git a/std/zig/parser.zig b/std/zig/parser.zig index 2b2afaeabb..09383a313b 100644 --- a/std/zig/parser.zig +++ b/std/zig/parser.zig @@ -1449,7 +1449,24 @@ pub const Parser = struct { @panic("TODO: inline asm"); }, Token.Id.Keyword_if => { - @panic("TODO: inline if"); + const node = try arena.create(ast.NodeIf); + *node = ast.NodeIf { + .base = self.initNode(ast.Node.Id.If), + .if_token = token, + .condition = undefined, + .payload = null, + .body = undefined, + .@"else" = null, + }; + 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 { .ValuePayload = &node.payload }); + try stack.append(State { .ExpectToken = Token.Id.RParen }); + try stack.append(State { .Expression = DestPtr { .Field = &node.condition } }); + try stack.append(State { .ExpectToken = Token.Id.LParen }); + continue; }, Token.Id.Keyword_inline => { stack.append(State { @@ -2188,6 +2205,15 @@ pub const Parser = struct { n = for_node.body; }, + ast.Node.Id.If => { + const if_node = @fieldParentPtr(ast.NodeIf, "base", n); + if (if_node.@"else") |@"else"| { + n = @"else".base; + continue; + } + + n = if_node.body; + }, ast.Node.Id.Else => { const else_node = @fieldParentPtr(ast.NodeElse, "base", n); n = else_node.body; @@ -3363,14 +3389,19 @@ pub const Parser = struct { const else_node = @fieldParentPtr(ast.NodeElse, "base", base); try stream.print("{} ", self.tokenizer.getTokenSlice(else_node.else_token)); - if (else_node.body.id == ast.Node.Id.Block) { - try stack.append(RenderState { .Expression = else_node.body }); - } else { - try stack.append(RenderState { .Indent = indent }); - try stack.append(RenderState { .Expression = else_node.body }); - try stack.append(RenderState.PrintIndent); - try stack.append(RenderState { .Indent = indent + indent_delta }); - try stack.append(RenderState { .Text = "\n" }); + switch (else_node.body.id) { + ast.Node.Id.Block, ast.Node.Id.If, + ast.Node.Id.For, ast.Node.Id.While, + ast.Node.Id.Switch => { + try stack.append(RenderState { .Expression = else_node.body }); + }, + else => { + try stack.append(RenderState { .Indent = indent }); + try stack.append(RenderState { .Expression = else_node.body }); + try stack.append(RenderState.PrintIndent); + try stack.append(RenderState { .Indent = indent + indent_delta }); + try stack.append(RenderState { .Text = "\n" }); + } } if (else_node.payload) |payload| { @@ -3396,6 +3427,7 @@ pub const Parser = struct { if (while_node.body.id == ast.Node.Id.Block) { try stack.append(RenderState { .Text = " " }); } else { + try stack.append(RenderState.PrintIndent); try stack.append(RenderState { .Text = "\n" }); } } @@ -3445,6 +3477,7 @@ pub const Parser = struct { if (for_node.body.id == ast.Node.Id.Block) { try stack.append(RenderState { .Text = " " }); } else { + try stack.append(RenderState.PrintIndent); try stack.append(RenderState { .Text = "\n" }); } } @@ -3469,6 +3502,53 @@ pub const Parser = struct { try stack.append(RenderState { .Expression = for_node.array_expr }); try stack.append(RenderState { .Text = "(" }); }, + ast.Node.Id.If => { + const if_node = @fieldParentPtr(ast.NodeIf, "base", base); + try stream.print("{} ", self.tokenizer.getTokenSlice(if_node.if_token)); + + switch (if_node.body.id) { + ast.Node.Id.Block, ast.Node.Id.If, + ast.Node.Id.For, ast.Node.Id.While, + ast.Node.Id.Switch => { + if (if_node.@"else") |@"else"| { + try stack.append(RenderState { .Expression = &@"else".base }); + + if (if_node.body.id == ast.Node.Id.Block) { + try stack.append(RenderState { .Text = " " }); + } else { + try stack.append(RenderState.PrintIndent); + try stack.append(RenderState { .Text = "\n" }); + } + } + }, + else => { + if (if_node.@"else") |@"else"| { + try stack.append(RenderState { .Expression = @"else".body }); + + if (@"else".payload) |payload| { + try stack.append(RenderState { .Text = " " }); + try stack.append(RenderState { .Expression = &payload.base }); + } + + try stack.append(RenderState { .Text = " " }); + try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(@"else".else_token) }); + try stack.append(RenderState { .Text = " " }); + } + } + } + + try stack.append(RenderState { .Expression = if_node.body }); + try stack.append(RenderState { .Text = " " }); + + if (if_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 = if_node.condition }); + try stack.append(RenderState { .Text = "(" }); + }, ast.Node.Id.StructField, ast.Node.Id.UnionTag, @@ -4210,8 +4290,7 @@ test "zig fmt: if" { \\ unreachable; \\ } \\ - \\ if (10 < 0) - \\ unreachable; + \\ if (10 < 0) unreachable; \\ \\ if (10 < 0) { \\ unreachable; -- cgit v1.2.3