authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-07 20:15:57+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-07 20:15:57+02:00
logdbc045706809e7135fdb55ebd7c4a7383f40bf0f
treee670539427ec6732a32b37f3e004bc9988d3d6bb
parent4184d4c66a26ba10fbc78cc21f2c73db8f0cfcb2
signaturelock-open Commit is signed but in an unrecognized format.

std-c declaration parsing


2 files changed, 170 insertions(+), 82 deletions(-)

lib/std/c/ast.zig+45-13
...@@ -51,9 +51,14 @@ pub const Error = union(enum) {...@@ -51,9 +51,14 @@ pub const Error = union(enum) {
51 ExpectedEnumField: SingleTokenError("expected enum field, found '{}'"),51 ExpectedEnumField: SingleTokenError("expected enum field, found '{}'"),
52 ExpectedType: SingleTokenError("expected enum field, found '{}'"),52 ExpectedType: SingleTokenError("expected enum field, found '{}'"),
53 InvalidTypeSpecifier: InvalidTypeSpecifier,53 InvalidTypeSpecifier: InvalidTypeSpecifier,
54 InvalidStorageClass: SingleTokenError("invalid storage class, found '{}'"),
55 InvalidDeclarator: SimpleError("invalid declarator"),
54 DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"),56 DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"),
55 DuplicateSpecifier: SingleTokenError("duplicate declaration specifier '{}'"),57 DuplicateSpecifier: SingleTokenError("duplicate declaration specifier '{}'"),
56 MustUseKwToRefer: MustUseKwToRefer,58 MustUseKwToRefer: MustUseKwToRefer,
59 FnSpecOnNonFn: SingleTokenError("function specifier '{}' on non function"),
60 NothingDeclared: SimpleError("declaration doesn't declare anything"),
61 QualifierIgnored: SingleTokenError("qualifier '{}' ignored"),
5762
58 pub fn render(self: *const Error, tree: *Tree, stream: var) !void {63 pub fn render(self: *const Error, tree: *Tree, stream: var) !void {
59 switch (self.*) {64 switch (self.*) {
...@@ -68,9 +73,14 @@ pub const Error = union(enum) {...@@ -68,9 +73,14 @@ pub const Error = union(enum) {
68 .ExpectedEnumField => |*x| return x.render(tree, stream),73 .ExpectedEnumField => |*x| return x.render(tree, stream),
69 .ExpectedType => |*x| return x.render(tree, stream),74 .ExpectedType => |*x| return x.render(tree, stream),
70 .InvalidTypeSpecifier => |*x| return x.render(tree, stream),75 .InvalidTypeSpecifier => |*x| return x.render(tree, stream),
76 .InvalidStorageClass => |*x| return x.render(tree, stream),
77 .InvalidDeclarator => |*x| return x.render(tree, stream),
71 .DuplicateQualifier => |*x| return x.render(tree, stream),78 .DuplicateQualifier => |*x| return x.render(tree, stream),
72 .DuplicateSpecifier => |*x| return x.render(tree, stream),79 .DuplicateSpecifier => |*x| return x.render(tree, stream),
73 .MustUseKwToRefer => |*x| return x.render(tree, stream),80 .MustUseKwToRefer => |*x| return x.render(tree, stream),
81 .FnSpecOnNonFn => |*x| return x.render(tree, stream),
82 .NothingDeclared => |*x| return x.render(tree, stream),
83 .QualifierIgnored => |*x| return x.render(tree, stream),
74 }84 }
75 }85 }
7686
...@@ -87,9 +97,14 @@ pub const Error = union(enum) {...@@ -87,9 +97,14 @@ pub const Error = union(enum) {
87 .ExpectedEnumField => |x| return x.token,97 .ExpectedEnumField => |x| return x.token,
88 .ExpectedType => |*x| return x.token,98 .ExpectedType => |*x| return x.token,
89 .InvalidTypeSpecifier => |x| return x.token,99 .InvalidTypeSpecifier => |x| return x.token,
100 .InvalidStorageClass => |x| return x.token,
101 .InvalidDeclarator => |x| return x.token,
90 .DuplicateQualifier => |x| return x.token,102 .DuplicateQualifier => |x| return x.token,
91 .DuplicateSpecifier => |x| return x.token,103 .DuplicateSpecifier => |x| return x.token,
92 .MustUseKwToRefer => |*x| return x.name,104 .MustUseKwToRefer => |*x| return x.name,
105 .FnSpecOnNonFn => |*x| return x.name,
106 .NothingDeclared => |*x| return x.name,
107 .QualifierIgnored => |*x| return x.name,
93 }108 }
94 }109 }
95110
...@@ -125,7 +140,7 @@ pub const Error = union(enum) {...@@ -125,7 +140,7 @@ pub const Error = union(enum) {
125 name: TokenIndex,140 name: TokenIndex,
126141
127 pub fn render(self: *const ExpectedToken, tree: *Tree, stream: var) !void {142 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)});143 return stream.print("must use '{}' tag to refer to type '{}'", .{ tree.slice(kw), tree.slice(name) });
129 }144 }
130 };145 };
131146
...@@ -139,6 +154,18 @@ pub const Error = union(enum) {...@@ -139,6 +154,18 @@ pub const Error = union(enum) {
139 }154 }
140 };155 };
141 }156 }
157
158 fn SimpleError(comptime msg: []const u8) type {
159 return struct {
160 const ThisError = @This();
161
162 token: TokenIndex,
163
164 pub fn render(self: *const ThisError, tokens: *Tree.TokenList, stream: var) !void {
165 return stream.write(msg);
166 }
167 };
168 }
142};169};
143170
144pub const Type = struct {171pub const Type = struct {
...@@ -194,9 +221,11 @@ pub const Node = struct {...@@ -194,9 +221,11 @@ pub const Node = struct {
194 CompoundStmt,221 CompoundStmt,
195 IfStmt,222 IfStmt,
196 StaticAssert,223 StaticAssert,
197 Fn,224 Declarator,
225 Pointer,
226 FnDecl,
198 Typedef,227 Typedef,
199 Var,228 VarDecl,
200 };229 };
201230
202 pub const Root = struct {231 pub const Root = struct {
...@@ -457,7 +486,7 @@ pub const Node = struct {...@@ -457,7 +486,7 @@ pub const Node = struct {
457486
458 pub const Declarator = struct {487 pub const Declarator = struct {
459 base: Node = Node{ .id = .Declarator },488 base: Node = Node{ .id = .Declarator },
460 pointer: *Pointer,489 pointer: ?*Pointer,
461 prefix: union(enum) {490 prefix: union(enum) {
462 None,491 None,
463 Identifer: TokenIndex,492 Identifer: TokenIndex,
...@@ -482,7 +511,7 @@ pub const Node = struct {...@@ -482,7 +511,7 @@ pub const Node = struct {
482 };511 };
483512
484 pub const Array = struct {513 pub const Array = struct {
485 rbracket: TokenIndex,514 lbracket: TokenIndex,
486 inner: union(enum) {515 inner: union(enum) {
487 Inferred,516 Inferred,
488 Unspecified: TokenIndex,517 Unspecified: TokenIndex,
...@@ -490,7 +519,7 @@ pub const Node = struct {...@@ -490,7 +519,7 @@ pub const Node = struct {
490 asterisk: ?TokenIndex,519 asterisk: ?TokenIndex,
491 static: ?TokenIndex,520 static: ?TokenIndex,
492 qual: TypeQual,521 qual: TypeQual,
493 expr: *Expr,522 // expr: *Expr,
494 },523 },
495 },524 },
496 rbracket: TokenIndex,525 rbracket: TokenIndex,
...@@ -514,10 +543,10 @@ pub const Node = struct {...@@ -514,10 +543,10 @@ pub const Node = struct {
514 },543 },
515 };544 };
516545
517 pub const Fn = struct {546 pub const FnDecl = struct {
518 base: Node = Node{ .id = .Fn },547 base: Node = Node{ .id = .FnDecl },
519 decl_spec: DeclSpec,548 decl_spec: DeclSpec,
520 declarator: *Node,549 declarator: *Declarator,
521 old_decls: OldDeclList,550 old_decls: OldDeclList,
522 body: ?*CompoundStmt,551 body: ?*CompoundStmt,
523552
...@@ -528,20 +557,23 @@ pub const Node = struct {...@@ -528,20 +557,23 @@ pub const Node = struct {
528 base: Node = Node{ .id = .Typedef },557 base: Node = Node{ .id = .Typedef },
529 decl_spec: DeclSpec,558 decl_spec: DeclSpec,
530 declarators: DeclaratorList,559 declarators: DeclaratorList,
560 semicolon: TokenIndex,
531561
532 pub const DeclaratorList = Root.DeclList;562 pub const DeclaratorList = Root.DeclList;
533 };563 };
534564
535 pub const Var = struct {565 pub const VarDecl = struct {
536 base: Node = Node{ .id = .Var },566 base: Node = Node{ .id = .VarDecl },
537 decl_spec: DeclSpec,567 decl_spec: DeclSpec,
538 initializers: Initializers,568 initializers: Initializers,
569 semicolon: TokenIndex,
539570
540 pub const Initializers = std.SegmentedList(*Initialized, 2);571 pub const Initializers = Root.DeclList;
541 };572 };
542573
543 pub const Initialized = struct {574 pub const Initialized = struct {
544 declarator: *Node,575 base: Node = Node{ .id = Initialized },
576 declarator: *Declarator,
545 eq: TokenIndex,577 eq: TokenIndex,
546 init: Initializer,578 init: Initializer,
547 };579 };
lib/std/c/parse.zig+125-69
...@@ -105,6 +105,10 @@ const Parser = struct {...@@ -105,6 +105,10 @@ const Parser = struct {
105 return null;105 return null;
106 }106 }
107107
108 fn declareSymbol(parser: *Parser, decl_spec: *Node.DeclSpec, dr: *Node.Declarator) Error!void {
109 return; // TODO
110 }
111
108 /// Root <- ExternalDeclaration* eof112 /// Root <- ExternalDeclaration* eof
109 fn root(parser: *Parser) Allocator.Error!*Node.Root {113 fn root(parser: *Parser) Allocator.Error!*Node.Root {
110 const node = try parser.arena.create(Node.Root);114 const node = try parser.arena.create(Node.Root);
...@@ -140,77 +144,127 @@ const Parser = struct {...@@ -140,77 +144,127 @@ const Parser = struct {
140144
141 fn declarationExtra(parser: *Parser, local: bool) !?*Node {145 fn declarationExtra(parser: *Parser, local: bool) !?*Node {
142 if (try parser.staticAssert()) |decl| return decl;146 if (try parser.staticAssert()) |decl| return decl;
147 const begin = parser.it.index + 1;
143 var ds = Node.DeclSpec{};148 var ds = Node.DeclSpec{};
144 const got_ds = try parser.declSpec(&ds);149 const got_ds = try parser.declSpec(&ds);
145 if (local and !got_ds) {150 if (local and !got_ds) {
146 // not a declaration151 // not a declaration
147 return null;152 return null;
148 }153 }
149 var dr = try parser.declarator();154 switch (ds.storage_class) {
150 // TODO disallow auto and register155 .Auto, .Register => |tok| return parser.err(.{
151 const next_tok = parser.it.peek().?;156 .InvalidStorageClass = .{ .token = tok },
152 if (next_tok.id == .Eof and !got_ds and dr == null) {157 }),
153 return null;158 .Typedef => {
154 }159 const node = try parser.arena.create(Node.Typedef);
155 switch (next_tok.id) {160 node.* = .{
156 .Semicolon,161 .decl_spec = ds,
157 .Equal,162 .declarators = Node.Typedef.DeclaratorList.init(parser.arena),
158 .Comma,163 .semicolon = undefined,
159 .Eof,164 };
160 => {165 while (true) {
161 while (dr != null) {166 const dr = @fieldParentPtr(Node.Declarator, "base", (try parser.declarator(.Must)) orelse return parser.err(.{
162 if (parser.eatToken(.Equal)) |tok| {
163 // TODO typedef
164 // dr.?.init = try parser.expect(initializer, .{
165 // .ExpectedInitializer = .{ .token = parser.it.index },
166 // });
167 }
168 if (parser.eatToken(.Comma) != null) break;
169 dr = (try parser.declarator()) orelse return parser.err(.{
170 .ExpectedDeclarator = .{ .token = parser.it.index },167 .ExpectedDeclarator = .{ .token = parser.it.index },
171 });168 }));
172 // .push(dr);169 try parser.declareSymbol(&ds, dr);
170 try node.declarators.push(&dr.base);
171 if (parser.eatToken(.Comma)) |_| {} else break;
173 }172 }
174 const semicolon = try parser.expectToken(.Semicolon);173 return &node.base;
175
176 // TODO VarDecl, TypeDecl, TypeDef
177 return null;
178 },174 },
179 else => {175 else => {},
180 if (dr == null)176 }
181 return parser.err(.{177 var first_dr = try parser.declarator(.Must);
182 .ExpectedDeclarator = .{ .token = parser.it.index },178 if (first_dr != null and declaratorIsFunction(first_dr.?)) {
183 });179 const dr = @fieldParentPtr(Node.Declarator, "base", first_dr.?);
184 var old_decls = Node.FnDef.OldDeclList.init(parser.arena);180 try parser.declareSymbol(&ds, dr);
185 while (true) {181 var old_decls = Node.FnDecl.OldDeclList.init(parser.arena);
186 var old_ds = Node.DeclSpec{};182 const body = if (parser.eatToken(.Semicolon)) |_|
187 if (!(try parser.declSpec(&old_ds))) {183 null
188 // not old decl184 else blk: {
189 break;185 // TODO first_dr.is_old
190 }186 // while (true) {
191 var old_dr = (try parser.declarator());187 // var old_ds = Node.DeclSpec{};
192 // if (old_dr == null)188 // if (!(try parser.declSpec(&old_ds))) {
193 // try parser.err(.{189 // // not old decl
194 // .NoParamName = .{ .token = parser.it.index },190 // break;
195 // });191 // }
196 // try old_decls.push(decl);192 // var old_dr = (try parser.declarator(.Must));
197 }193 // // if (old_dr == null)
198 const body = (try parser.compoundStmt()) orelse return parser.err(.{194 // // try parser.err(.{
195 // // .NoParamName = .{ .token = parser.it.index },
196 // // });
197 // // try old_decls.push(decl);
198 // }
199 const body_node = (try parser.compoundStmt()) orelse return parser.err(.{
199 .ExpectedFnBody = .{ .token = parser.it.index },200 .ExpectedFnBody = .{ .token = parser.it.index },
200 });201 });
202 break :blk @fieldParentPtr(Node.CompoundStmt, "base", body_node);
203 };
201204
202 const node = try parser.arena.create(Node.FnDef);205 const node = try parser.arena.create(Node.FnDecl);
203 node.* = .{206 node.* = .{
204 .decl_spec = ds,207 .decl_spec = ds,
205 .declarator = dr orelse return null,208 .declarator = dr,
206 .old_decls = old_decls,209 .old_decls = old_decls,
207 .body = @fieldParentPtr(Node.CompoundStmt, "base", body),210 .body = body,
211 };
212 return &node.base;
213 } else {
214 switch (ds.fn_spec) {
215 .Inline, .Noreturn => |tok| return parser.err(.{
216 .FnSpecOnNonFn = .{ .token = tok },
217 }),
218 else => {},
219 }
220 // TODO threadlocal without static or extern on local variable
221 const node = try parser.arena.create(Node.VarDecl);
222 node.* = .{
223 .decl_spec = ds,
224 .initializers = Node.VarDecl.Initializers.init(parser.arena),
225 .semicolon = undefined,
226 };
227 if (first_dr == null) {
228 node.semicolon = try parser.expectToken(.Semicolon);
229 const ok = switch (ds.type_spec.spec) {
230 .Enum => |e| e.name != null,
231 .Record => |r| r.name != null,
232 else => false,
208 };233 };
234 const q = ds.type_spec.qual;
235 if (!ok)
236 try parser.warn(.{
237 .NothingDeclared = .{ .token = begin },
238 })
239 else if (q.@"const" orelse q.atomic orelse q.@"volatile" orelse q.restrict) |tok|
240 try parser.warn(.{
241 .QualifierIgnored = .{ .token = tok },
242 });
209 return &node.base;243 return &node.base;
210 },244 }
245 var dr = @fieldParentPtr(Node.Declarator, "base", first_dr.?);
246 while (true) {
247 try parser.declareSymbol(&ds, dr);
248 if (parser.eatToken(.Equal)) |tok| {
249 try node.initializers.push((try parser.initializer(dr)) orelse return parser.err(.{
250 .ExpectedInitializer = .{ .token = parser.it.index },
251 }));
252 } else
253 try node.initializers.push(&dr.base);
254 if (parser.eatToken(.Comma) != null) break;
255 dr = @fieldParentPtr(Node.Declarator, "base", (try parser.declarator(.Must)) orelse return parser.err(.{
256 .ExpectedDeclarator = .{ .token = parser.it.index },
257 }));
258 }
259 node.semicolon = try parser.expectToken(.Semicolon);
260 return &node.base;
211 }261 }
212 }262 }
213263
264 fn declaratorIsFunction(dr: *Node) bool {
265 return false; // TODO
266 }
267
214 /// StaticAssert <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON268 /// StaticAssert <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON
215 fn staticAssert(parser: *Parser) !?*Node {269 fn staticAssert(parser: *Parser) !?*Node {
216 const tok = parser.eatToken(.Keyword_static_assert) orelse return null;270 const tok = parser.eatToken(.Keyword_static_assert) orelse return null;
...@@ -733,7 +787,7 @@ const Parser = struct {...@@ -733,7 +787,7 @@ const Parser = struct {
733 fn recordDeclarator(parser: *Parser) !*Node {}787 fn recordDeclarator(parser: *Parser) !*Node {}
734788
735 /// Pointer <- ASTERISK TypeQual* Pointer?789 /// Pointer <- ASTERISK TypeQual* Pointer?
736 fn pointer(parser: *Parser) Error!?*Node {790 fn pointer(parser: *Parser) Error!?*Node.Pointer {
737 const asterisk = parser.eatToken(.Asterisk) orelse return null;791 const asterisk = parser.eatToken(.Asterisk) orelse return null;
738 const node = try parser.arena.create(Node.Pointer);792 const node = try parser.arena.create(Node.Pointer);
739 node.* = .{793 node.* = .{
...@@ -743,7 +797,7 @@ const Parser = struct {...@@ -743,7 +797,7 @@ const Parser = struct {
743 };797 };
744 while (try parser.typeQual(&node.qual)) {}798 while (try parser.typeQual(&node.qual)) {}
745 node.pointer = try parser.pointer();799 node.pointer = try parser.pointer();
746 return &node.base;800 return node;
747 }801 }
748802
749 const Named = enum {803 const Named = enum {
...@@ -772,7 +826,7 @@ const Parser = struct {...@@ -772,7 +826,7 @@ const Parser = struct {
772 node.* = .{826 node.* = .{
773 .pointer = ptr,827 .pointer = ptr,
774 .prefix = .{828 .prefix = .{
775 .Comples = .{829 .Complex = .{
776 .lparen = lparen,830 .lparen = lparen,
777 .inner = inner,831 .inner = inner,
778 .rparen = try parser.expectToken(.RParen),832 .rparen = try parser.expectToken(.RParen),
...@@ -785,7 +839,7 @@ const Parser = struct {...@@ -785,7 +839,7 @@ const Parser = struct {
785 node = try parser.arena.create(Node.Declarator);839 node = try parser.arena.create(Node.Declarator);
786 node.* = .{840 node.* = .{
787 .pointer = ptr,841 .pointer = ptr,
788 .prefix = .{ .Simple = tok },842 .prefix = .{ .Identifer = tok },
789 .suffix = .None,843 .suffix = .None,
790 };844 };
791 } else if (named == .Must) {845 } else if (named == .Must) {
...@@ -793,7 +847,9 @@ const Parser = struct {...@@ -793,7 +847,9 @@ const Parser = struct {
793 .ExpectedToken = .{ .token = parser.it.index, .expected_id = .Identifier },847 .ExpectedToken = .{ .token = parser.it.index, .expected_id = .Identifier },
794 });848 });
795 } else {849 } else {
796 return ptr;850 if (ptr) |some|
851 return &some.base;
852 return null;
797 }853 }
798 } else {854 } else {
799 node = try parser.arena.create(Node.Declarator);855 node = try parser.arena.create(Node.Declarator);
...@@ -808,16 +864,16 @@ const Parser = struct {...@@ -808,16 +864,16 @@ const Parser = struct {
808 node.suffix = .{864 node.suffix = .{
809 .Fn = .{865 .Fn = .{
810 .lparen = lparen,866 .lparen = lparen,
811 .params = .Node.Declarator.Params.init(parser.arena),867 .params = Node.Declarator.Params.init(parser.arena),
812 .rparen = undefined,868 .rparen = undefined,
813 },869 },
814 };870 };
815 try parser.ParamDecl(node);871 try parser.paramDecl(node);
816 node.suffix.Fn.rparen = try parser.expectToken(.RParen);872 node.suffix.Fn.rparen = try parser.expectToken(.RParen);
817 } else {873 } else {
818 while (parser.arrayDeclarator()) |arr| {874 while (try parser.arrayDeclarator()) |arr| {
819 if (node.suffix == .None)875 if (node.suffix == .None)
820 node.suffix = .{ .Array = .Node.Declarator.Arrays.init(parser.arena) };876 node.suffix = .{ .Array = Node.Declarator.Arrays.init(parser.arena) };
821 try node.suffix.Array.push(arr);877 try node.suffix.Array.push(arr);
822 }878 }
823 }879 }
...@@ -825,7 +881,7 @@ const Parser = struct {...@@ -825,7 +881,7 @@ const Parser = struct {
825 return parser.err(.{881 return parser.err(.{
826 .InvalidDeclarator = .{ .token = tok },882 .InvalidDeclarator = .{ .token = tok },
827 });883 });
828 return node;884 return &node.base;
829 }885 }
830886
831 /// ArrayDeclarator887 /// ArrayDeclarator
...@@ -834,11 +890,11 @@ const Parser = struct {...@@ -834,11 +890,11 @@ const Parser = struct {
834 /// / TypeQual+ (ASTERISK / Keyword_static AssignmentExpr)890 /// / TypeQual+ (ASTERISK / Keyword_static AssignmentExpr)
835 /// / TypeQual+ AssignmentExpr?891 /// / TypeQual+ AssignmentExpr?
836 /// / AssignmentExpr892 /// / AssignmentExpr
837 fn arrayDeclarator(parser: *Parser, dr: *Node.Declarator) !?*Node.Array {893 fn arrayDeclarator(parser: *Parser) !?*Node.Array {
838 const lbracket = parser.eatToken(.LBracket) orelse return null;894 const lbracket = parser.eatToken(.LBracket) orelse return null;
839 const arr = try parser.arena.create(Node.Array);895 const arr = try parser.arena.create(Node.Array);
840 arr.* = .{896 arr.* = .{
841 .lbracket = lbarcket,897 .lbracket = lbracket,
842 .inner = .Inferred,898 .inner = .Inferred,
843 .rbracket = undefined,899 .rbracket = undefined,
844 };900 };
...@@ -856,12 +912,12 @@ const Parser = struct {...@@ -856,12 +912,12 @@ const Parser = struct {
856 fn paramDecl(parser: *Parser, dr: *Node.Declarator) !void {912 fn paramDecl(parser: *Parser, dr: *Node.Declarator) !void {
857 var old_style = false;913 var old_style = false;
858 while (true) {914 while (true) {
859 var ds = Node.DeclSpec;915 var ds = Node.DeclSpec{};
860 if (try parser.declSpec(&ds)) {916 if (try parser.declSpec(&ds)) {
861 //TODO917 //TODO
862 } else if (parser.eatToken(.Identifier)) {918 } else if (parser.eatToken(.Identifier)) |tok| {
863 old_style = true;919 old_style = true;
864 } else if (parser.eatToken(.Ellipsis)) {920 } else if (parser.eatToken(.Ellipsis)) |tok| {
865 // TODO921 // TODO
866 }922 }
867 }923 }