authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-07 19:05:46+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-07 19:05:46+02:00
log4184d4c66a26ba10fbc78cc21f2c73db8f0cfcb2
treece96a5cbe63f8bd86ab1cfeb3892e1fea44005d0
parentdf12c1328eb9c2af006dfd9e5cf69046ad6fc235
signaturelock-open Commit is signed but in an unrecognized format.

std-c parser record and enum specifiers


2 files changed, 151 insertions(+), 31 deletions(-)

lib/std/c/ast.zig+36-16
...@@ -48,9 +48,12 @@ pub const Error = union(enum) {...@@ -48,9 +48,12 @@ pub const Error = union(enum) {
48 ExpectedFnBody: SingleTokenError("expected function body, found '{}'"),48 ExpectedFnBody: SingleTokenError("expected function body, found '{}'"),
49 ExpectedDeclarator: SingleTokenError("expected declarator, found '{}'"),49 ExpectedDeclarator: SingleTokenError("expected declarator, found '{}'"),
50 ExpectedInitializer: SingleTokenError("expected initializer, found '{}'"),50 ExpectedInitializer: SingleTokenError("expected initializer, found '{}'"),
51 ExpectedEnumField: SingleTokenError("expected enum field, found '{}'"),
52 ExpectedType: SingleTokenError("expected enum field, found '{}'"),
51 InvalidTypeSpecifier: InvalidTypeSpecifier,53 InvalidTypeSpecifier: InvalidTypeSpecifier,
52 DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"),54 DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"),
53 DuplicateSpecifier: SingleTokenError("duplicate declaration specifier '{}'"),55 DuplicateSpecifier: SingleTokenError("duplicate declaration specifier '{}'"),
56 MustUseKwToRefer: MustUseKwToRefer,
5457
55 pub fn render(self: *const Error, tree: *Tree, stream: var) !void {58 pub fn render(self: *const Error, tree: *Tree, stream: var) !void {
56 switch (self.*) {59 switch (self.*) {
...@@ -62,9 +65,12 @@ pub const Error = union(enum) {...@@ -62,9 +65,12 @@ pub const Error = union(enum) {
62 .ExpectedDeclarator => |*x| return x.render(tree, stream),65 .ExpectedDeclarator => |*x| return x.render(tree, stream),
63 .ExpectedFnBody => |*x| return x.render(tree, stream),66 .ExpectedFnBody => |*x| return x.render(tree, stream),
64 .ExpectedInitializer => |*x| return x.render(tree, stream),67 .ExpectedInitializer => |*x| return x.render(tree, stream),
68 .ExpectedEnumField => |*x| return x.render(tree, stream),
69 .ExpectedType => |*x| return x.render(tree, stream),
65 .InvalidTypeSpecifier => |*x| return x.render(tree, stream),70 .InvalidTypeSpecifier => |*x| return x.render(tree, stream),
66 .DuplicateQualifier => |*x| return x.render(tree, stream),71 .DuplicateQualifier => |*x| return x.render(tree, stream),
67 .DuplicateSpecifier => |*x| return x.render(tree, stream),72 .DuplicateSpecifier => |*x| return x.render(tree, stream),
73 .MustUseKwToRefer => |*x| return x.render(tree, stream),
68 }74 }
69 }75 }
7076
...@@ -78,9 +84,12 @@ pub const Error = union(enum) {...@@ -78,9 +84,12 @@ pub const Error = union(enum) {
78 .ExpectedDeclarator => |x| return x.token,84 .ExpectedDeclarator => |x| return x.token,
79 .ExpectedFnBody => |x| return x.token,85 .ExpectedFnBody => |x| return x.token,
80 .ExpectedInitializer => |x| return x.token,86 .ExpectedInitializer => |x| return x.token,
87 .ExpectedEnumField => |x| return x.token,
88 .ExpectedType => |*x| return x.token,
81 .InvalidTypeSpecifier => |x| return x.token,89 .InvalidTypeSpecifier => |x| return x.token,
82 .DuplicateQualifier => |x| return x.token,90 .DuplicateQualifier => |x| return x.token,
83 .DuplicateSpecifier => |x| return x.token,91 .DuplicateSpecifier => |x| return x.token,
92 .MustUseKwToRefer => |*x| return x.name,
84 }93 }
85 }94 }
8695
...@@ -111,6 +120,15 @@ pub const Error = union(enum) {...@@ -111,6 +120,15 @@ pub const Error = union(enum) {
111 }120 }
112 };121 };
113122
123 pub const MustUseKwToRefer = struct {
124 kw: TokenIndex,
125 name: TokenIndex,
126
127 pub fn render(self: *const ExpectedToken, tree: *Tree, stream: var) !void {
128 return stream.print("must use '{}' tag to refer to type '{}'", .{tree.slice(kw), tree.slice(name)});
129 }
130 };
131
114 fn SingleTokenError(comptime msg: []const u8) type {132 fn SingleTokenError(comptime msg: []const u8) type {
115 return struct {133 return struct {
116 token: TokenIndex,134 token: TokenIndex,
...@@ -125,14 +143,13 @@ pub const Error = union(enum) {...@@ -125,14 +143,13 @@ pub const Error = union(enum) {
125143
126pub const Type = struct {144pub const Type = struct {
127 pub const TypeList = std.SegmentedList(*Type, 4);145 pub const TypeList = std.SegmentedList(*Type, 4);
128 @"const": bool,146 @"const": bool = false,
129 atomic: bool,147 atomic: bool = false,
130 @"volatile": bool,148 @"volatile": bool = false,
131 restrict: bool,149 restrict: bool = false,
132150
133 id: union(enum) {151 id: union(enum) {
134 Int: struct {152 Int: struct {
135 quals: Qualifiers,
136 id: Id,153 id: Id,
137 is_signed: bool,154 is_signed: bool,
138155
...@@ -145,7 +162,6 @@ pub const Type = struct {...@@ -145,7 +162,6 @@ pub const Type = struct {
145 };162 };
146 },163 },
147 Float: struct {164 Float: struct {
148 quals: Qualifiers,
149 id: Id,165 id: Id,
150166
151 pub const Id = enum {167 pub const Id = enum {
...@@ -154,10 +170,7 @@ pub const Type = struct {...@@ -154,10 +170,7 @@ pub const Type = struct {
154 LongDouble,170 LongDouble,
155 };171 };
156 },172 },
157 Pointer: struct {173 Pointer: *Type,
158 quals: Qualifiers,
159 child_type: *Type,
160 },
161 Function: struct {174 Function: struct {
162 return_type: *Type,175 return_type: *Type,
163 param_types: TypeList,176 param_types: TypeList,
...@@ -173,6 +186,8 @@ pub const Node = struct {...@@ -173,6 +186,8 @@ pub const Node = struct {
173186
174 pub const Id = enum {187 pub const Id = enum {
175 Root,188 Root,
189 EnumField,
190 RecordField,
176 JumpStmt,191 JumpStmt,
177 ExprStmt,192 ExprStmt,
178 Label,193 Label,
...@@ -350,15 +365,16 @@ pub const Node = struct {...@@ -350,15 +365,16 @@ pub const Node = struct {
350 };365 };
351366
352 pub const EnumField = struct {367 pub const EnumField = struct {
353 base: Node = Node{ .id = EnumField },368 base: Node = Node{ .id = .EnumField },
354 name: TokenIndex,369 name: TokenIndex,
355 value: ?*Node,370 value: ?*Node,
356 };371 };
357372
358 pub const RecordType = struct {373 pub const RecordType = struct {
359 kind: union(enum) {374 tok: TokenIndex,
360 Struct: TokenIndex,375 kind: enum {
361 Union: TokenIndex,376 Struct,
377 Union,
362 },378 },
363 name: ?TokenIndex,379 name: ?TokenIndex,
364 body: ?struct {380 body: ?struct {
...@@ -373,8 +389,12 @@ pub const Node = struct {...@@ -373,8 +389,12 @@ pub const Node = struct {
373 };389 };
374390
375 pub const RecordField = struct {391 pub const RecordField = struct {
376 base: Node = Node{ .id = RecordField },392 base: Node = Node{ .id = .RecordField },
377 // TODO393 type_spec: TypeSpec,
394 declarators: DeclaratorList,
395 semicolon: TokenIndex,
396
397 pub const DeclaratorList = Root.DeclList;
378 };398 };
379399
380 pub const TypeQual = struct {400 pub const TypeQual = struct {
lib/std/c/parse.zig+115-15
...@@ -94,12 +94,11 @@ const Parser = struct {...@@ -94,12 +94,11 @@ const Parser = struct {
94 }94 }
9595
96 fn getSymbol(parser: *Parser, tok: TokenIndex) ?*Type {96 fn getSymbol(parser: *Parser, tok: TokenIndex) ?*Type {
97 const token = parser.it.list.at(tok);97 const name = parser.tree.slice(tok);
98 const name = parser.tree.slice(token);
99 const syms = parser.symbols.toSliceConst();98 const syms = parser.symbols.toSliceConst();
100 var i = syms.len;99 var i = syms.len;
101 while (i > 0) : (i -= 1) {100 while (i > 0) : (i -= 1) {
102 if (mem.eql(u8, name, syms[i].name)) {101 if (std.mem.eql(u8, name, syms[i].name)) {
103 return syms[i].ty;102 return syms[i].ty;
104 }103 }
105 }104 }
...@@ -492,31 +491,29 @@ const Parser = struct {...@@ -492,31 +491,29 @@ const Parser = struct {
492 } else if (parser.eatToken(.Keyword_enum)) |tok| {491 } else if (parser.eatToken(.Keyword_enum)) |tok| {
493 if (type_spec.spec != .None)492 if (type_spec.spec != .None)
494 break :blk;493 break :blk;
495 type_spec.Enum = try parser.enumSpec(tok);494 type_spec.spec.Enum = try parser.enumSpec(tok);
496 return true;495 return true;
497 } else if (parser.eatToken(.Keyword_union) orelse parser.eatToken(.Keyword_struct)) |tok| {496 } else if (parser.eatToken(.Keyword_union) orelse parser.eatToken(.Keyword_struct)) |tok| {
498 if (type_spec.spec != .None)497 if (type_spec.spec != .None)
499 break :blk;498 break :blk;
500 type_spec.Record = try parser.recordSpec();499 type_spec.spec.Record = try parser.recordSpec(tok);
501 return true;500 return true;
502 } else if (parser.eatToken(.Identifier)) |tok| {501 } else if (parser.eatToken(.Identifier)) |tok| {
503 const ty = parser.getSymbol(tok) orelse {502 const ty = parser.getSymbol(tok) orelse {
504 parser.putBackToken(tok);503 parser.putBackToken(tok);
505 return false;504 return false;
506 };505 };
507 switch (ty) {506 switch (ty.id) {
508 .Enum => |e| {507 .Enum => |e| {
509 return parser.err(.{508 return parser.err(.{
510 .MustUseKwToRefer = .{ .kw = e.identifier, .sym = tok },509 .MustUseKwToRefer = .{ .kw = e.tok, .name = tok },
511 });510 });
512 },511 },
513 .Record => |r| {512 .Record => |r| {
514 return parser.err(.{513 return parser.err(.{
515 .MustUseKwToRefer = .{514 .MustUseKwToRefer = .{
516 .kw = switch (r.kind) {515 .kw = r.tok,
517 .Struct, .Union => |kw| kw,516 .name = tok,
518 },
519 .sym = tok,
520 },517 },
521 });518 });
522 },519 },
...@@ -613,18 +610,121 @@ const Parser = struct {...@@ -613,18 +610,121 @@ const Parser = struct {
613 }610 }
614611
615 /// EnumSpec <- Keyword_enum IDENTIFIER? (LBRACE EnumField RBRACE)?612 /// EnumSpec <- Keyword_enum IDENTIFIER? (LBRACE EnumField RBRACE)?
616 fn enumSpecifier(parser: *Parser) !*Node {}613 fn enumSpec(parser: *Parser, tok: TokenIndex) !*Node.EnumType {
614 const node = try parser.arena.create(Node.EnumType);
615 const name = parser.eatToken(.Identifier);
616 node.* = .{
617 .tok = tok,
618 .name = name,
619 .body = null,
620 };
621 const ty = try parser.arena.create(Type);
622 ty.* = .{
623 .id = .{
624 .Enum = node,
625 },
626 };
627 if (name) |some|
628 try parser.symbols.append(.{
629 .name = parser.tree.slice(some),
630 .ty = ty,
631 });
632 if (parser.eatToken(.LBrace)) |lbrace| {
633 var fields = Node.EnumType.FieldList.init(parser.arena);
634 try fields.push((try parser.enumField()) orelse return parser.err(.{
635 .ExpectedEnumField = .{ .token = parser.it.index },
636 }));
637 while (parser.eatToken(.Comma)) |_| {
638 try fields.push((try parser.enumField()) orelse break);
639 }
640 node.body = .{
641 .lbrace = lbrace,
642 .fields = fields,
643 .rbrace = try parser.expectToken(.RBrace),
644 };
645 }
646 return node;
647 }
617648
618 /// EnumField <- IDENTIFIER (EQUAL ConstExpr)? (COMMA EnumField) COMMA?649 /// EnumField <- IDENTIFIER (EQUAL ConstExpr)? (COMMA EnumField) COMMA?
619 fn enumField(parser: *Parser) !*Node {}650 fn enumField(parser: *Parser) !?*Node {
651 const name = parser.eatToken(.Identifier) orelse return null;
652 const node = try parser.arena.create(Node.EnumField);
653 node.* = .{
654 .name = name,
655 .value = null,
656 };
657 if (parser.eatToken(.Equal)) |eq| {
658 node.value = try parser.constExpr();
659 }
660 return &node.base;
661 }
620662
621 /// RecordSpec <- (Keyword_struct / Keyword_union) IDENTIFIER? (LBRACE RecordField+ RBRACE)?663 /// RecordSpec <- (Keyword_struct / Keyword_union) IDENTIFIER? (LBRACE RecordField+ RBRACE)?
622 fn recordSpecifier(parser: *Parser) !*Node {}664 fn recordSpec(parser: *Parser, tok: TokenIndex) !*Node.RecordType {
665 const node = try parser.arena.create(Node.RecordType);
666 const name = parser.eatToken(.Identifier);
667 const is_struct = parser.tree.slice(tok)[0] == 's';
668 node.* = .{
669 .tok = tok,
670 .kind = if (is_struct) .Struct else .Union,
671 .name = name,
672 .body = null,
673 };
674 const ty = try parser.arena.create(Type);
675 ty.* = .{
676 .id = .{
677 .Record = node,
678 },
679 };
680 if (name) |some|
681 try parser.symbols.append(.{
682 .name = parser.tree.slice(some),
683 .ty = ty,
684 });
685 if (parser.eatToken(.LBrace)) |lbrace| {
686 var fields = Node.RecordType.FieldList.init(parser.arena);
687 while (true) {
688 if (parser.eatToken(.RBrace)) |rbrace| {
689 node.body = .{
690 .lbrace = lbrace,
691 .fields = fields,
692 .rbrace = rbrace,
693 };
694 break;
695 }
696 try fields.push(try parser.recordField());
697 }
698 }
699 return node;
700 }
623701
624 /// RecordField702 /// RecordField
625 /// <- TypeSpec* (RecordDeclarator (COMMA RecordDeclarator))? SEMICOLON703 /// <- TypeSpec* (RecordDeclarator (COMMA RecordDeclarator))? SEMICOLON
626 /// \ StaticAssert704 /// \ StaticAssert
627 fn recordField(parser: *Parser) !*Node {}705 fn recordField(parser: *Parser) Error!*Node {
706 if (try parser.staticAssert()) |decl| return decl;
707 var got = false;
708 var type_spec = Node.TypeSpec{};
709 while (try parser.typeSpec(&type_spec)) got = true;
710 if (!got)
711 return parser.err(.{
712 .ExpectedType = .{ .token = parser.it.index },
713 });
714 const node = try parser.arena.create(Node.RecordField);
715 node.* = .{
716 .type_spec = type_spec,
717 .declarators = Node.RecordField.DeclaratorList.init(parser.arena),
718 .semicolon = undefined,
719 };
720 while (true) {
721 try node.declarators.push(try parser.recordDeclarator());
722 if (parser.eatToken(.Comma)) |_| {} else break;
723 }
724
725 node.semicolon = try parser.expectToken(.Semicolon);
726 return &node.base;
727 }
628728
629 /// TypeName <- TypeSpec* AbstractDeclarator?729 /// TypeName <- TypeSpec* AbstractDeclarator?
630 fn typeName(parser: *Parser) !*Node {730 fn typeName(parser: *Parser) !*Node {