zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 09cf82361999c1a22819467e02fc68fd22ca188e (tree)
parent ec611bf8b47af0db5244af644040907bfcb63945
Author: Jimmi Holst Christensen <jhc@liab.dk>
Date:   Wed,  4 Apr 2018 09:57:37 +0200

std.zig.parser now parses container decls

Diffstat:
Mstd/zig/ast.zig | 11+++++++++--
Mstd/zig/parser.zig | 260+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
2 files changed, 176 insertions(+), 95 deletions(-)

diff --git a/std/zig/ast.zig b/std/zig/ast.zig @@ -214,12 +214,19 @@ pub const NodeVarDecl = struct { pub const NodeContainerDecl = struct { base: Node, - kind_token: Token, + ltoken: Token, + layout: Layout, kind: Kind, init_arg_expr: InitArg, fields_and_decls: ArrayList(&Node), rbrace_token: Token, + const Layout = enum { + Auto, + Extern, + Packed, + }; + const Kind = enum { Struct, Enum, @@ -266,7 +273,7 @@ pub const NodeContainerDecl = struct { } pub fn firstToken(self: &NodeContainerDecl) Token { - return self.kind_token; + return self.ltoken; } pub fn lastToken(self: &NodeContainerDecl) Token { diff --git a/std/zig/parser.zig b/std/zig/parser.zig @@ -59,6 +59,11 @@ pub const Parser = struct { lib_name: ?&ast.Node, }; + const ContainerExternCtx = struct { + ltoken: Token, + layout: ast.NodeContainerDecl.Layout, + }; + const DestPtr = union(enum) { Field: &&ast.Node, NullableField: &?&ast.Node, @@ -90,6 +95,7 @@ pub const Parser = struct { TopLevel, TopLevelExtern: TopLevelDeclCtx, TopLevelDecl: TopLevelDeclCtx, + ContainerExtern: ContainerExternCtx, ContainerDecl: &ast.NodeContainerDecl, Expression: DestPtr, ExpectOperand, @@ -338,6 +344,63 @@ pub const Parser = struct { return self.parseError(token, "expected '=' or ';', found {}", @tagName(token.id)); }, + State.ContainerExtern => |ctx| { + const token = self.getNextToken(); + + const node = try arena.create(ast.NodeContainerDecl); + *node = ast.NodeContainerDecl { + .base = self.initNode(ast.Node.Id.ContainerDecl), + .ltoken = ctx.ltoken, + .layout = ctx.layout, + .kind = switch (token.id) { + Token.Id.Keyword_struct => ast.NodeContainerDecl.Kind.Struct, + Token.Id.Keyword_union => ast.NodeContainerDecl.Kind.Union, + Token.Id.Keyword_enum => ast.NodeContainerDecl.Kind.Enum, + else => { + return self.parseError(token, "expected {}, {} or {}, found {}", + @tagName(Token.Id.Keyword_struct), + @tagName(Token.Id.Keyword_union), + @tagName(Token.Id.Keyword_enum), + @tagName(token.id)); + }, + }, + .init_arg_expr = undefined, + .fields_and_decls = ArrayList(&ast.Node).init(arena), + .rbrace_token = undefined, + }; + + try stack.append(State { .Operand = &node.base }); + try stack.append(State.AfterOperand); + try stack.append(State { .ContainerDecl = node }); + try stack.append(State { .ExpectToken = Token.Id.LBrace }); + + const lparen = self.getNextToken(); + if (lparen.id != Token.Id.LParen) { + self.putBackToken(lparen); + node.init_arg_expr = ast.NodeContainerDecl.InitArg.None; + continue; + } + + try stack.append(State { .ExpectToken = Token.Id.RParen }); + + const init_arg_token = self.getNextToken(); + switch (init_arg_token.id) { + Token.Id.Keyword_enum => { + node.init_arg_expr = ast.NodeContainerDecl.InitArg.Enum; + }, + else => { + self.putBackToken(init_arg_token); + node.init_arg_expr = ast.NodeContainerDecl.InitArg { .Type = undefined }; + try stack.append(State { + .Expression = DestPtr { + .Field = &node.init_arg_expr.Type + } + }); + }, + } + continue; + }, + State.ContainerDecl => |container_decl| { const token = self.getNextToken(); @@ -633,52 +696,30 @@ pub const Parser = struct { try stack.append(State.AfterOperand); continue; }, - Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => { - const node = try arena.create(ast.NodeContainerDecl); - *node = ast.NodeContainerDecl { - .base = self.initNode(ast.Node.Id.ContainerDecl), - .kind_token = token, - .kind = switch (token.id) { - Token.Id.Keyword_struct => ast.NodeContainerDecl.Kind.Struct, - Token.Id.Keyword_union => ast.NodeContainerDecl.Kind.Union, - Token.Id.Keyword_enum => ast.NodeContainerDecl.Kind.Enum, - else => unreachable, + Token.Id.Keyword_packed => { + try stack.append(State { + .ContainerExtern = ContainerExternCtx { + .ltoken = token, + .layout = ast.NodeContainerDecl.Layout.Packed, }, - .init_arg_expr = undefined, - .fields_and_decls = ArrayList(&ast.Node).init(arena), - .rbrace_token = undefined, - }; - - try stack.append(State { .Operand = &node.base }); - try stack.append(State.AfterOperand); - try stack.append(State { .ContainerDecl = node }); - try stack.append(State { .ExpectToken = Token.Id.LBrace }); - - const lparen = self.getNextToken(); - if (lparen.id != Token.Id.LParen) { - self.putBackToken(lparen); - node.init_arg_expr = ast.NodeContainerDecl.InitArg.None; - continue; - } - - try stack.append(State { .ExpectToken = Token.Id.RParen }); - - const init_arg_token = self.getNextToken(); - switch (init_arg_token.id) { - Token.Id.Keyword_enum => { - node.init_arg_expr = ast.NodeContainerDecl.InitArg.Enum; + }); + }, + Token.Id.Keyword_extern => { + try stack.append(State { + .ContainerExtern = ContainerExternCtx { + .ltoken = token, + .layout = ast.NodeContainerDecl.Layout.Extern, }, - else => { - self.putBackToken(lparen); - node.init_arg_expr = ast.NodeContainerDecl.InitArg { .Type = undefined }; - try stack.append(State { - .Expression = DestPtr { - .Field = &node.init_arg_expr.Type - } - }); + }); + }, + Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => { + self.putBackToken(token); + try stack.append(State { + .ContainerExtern = ContainerExternCtx { + .ltoken = token, + .layout = ast.NodeContainerDecl.Layout.Auto, }, - } - continue; + }); }, Token.Id.Builtin => { const node = try arena.create(ast.NodeBuiltinCall); @@ -1706,6 +1747,29 @@ pub const Parser = struct { try stack.append(RenderState { .Text = " " }); try stack.append(RenderState { .Expression = test_decl.name }); }, + ast.Node.Id.StructField => { + const field = @fieldParentPtr(ast.NodeStructField, "base", decl); + try stream.print("{}: ", self.tokenizer.getTokenSlice(field.name_token)); + try stack.append(RenderState { .Expression = field.type_expr}); + }, + ast.Node.Id.UnionTag => { + const tag = @fieldParentPtr(ast.NodeUnionTag, "base", decl); + try stream.print("{}", self.tokenizer.getTokenSlice(tag.name_token)); + + if (tag.type_expr) |type_expr| { + try stream.print(": "); + try stack.append(RenderState { .Expression = type_expr}); + } + }, + ast.Node.Id.EnumTag => { + const tag = @fieldParentPtr(ast.NodeEnumTag, "base", decl); + try stream.print("{}", self.tokenizer.getTokenSlice(tag.name_token)); + + if (tag.value) |value| { + try stream.print(" = "); + try stack.append(RenderState { .Expression = value}); + } + }, else => unreachable, } }, @@ -1990,27 +2054,30 @@ pub const Parser = struct { }, ast.Node.Id.ContainerDecl => { const container_decl = @fieldParentPtr(ast.NodeContainerDecl, "base", base); - try stream.print("{} {{", self.tokenizer.getTokenSlice(container_decl.kind_token)); + + switch (container_decl.layout) { + ast.NodeContainerDecl.Layout.Packed => try stream.print("packed "), + ast.NodeContainerDecl.Layout.Extern => try stream.print("extern "), + ast.NodeContainerDecl.Layout.Auto => { }, + } + + switch (container_decl.kind) { + ast.NodeContainerDecl.Kind.Struct => try stream.print("struct"), + ast.NodeContainerDecl.Kind.Enum => try stream.print("enum"), + ast.NodeContainerDecl.Kind.Union => try stream.print("union"), + } + try stack.append(RenderState { .Text = "}"}); try stack.append(RenderState.PrintIndent); try stack.append(RenderState { .Indent = indent }); + try stack.append(RenderState { .Text = "\n"}); const fields_and_decls = container_decl.fields_and_decls.toSliceConst(); var i = fields_and_decls.len; while (i != 0) { i -= 1; const node = fields_and_decls[i]; - if (i != 0) { - switch (node.id) { - ast.Node.Id.StructField, - ast.Node.Id.UnionTag, - ast.Node.Id.EnumTag => { - try stack.append(RenderState { .Text = "," }); - }, - else => { } - } - } - try stack.append(RenderState { .Expression = node}); + try stack.append(RenderState { .TopLevelDecl = node}); try stack.append(RenderState.PrintIndent); try stack.append(RenderState { .Text = blk: { @@ -2025,22 +2092,43 @@ pub const Parser = struct { break :blk "\n"; }, }); + + if (i != 0) { + const prev_node = fields_and_decls[i - 1]; + switch (prev_node.id) { + ast.Node.Id.StructField, + ast.Node.Id.UnionTag, + ast.Node.Id.EnumTag => { + try stack.append(RenderState { .Text = "," }); + }, + else => { } + } + } } try stack.append(RenderState { .Indent = indent + indent_delta}); + try stack.append(RenderState { .Text = "{"}); + + switch (container_decl.init_arg_expr) { + ast.NodeContainerDecl.InitArg.None => try stack.append(RenderState { .Text = " "}), + ast.NodeContainerDecl.InitArg.Enum => try stack.append(RenderState { .Text = "(enum) "}), + ast.NodeContainerDecl.InitArg.Type => |type_expr| { + try stack.append(RenderState { .Text = ") "}); + try stack.append(RenderState { .Expression = type_expr}); + try stack.append(RenderState { .Text = "("}); + }, + } }, ast.Node.Id.MultilineStringLiteral => { const multiline_str_literal = @fieldParentPtr(ast.NodeMultilineStringLiteral, "base", base); try stream.print("\n"); var i : usize = 0; - indent += 4; while (i < multiline_str_literal.tokens.len) : (i += 1) { const t = multiline_str_literal.tokens.at(i); - try stream.writeByteNTimes(' ', indent); + try stream.writeByteNTimes(' ', indent + indent_delta); try stream.print("{}", self.tokenizer.getTokenSlice(t)); } - try stream.writeByteNTimes(' ', indent); - indent -= 4; + try stream.writeByteNTimes(' ', indent + indent_delta); }, ast.Node.Id.UndefinedLiteral => { const undefined_literal = @fieldParentPtr(ast.NodeUndefinedLiteral, "base", base); @@ -2060,31 +2148,12 @@ pub const Parser = struct { } } }, - ast.Node.Id.StructField => { - const field = @fieldParentPtr(ast.NodeStructField, "base", base); - try stream.print("{}:", self.tokenizer.getTokenSlice(field.name_token)); - }, - ast.Node.Id.UnionTag => { - const tag = @fieldParentPtr(ast.NodeUnionTag, "base", base); - try stream.print("{}", self.tokenizer.getTokenSlice(tag.name_token)); - - if (tag.type_expr) |type_expr| { - try stream.print(": "); - try stack.append(RenderState { .Expression = type_expr}); - } - }, - ast.Node.Id.EnumTag => { - const tag = @fieldParentPtr(ast.NodeEnumTag, "base", base); - try stream.print("{}", self.tokenizer.getTokenSlice(tag.name_token)); - - if (tag.value) |value| { - try stream.print(" = "); - try stack.append(RenderState { .Expression = value}); - } - }, 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.StructField, + ast.Node.Id.UnionTag, + ast.Node.Id.EnumTag, ast.Node.Id.Root, ast.Node.Id.VarDecl, ast.Node.Id.TestDecl, @@ -2489,21 +2558,21 @@ test "zig fmt: struct declaration" { \\ return *self; \\ } \\ - \\ f2: u8, + \\ f2: u8 \\}; \\ \\const Ps = packed struct { \\ a: u8, \\ b: u8, \\ - \\ c: u8, + \\ c: u8 \\}; \\ \\const Es = extern struct { \\ a: u8, \\ b: u8, \\ - \\ c: u8, + \\ c: u8 \\}; \\ ); @@ -2513,25 +2582,25 @@ test "zig fmt: enum declaration" { try testCanonical( \\const E = enum { \\ Ok, - \\ SomethingElse = 0, + \\ SomethingElse = 0 \\}; \\ \\const E2 = enum(u8) { \\ Ok, \\ SomethingElse = 255, - \\ SomethingThird, + \\ SomethingThird \\}; \\ \\const Ee = extern enum { \\ Ok, \\ SomethingElse, - \\ SomethingThird, + \\ SomethingThird \\}; \\ \\const Ep = packed enum { \\ Ok, \\ SomethingElse, - \\ SomethingThird, + \\ SomethingThird \\}; \\ ); @@ -2542,31 +2611,36 @@ test "zig fmt: union declaration" { \\const U = union { \\ Int: u8, \\ Float: f32, - \\ Bool: bool, + \\ None, + \\ Bool: bool \\}; \\ \\const Ue = union(enum) { \\ Int: u8, \\ Float: f32, - \\ Bool: bool, + \\ None, + \\ Bool: bool \\}; \\ \\const E = enum { \\ Int, \\ Float, - \\ Bool, + \\ None, + \\ Bool \\}; \\ \\const Ue2 = union(E) { \\ Int: u8, \\ Float: f32, - \\ Bool: bool, + \\ None, + \\ Bool: bool \\}; \\ \\const Eu = extern union { \\ Int: u8, \\ Float: f32, - \\ Bool: bool, + \\ None, + \\ Bool: bool \\}; \\ );