authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-05 00:33:34+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-05 20:25:51+02:00
log25f7f66b8fb882a9b0abcad1baed851fabc464de
treec30d0ee976874142447c987f3e6f9169e66c63f7
parentdccf1247b21ee2b15f6ec3c01c908b29b5c60f24
signature Commit is signed but in an unrecognized format.

std-c type parsing


2 files changed, 360 insertions(+), 29 deletions(-)

lib/std/c/ast.zig+84-3
......@@ -26,10 +26,12 @@ pub const Tree = struct {
2626};
2727
2828pub const Error = union(enum) {
29 InvalidToken: SingleTokenError("Invalid token '{}'"),
29 InvalidToken: SingleTokenError("invalid token '{}'"),
3030 ExpectedToken: ExpectedToken,
31 ExpectedExpr: SingleTokenError("Expected expression, found '{}'"),
32 ExpectedStmt: SingleTokenError("Expected statement, found '{}'"),
31 ExpectedExpr: SingleTokenError("expected expression, found '{}'"),
32 ExpectedStmt: SingleTokenError("expected statement, found '{}'"),
33 InvalidTypeSpecifier: InvalidTypeSpecifier,
34 DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"),
3335
3436 pub fn render(self: *const Error, tokens: *Tree.TokenList, stream: var) !void {
3537 switch (self.*) {
......@@ -37,6 +39,8 @@ pub const Error = union(enum) {
3739 .ExpectedToken => |*x| return x.render(tokens, stream),
3840 .ExpectedExpr => |*x| return x.render(tokens, stream),
3941 .ExpectedStmt => |*x| return x.render(tokens, stream),
42 .InvalidTypeSpecifier => |*x| return x.render(tokens, stream),
43 .DuplicateQualifier => |*x| return x.render(tokens, stream),
4044 }
4145 }
4246
......@@ -46,6 +50,8 @@ pub const Error = union(enum) {
4650 .ExpectedToken => |x| return x.token,
4751 .ExpectedExpr => |x| return x.token,
4852 .ExpectedStmt => |x| return x.token,
53 .InvalidTypeSpecifier => |x| return x.token,
54 .DuplicateQualifier => |x| return x.token,
4955 }
5056 }
5157
......@@ -64,6 +70,18 @@ pub const Error = union(enum) {
6470 }
6571 };
6672
73 pub const InvalidTypeSpecifier = struct {
74 token: TokenIndex,
75 type: *Node.Type,
76
77 pub fn render(self: *const ExpectedToken, tokens: *Tree.TokenList, stream: var) !void {
78 try stream.write("invalid type specifier '");
79 try type.specifier.print(tokens, stream);
80 const token_name = tokens.at(self.token).id.symbol();
81 return stream.print("{}'", .{ token_name });
82 }
83 };
84
6785 fn SingleTokenError(comptime msg: []const u8) type {
6886 return struct {
6987 token: TokenIndex,
......@@ -96,6 +114,69 @@ pub const Node = struct {
96114 pub const DeclList = SegmentedList(*Node, 4);
97115 };
98116
117 pub const Type = struct {
118 qualifiers: Qualifiers,
119 specifier: union(enum) {
120 /// error or default to int
121 None,
122 Void: TokenIndex,
123 Char: struct {
124 sign: ?TokenIndex = null,
125 char: TokenIndex,
126 },
127 Short: struct {
128 sign: ?TokenIndex = null,
129 short: TokenIndex = null,
130 int: ?TokenIndex = null,
131 },
132 Int: struct {
133 sign: ?TokenIndex = null,
134 int: ?TokenIndex = null,
135 },
136 Long: struct {
137 sign: ?TokenIndex = null,
138 long: TokenIndex,
139 longlong: ?TokenIndex = null,
140 int: ?TokenIndex = null,
141 },
142 Float: struct {
143 float: TokenIndex,
144 complex: ?TokenIndex = null,
145 },
146 Double: struct {
147 long: ?TokenIndex = null,
148 double: ?TokenIndex,
149 complex: ?TokenIndex = null,
150 },
151 Bool: TokenIndex,
152 Atomic: struct {
153 atomic: TokenIndex,
154 typename: *Node,
155 rparen: TokenIndex,
156 },
157
158 //todo
159 // @"enum",
160 // record,
161
162 Typedef: TokenIndex,
163
164 pub fn print(self: *@This(), self: *const @This(), tokens: *Tree.TokenList, stream: var) !void {
165 switch (self) {
166 .None => unreachable,
167 else => @panic("TODO print type specifier"),
168 }
169 }
170 },
171 };
172
173 pub const Qualifiers = struct {
174 @"const": ?TokenIndex = null,
175 atomic: ?TokenIndex = null,
176 @"volatile": ?TokenIndex = null,
177 restrict: ?TokenIndex = null,
178 };
179
99180 pub const JumpStmt = struct {
100181 base: Node = Node{ .id = .JumpStmt },
101182 ltoken: TokenIndex,
lib/std/c/parse.zig+276-26
......@@ -109,35 +109,284 @@ const Parser = struct {
109109 fn staticAssertDeclaration(parser: *Parser) !?*Node {}
110110
111111 /// DeclarationSpecifiers
112 /// <- StorageClassSpecifier DeclarationSpecifiers?
113 /// / TypeSpecifier DeclarationSpecifiers?
114 /// / TypeQualifier DeclarationSpecifiers?
115 /// / FunctionSpecifier DeclarationSpecifiers?
116 /// / AlignmentSpecifier DeclarationSpecifiers?
112 /// <- (Keyword_typedef / Keyword_extern / Keyword_static / Keyword_thread_local / Keyword_auto / Keyword_register
113 /// / Type
114 /// / Keyword_inline / Keyword_noreturn
115 /// / Keyword_alignas LPAREN (TypeName / ConstExpr) RPAREN)*
117116 fn declarationSpecifiers(parser: *Parser) !*Node {}
118117
119 /// StorageClassSpecifier
120 /// <- Keyword_typedef / Keyword_extern / Keyword_static / Keyword_thread_local / Keyword_auto / Keyword_register
121 fn storageClassSpecifier(parser: *Parser) !*Node {}
122
123 /// TypeSpecifier
118 /// Type
124119 /// <- Keyword_void / Keyword_char / Keyword_short / Keyword_int / Keyword_long / Keyword_float / Keyword_double
125120 /// / Keyword_signed / Keyword_unsigned / Keyword_bool / Keyword_complex / Keyword_imaginary /
126121 /// / Keyword_atomic LPAREN TypeName RPAREN
127122 /// / EnumSpecifier
128123 /// / RecordSpecifier
129124 /// / IDENTIFIER // typedef name
130 fn typeSpecifier(parser: *Parser) !*Node {}
125 /// / TypeQualifier
126 fn type(parser: *Parser, type: *Node.Type) !bool {
127 while (try parser.typeQualifier(type.qualifiers)) {}
128 blk: {
129 if (parser.eatToken(.Keyword_void)) |tok| {
130 if (type.specifier != .None)
131 break :blk;
132 type.specifier = .{ .Void = tok };
133 return true;
134 } else if (parser.eatToken(.Keyword_char)) |tok| {
135 switch (type.specifier) {
136 .None => {
137 type.specifier = .{
138 .Char = .{
139 .char = tok,
140 },
141 };
142 },
143 .Int => |int| {
144 if (int.int != null)
145 break :blk;
146 type.specifier = .{
147 .Char = .{
148 .char = tok,
149 .sign = int.sign,
150 },
151 };
152 },
153 else => break :blk,
154 }
155 return true;
156 } else if (parser.eatToken(.Keyword_short)) |tok| {
157 switch (type.specifier) {
158 .None => {
159 type.specifier = .{
160 .Short = .{
161 .short = tok,
162 },
163 };
164 },
165 .Int => |int| {
166 if (int.int != null)
167 break :blk;
168 type.specifier = .{
169 .Short = .{
170 .short = tok,
171 .sign = int.sign,
172 },
173 };
174 },
175 else => break :blk,
176 }
177 return true;
178 } else if (parser.eatToken(.Keyword_long)) |tok| {
179 switch (type.specifier) {
180 .None => {
181 type.specifier = .{
182 .Long = .{
183 .long = tok,
184 },
185 };
186 },
187 .Int => |int| {
188 type.specifier = .{
189 .Long = .{
190 .long = tok,
191 .sign = int.sign,
192 .int = int.int,
193 },
194 };
195 },
196 .Long => |*long| {
197 if (long.longlong != null)
198 break :blk;
199 long.longlong = tok;
200 },
201 .Double => |*double| {
202 if (double.long != null)
203 break :blk;
204 double.long = tok;
205 },
206 else => break :blk,
207 }
208 return true;
209 } else if (parser.eatToken(.Keyword_int)) |tok| {
210 switch (type.specifier) {
211 .None => {
212 type.specifier = .{
213 .Int = .{
214 .int = tok,
215 },
216 };
217 },
218 .Short => |*short| {
219 if (short.int != null)
220 break :blk;
221 short.int = tok;
222 },
223 .Int => |*int| {
224 if (int.int != null)
225 break :blk;
226 int.int = tok;
227 },
228 .Long => |*long| {
229 if (long.int != null)
230 break :blk;
231 long.int = tok;
232 },
233 else => break :blk,
234 }
235 return true;
236 } else if (parser.eatToken(.Keyword_signed) orelse parser.eatToken(.Keyword_unsigned)) |tok| {
237 switch (type.specifier) {
238 .None => {
239 type.specifier = .{
240 .Int = .{
241 .sign = tok,
242 },
243 };
244 },
245 .Char => |*char| {
246 if (char.sign != null)
247 break :blk;
248 char.sign = tok;
249 },
250 .Short => |*short| {
251 if (short.sign != null)
252 break :blk;
253 short.sign = tok;
254 },
255 .Int => |*int| {
256 if (int.sign != null)
257 break :blk;
258 int.sign = tok;
259 },
260 .Long => |*long| {
261 if (long.sign != null)
262 break :blk;
263 long.sign = tok;
264 },
265 else => break :blk,
266 }
267 return true;
268 } else if (parser.eatToken(.Keyword_float)) |tok| {
269 if (type.specifier != .None)
270 break :blk;
271 type.specifier = .{
272 .Float = .{
273 .float = tok,
274 },
275 };
276 return true;
277 } else if (parser.eatToken(.Keyword_double)) |tok| {
278 if (type.specifier != .None)
279 break :blk;
280 type.specifier = .{
281 .Double = .{
282 .double = tok,
283 },
284 };
285 return true;
286 } else if (parser.eatToken(.Keyword_complex)) |tok| {
287 switch (type.specifier) {
288 .None => {
289 type.specifier = .{
290 .Double = .{
291 .complex = tok,
292 .double = null
293 },
294 };
295 },
296 .Float => |*float| {
297 if (float.complex != null)
298 break :blk;
299 float.complex = tok;
300 },
301 .Double => |*double| {
302 if (double.complex != null)
303 break :blk;
304 double.complex = tok;
305 },
306 else => break :blk,
307 }
308 return true;
309 } if (parser.eatToken(.Keyword_bool)) |tok| {
310 if (type.specifier != .None)
311 break :blk;
312 type.specifier = .{ .Bool = tok };
313 return true;
314 } else if (parser.eatToken(.Keyword_atomic)) |tok| {
315 if (type.specifier != .None)
316 break :blk;
317 _ = try parser.expectToken(.LParen);
318 const name = try parser.expect(typeName, .{
319 .ExpectedTypeName = .{ .tok = it.index },
320 });
321 type.specifier.Atomic = .{
322 .atomic = tok,
323 .typename = name,
324 .rparen = try parser.expectToken(.RParen),
325 };
326 return true;
327 } else if (parser.eatToken(.Keyword_enum)) |tok| {
328 if (type.specifier != .None)
329 break :blk;
330 @panic("TODO enum type");
331 // return true;
332 } else if (parser.eatToken(.Keyword_union) orelse parser.eatToken(.Keyword_struct)) |tok| {
333 if (type.specifier != .None)
334 break :blk;
335 @panic("TODO record type");
336 // return true;
337 } else if (parser.eatToken(.Identifier)) |tok| {
338 if (!parser.typedefs.contains(tok)) {
339 parser.putBackToken(tok);
340 return false;
341 }
342 type.specifier = .{
343 .Typedef = tok,
344 };
345 return true;
346 }
347 }
348 try parser.tree.errors.push(.{
349 .InvalidTypeSpecifier = .{
350 .token = parser.it.index,
351 .type = type,
352 },
353 });
354 return error.ParseError;
355 }
131356
132357 /// TypeQualifier <- Keyword_const / Keyword_restrict / Keyword_volatile / Keyword_atomic
133 fn typeQualifier(parser: *Parser) !*Node {}
358 fn typeQualifier(parser: *Parser, qualifiers: *Node.Qualifiers) !bool {
359 if (parser.eatToken(.Keyword_const)) |tok| {
360 if (qualifiers.@"const" != null)
361 return parser.warning(.{
362 .DuplicateQualifier = .{ .token = tok },
363 });
364 qualifiers.@"const" = tok;
365 } else if (parser.eatToken(.Keyword_restrict)) |tok| {
366 if (qualifiers.atomic != null)
367 return parser.warning(.{
368 .DuplicateQualifier = .{ .token = tok },
369 });
370 qualifiers.atomic = tok;
371 } else if (parser.eatToken(.Keyword_volatile)) |tok| {
372 if (qualifiers.@"volatile" != null)
373 return parser.warning(.{
374 .DuplicateQualifier = .{ .token = tok },
375 });
376 qualifiers.@"volatile" = tok;
377 } else if (parser.eatToken(.Keyword_atomic)) |tok| {
378 if (qualifiers.atomic != null)
379 return parser.warning(.{
380 .DuplicateQualifier = .{ .token = tok },
381 });
382 qualifiers.atomic = tok;
383 } else return false;
384 return true;
385 }
134386
135387 /// FunctionSpecifier <- Keyword_inline / Keyword_noreturn
136388 fn functionSpecifier(parser: *Parser) !*Node {}
137389
138 /// AlignmentSpecifier <- Keyword_alignas LPAREN (TypeName / ConstExpr) RPAREN
139 fn alignmentSpecifier(parser: *Parser) !*Node {}
140
141390 /// EnumSpecifier <- Keyword_enum IDENTIFIER? (LBRACE EnumField RBRACE)?
142391 fn enumSpecifier(parser: *Parser) !*Node {}
143392
......@@ -148,19 +397,14 @@ const Parser = struct {
148397 fn recordSpecifier(parser: *Parser) !*Node {}
149398
150399 /// RecordField
151 /// <- SpecifierQualifer (RecordDeclarator (COMMA RecordDeclarator))? SEMICOLON
400 /// <- Type* (RecordDeclarator (COMMA RecordDeclarator))? SEMICOLON
152401 /// \ StaticAssertDeclaration
153402 fn recordField(parser: *Parser) !*Node {}
154403
155404 /// TypeName
156 /// <- SpecifierQualifer AbstractDeclarator?
405 /// <- Type* AbstractDeclarator?
157406 fn typeName(parser: *Parser) !*Node {}
158407
159 /// SpecifierQualifer
160 /// <- TypeSpecifier SpecifierQualifer?
161 /// / TypeQualifier SpecifierQualifer?
162 fn specifierQualifer(parser: *Parser) !*Node {}
163
164408 /// RecordDeclarator <- Declarator? (COLON ConstExpr)?
165409 fn recordDeclarator(parser: *Parser) !*Node {}
166410
......@@ -329,7 +573,7 @@ const Parser = struct {
329573 if (parser.eatToken(.Keyword_else)) |else_tok| {
330574 node.@"else" = .{
331575 .tok = else_tok,
332 .stmt = try parser.stmt(expr, .{
576 .stmt = try parser.stmt(expr, .{
333577 .ExpectedStmt = .{ .token = it.index },
334578 }),
335579 };
......@@ -431,11 +675,11 @@ const Parser = struct {
431675 }
432676 }
433677
434 fn putBackToken(it: *TokenIterator, putting_back: TokenIndex) void {
678 fn putBackToken(parser: *Parser, putting_back: TokenIndex) void {
435679 while (true) {
436 const prev_tok = it.prev() orelse return;
680 const prev_tok = parser.it.prev() orelse return;
437681 if (next_tok.id == .LineComment or next_tok.id == .MultiLineComment) continue;
438 assert(it.list.at(putting_back) == prev_tok);
682 assert(parser.it.list.at(putting_back) == prev_tok);
439683 return;
440684 }
441685 }
......@@ -450,4 +694,10 @@ const Parser = struct {
450694 return error.ParseError;
451695 };
452696 }
697
698 fn warning(parser: *Parser, err: ast.Error) Error {
699 // if (parser.warnaserror)
700 try parser.tree.errors.push(err);
701 return error.ParseError;
702 }
453703};