authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-05 13:24:10+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-05 20:25:51+02:00
log46f292982d6035c7d57ae8d637c770a121c40e37
tree8f103c5572630359d0a4fe119a86b58422a54fe6
parent25f7f66b8fb882a9b0abcad1baed851fabc464de
signature Commit is signed but in an unrecognized format.

std-c parser DeclSpec


4 files changed, 232 insertions(+), 109 deletions(-)

lib/std/c.zig+1-1
...@@ -2,7 +2,7 @@ const builtin = @import("builtin");...@@ -2,7 +2,7 @@ const builtin = @import("builtin");
2const std = @import("std");2const std = @import("std");
3const page_size = std.mem.page_size;3const page_size = std.mem.page_size;
44
5const tokenizer = @import("c/tokenizer.zig");5pub const tokenizer = @import("c/tokenizer.zig");
6pub const Token = tokenizer.Token;6pub const Token = tokenizer.Token;
7pub const Tokenizer = tokenizer.Tokenizer;7pub const Tokenizer = tokenizer.Tokenizer;
8pub const parse = @import("c/parse.zig").parse;8pub const parse = @import("c/parse.zig").parse;
lib/std/c/ast.zig+38-8
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1const std = @import("std.zig");1const std = @import("std");
2const SegmentedList = std.SegmentedList;2const SegmentedList = std.SegmentedList;
3const Token = std.c.Token;3const Token = std.c.Token;
4const Source = std.c.tokenizer.Source;4const Source = std.c.tokenizer.Source;
...@@ -11,6 +11,7 @@ pub const Tree = struct {...@@ -11,6 +11,7 @@ pub const Tree = struct {
11 root_node: *Node.Root,11 root_node: *Node.Root,
12 arena_allocator: std.heap.ArenaAllocator,12 arena_allocator: std.heap.ArenaAllocator,
13 errors: ErrorList,13 errors: ErrorList,
14 warnings: ?ErrorList,
1415
15 pub const SourceList = SegmentedList(Source, 4);16 pub const SourceList = SegmentedList(Source, 4);
16 pub const TokenList = Source.TokenList;17 pub const TokenList = Source.TokenList;
...@@ -30,8 +31,10 @@ pub const Error = union(enum) {...@@ -30,8 +31,10 @@ pub const Error = union(enum) {
30 ExpectedToken: ExpectedToken,31 ExpectedToken: ExpectedToken,
31 ExpectedExpr: SingleTokenError("expected expression, found '{}'"),32 ExpectedExpr: SingleTokenError("expected expression, found '{}'"),
32 ExpectedStmt: SingleTokenError("expected statement, found '{}'"),33 ExpectedStmt: SingleTokenError("expected statement, found '{}'"),
34 ExpectedTypeName: SingleTokenError("expected type name, found '{}'"),
33 InvalidTypeSpecifier: InvalidTypeSpecifier,35 InvalidTypeSpecifier: InvalidTypeSpecifier,
34 DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"),36 DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"),
37 DuplicateSpecifier: SingleTokenError("duplicate declaration specifier '{}'"),
3538
36 pub fn render(self: *const Error, tokens: *Tree.TokenList, stream: var) !void {39 pub fn render(self: *const Error, tokens: *Tree.TokenList, stream: var) !void {
37 switch (self.*) {40 switch (self.*) {
...@@ -39,8 +42,10 @@ pub const Error = union(enum) {...@@ -39,8 +42,10 @@ pub const Error = union(enum) {
39 .ExpectedToken => |*x| return x.render(tokens, stream),42 .ExpectedToken => |*x| return x.render(tokens, stream),
40 .ExpectedExpr => |*x| return x.render(tokens, stream),43 .ExpectedExpr => |*x| return x.render(tokens, stream),
41 .ExpectedStmt => |*x| return x.render(tokens, stream),44 .ExpectedStmt => |*x| return x.render(tokens, stream),
45 .ExpectedTypeName => |*x| return x.render(tokens, stream),
42 .InvalidTypeSpecifier => |*x| return x.render(tokens, stream),46 .InvalidTypeSpecifier => |*x| return x.render(tokens, stream),
43 .DuplicateQualifier => |*x| return x.render(tokens, stream),47 .DuplicateQualifier => |*x| return x.render(tokens, stream),
48 .DuplicateSpecifier => |*x| return x.render(tokens, stream),
44 }49 }
45 }50 }
4651
...@@ -50,8 +55,10 @@ pub const Error = union(enum) {...@@ -50,8 +55,10 @@ pub const Error = union(enum) {
50 .ExpectedToken => |x| return x.token,55 .ExpectedToken => |x| return x.token,
51 .ExpectedExpr => |x| return x.token,56 .ExpectedExpr => |x| return x.token,
52 .ExpectedStmt => |x| return x.token,57 .ExpectedStmt => |x| return x.token,
58 .ExpectedTypeName => |x| return x.token,
53 .InvalidTypeSpecifier => |x| return x.token,59 .InvalidTypeSpecifier => |x| return x.token,
54 .DuplicateQualifier => |x| return x.token,60 .DuplicateQualifier => |x| return x.token,
61 .DuplicateSpecifier => |x| return x.token,
55 }62 }
56 }63 }
5764
...@@ -72,11 +79,11 @@ pub const Error = union(enum) {...@@ -72,11 +79,11 @@ pub const Error = union(enum) {
7279
73 pub const InvalidTypeSpecifier = struct {80 pub const InvalidTypeSpecifier = struct {
74 token: TokenIndex,81 token: TokenIndex,
75 type: *Node.Type,82 type_spec: *Node.TypeSpec,
7683
77 pub fn render(self: *const ExpectedToken, tokens: *Tree.TokenList, stream: var) !void {84 pub fn render(self: *const ExpectedToken, tokens: *Tree.TokenList, stream: var) !void {
78 try stream.write("invalid type specifier '");85 try stream.write("invalid type specifier '");
79 try type.specifier.print(tokens, stream);86 try type_spec.spec.print(tokens, stream);
80 const token_name = tokens.at(self.token).id.symbol();87 const token_name = tokens.at(self.token).id.symbol();
81 return stream.print("{}'", .{ token_name });88 return stream.print("{}'", .{ token_name });
82 }89 }
...@@ -114,9 +121,32 @@ pub const Node = struct {...@@ -114,9 +121,32 @@ pub const Node = struct {
114 pub const DeclList = SegmentedList(*Node, 4);121 pub const DeclList = SegmentedList(*Node, 4);
115 };122 };
116123
117 pub const Type = struct {124 pub const DeclSpec = struct {
118 qualifiers: Qualifiers,125 storage_class: union(enum) {
119 specifier: union(enum) {126 Auto: TokenIndex,
127 Extern: TokenIndex,
128 Register: TokenIndex,
129 Static: TokenIndex,
130 Typedef: TokenIndex,
131 None,
132 } = .None,
133 thread_local: ?TokenIndex = null,
134 type_spec: TypeSpec = TypeSpec{},
135 fn_spec: union(enum) {
136 Inline: TokenIndex,
137 Noreturn: TokenIndex,
138 None,
139 } = .None,
140 align_spec: ?struct {
141 alignas: TokenIndex,
142 expr: *Node,
143 rparen: TokenIndex,
144 } = null,
145 };
146
147 pub const TypeSpec = struct {
148 qual: TypeQual = TypeQual{},
149 spec: union(enum) {
120 /// error or default to int150 /// error or default to int
121 None,151 None,
122 Void: TokenIndex,152 Void: TokenIndex,
...@@ -167,10 +197,10 @@ pub const Node = struct {...@@ -167,10 +197,10 @@ pub const Node = struct {
167 else => @panic("TODO print type specifier"),197 else => @panic("TODO print type specifier"),
168 }198 }
169 }199 }
170 },200 } = .None,
171 };201 };
172202
173 pub const Qualifiers = struct {203 pub const TypeQual = struct {
174 @"const": ?TokenIndex = null,204 @"const": ?TokenIndex = null,
175 atomic: ?TokenIndex = null,205 atomic: ?TokenIndex = null,
176 @"volatile": ?TokenIndex = null,206 @"volatile": ?TokenIndex = null,
lib/std/c/parse.zig+187-98
...@@ -1,7 +1,8 @@...@@ -1,7 +1,8 @@
1const std = @import("../std.zig");1const std = @import("std");
2const assert = std.debug.assert;2const assert = std.debug.assert;
3const Allocator = std.mem.Allocator;3const Allocator = std.mem.Allocator;
4const ast = std.c.ast;4const ast = std.c.ast;
5const Node = ast.Node;
5const Tree = ast.Tree;6const Tree = ast.Tree;
6const TokenIndex = ast.TokenIndex;7const TokenIndex = ast.TokenIndex;
7const Token = std.c.Token;8const Token = std.c.Token;
...@@ -69,6 +70,12 @@ const Parser = struct {...@@ -69,6 +70,12 @@ const Parser = struct {
69 arena: *Allocator,70 arena: *Allocator,
70 it: *TokenIterator,71 it: *TokenIterator,
71 tree: *Tree,72 tree: *Tree,
73 typedefs: std.StringHashMap(void),
74
75 fn isTypedef(parser: *Parser, tok: TokenIndex) bool {
76 const token = parser.it.list.at(tok);
77 return parser.typedefs.contains(token.slice());
78 }
7279
73 /// Root <- ExternalDeclaration* eof80 /// Root <- ExternalDeclaration* eof
74 fn root(parser: *Parser) Allocator.Error!*Node {81 fn root(parser: *Parser) Allocator.Error!*Node {
...@@ -93,48 +100,89 @@ const Parser = struct {...@@ -93,48 +100,89 @@ const Parser = struct {
93 }100 }
94101
95 /// ExternalDeclaration102 /// ExternalDeclaration
96 /// <- Declaration103 /// <- DeclSpec Declarator Declaration* CompoundStmt
97 /// / DeclarationSpecifiers Declarator Declaration* CompoundStmt104 /// / DeclSpec (Declarator (EQUAL Initializer)?)* SEMICOLON
105 /// / StaticAssert
98 fn externalDeclarations(parser: *Parser) !?*Node {106 fn externalDeclarations(parser: *Parser) !?*Node {
99 if (try Declaration(parser)) |decl| {}107 if (try Declaration(parser)) |decl| {}
100 return null;108 return null;
101 }109 }
102110
103 /// Declaration111 /// Declaration
104 /// <- DeclarationSpecifiers (Declarator (EQUAL Initializer)?)* SEMICOLON112 /// <- DeclSpec (Declarator (EQUAL Initializer)?)* SEMICOLON
105 /// \ StaticAssertDeclaration113 /// / StaticAssert
106 fn declaration(parser: *Parser) !?*Node {}114 fn declaration(parser: *Parser) !?*Node {}
107115
108 /// StaticAssertDeclaration <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON116 /// StaticAssert <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON
109 fn staticAssertDeclaration(parser: *Parser) !?*Node {}117 fn StaticAssert(parser: *Parser) !?*Node {}
110118
111 /// DeclarationSpecifiers119 /// DeclSpec <- (StorageClassSpec / TypeSpec / FnSpec / AlignSpec)*
112 /// <- (Keyword_typedef / Keyword_extern / Keyword_static / Keyword_thread_local / Keyword_auto / Keyword_register120 fn declSpec(parser: *Parser) !*Node.DeclSpec {
113 /// / Type121 const ds = try parser.arena.create(Node.DeclSpec);
114 /// / Keyword_inline / Keyword_noreturn122 ds.* = .{};
115 /// / Keyword_alignas LPAREN (TypeName / ConstExpr) RPAREN)*123 while ((try parser.storageClassSpec(ds)) or (try parser.typeSpec(&ds.type_spec)) or (try parser.fnSpec(ds)) or (try parser.alignSpec(ds))) {}
116 fn declarationSpecifiers(parser: *Parser) !*Node {}124 return ds;
125 }
117126
118 /// Type127 /// StorageClassSpec
128 /// <- Keyword_typedef / Keyword_extern / Keyword_static / Keyword_thread_local / Keyword_auto / Keyword_register
129 fn storageClassSpec(parser: *Parser, ds: *Node.DeclSpec) !bool {
130 blk: {
131 if (parser.eatToken(.Keyword_typedef)) |tok| {
132 if (ds.storage_class != .None or ds.thread_local != null)
133 break :blk;
134 ds.storage_class = .{ .Typedef = tok };
135 } else if (parser.eatToken(.Keyword_extern)) |tok| {
136 if (ds.storage_class != .None)
137 break :blk;
138 ds.storage_class = .{ .Extern = tok };
139 } else if (parser.eatToken(.Keyword_static)) |tok| {
140 if (ds.storage_class != .None)
141 break :blk;
142 ds.storage_class = .{ .Static = tok };
143 } else if (parser.eatToken(.Keyword_thread_local)) |tok| {
144 switch (ds.storage_class) {
145 .None, .Extern, .Static => {},
146 else => break :blk,
147 }
148 ds.thread_local = tok;
149 } else if (parser.eatToken(.Keyword_auto)) |tok| {
150 if (ds.storage_class != .None or ds.thread_local != null)
151 break :blk;
152 ds.storage_class = .{ .Auto = tok };
153 } else if (parser.eatToken(.Keyword_register)) |tok| {
154 if (ds.storage_class != .None or ds.thread_local != null)
155 break :blk;
156 ds.storage_class = .{ .Register = tok };
157 } else return false;
158 return true;
159 }
160 try parser.warning(.{
161 .DuplicateSpecifier = .{ .token = parser.it.index },
162 });
163 return true;
164 }
165
166 /// TypeSpec
119 /// <- Keyword_void / Keyword_char / Keyword_short / Keyword_int / Keyword_long / Keyword_float / Keyword_double167 /// <- Keyword_void / Keyword_char / Keyword_short / Keyword_int / Keyword_long / Keyword_float / Keyword_double
120 /// / Keyword_signed / Keyword_unsigned / Keyword_bool / Keyword_complex / Keyword_imaginary /168 /// / Keyword_signed / Keyword_unsigned / Keyword_bool / Keyword_complex / Keyword_imaginary /
121 /// / Keyword_atomic LPAREN TypeName RPAREN169 /// / Keyword_atomic LPAREN TypeName RPAREN
122 /// / EnumSpecifier170 /// / EnumSpecifier
123 /// / RecordSpecifier171 /// / RecordSpecifier
124 /// / IDENTIFIER // typedef name172 /// / IDENTIFIER // typedef name
125 /// / TypeQualifier173 /// / TypeQual
126 fn type(parser: *Parser, type: *Node.Type) !bool {174 fn typeSpec(parser: *Parser, type_spec: *Node.TypeSpec) !bool {
127 while (try parser.typeQualifier(type.qualifiers)) {}175 while (try parser.typeQual(&type_spec.qual)) {}
128 blk: {176 blk: {
129 if (parser.eatToken(.Keyword_void)) |tok| {177 if (parser.eatToken(.Keyword_void)) |tok| {
130 if (type.specifier != .None)178 if (type_spec.spec != .None)
131 break :blk;179 break :blk;
132 type.specifier = .{ .Void = tok };180 type_spec.spec = .{ .Void = tok };
133 return true;181 return true;
134 } else if (parser.eatToken(.Keyword_char)) |tok| {182 } else if (parser.eatToken(.Keyword_char)) |tok| {
135 switch (type.specifier) {183 switch (type_spec.spec) {
136 .None => {184 .None => {
137 type.specifier = .{185 type_spec.spec = .{
138 .Char = .{186 .Char = .{
139 .char = tok,187 .char = tok,
140 },188 },
...@@ -143,7 +191,7 @@ const Parser = struct {...@@ -143,7 +191,7 @@ const Parser = struct {
143 .Int => |int| {191 .Int => |int| {
144 if (int.int != null)192 if (int.int != null)
145 break :blk;193 break :blk;
146 type.specifier = .{194 type_spec.spec = .{
147 .Char = .{195 .Char = .{
148 .char = tok,196 .char = tok,
149 .sign = int.sign,197 .sign = int.sign,
...@@ -154,9 +202,9 @@ const Parser = struct {...@@ -154,9 +202,9 @@ const Parser = struct {
154 }202 }
155 return true;203 return true;
156 } else if (parser.eatToken(.Keyword_short)) |tok| {204 } else if (parser.eatToken(.Keyword_short)) |tok| {
157 switch (type.specifier) {205 switch (type_spec.spec) {
158 .None => {206 .None => {
159 type.specifier = .{207 type_spec.spec = .{
160 .Short = .{208 .Short = .{
161 .short = tok,209 .short = tok,
162 },210 },
...@@ -165,7 +213,7 @@ const Parser = struct {...@@ -165,7 +213,7 @@ const Parser = struct {
165 .Int => |int| {213 .Int => |int| {
166 if (int.int != null)214 if (int.int != null)
167 break :blk;215 break :blk;
168 type.specifier = .{216 type_spec.spec = .{
169 .Short = .{217 .Short = .{
170 .short = tok,218 .short = tok,
171 .sign = int.sign,219 .sign = int.sign,
...@@ -176,16 +224,16 @@ const Parser = struct {...@@ -176,16 +224,16 @@ const Parser = struct {
176 }224 }
177 return true;225 return true;
178 } else if (parser.eatToken(.Keyword_long)) |tok| {226 } else if (parser.eatToken(.Keyword_long)) |tok| {
179 switch (type.specifier) {227 switch (type_spec.spec) {
180 .None => {228 .None => {
181 type.specifier = .{229 type_spec.spec = .{
182 .Long = .{230 .Long = .{
183 .long = tok,231 .long = tok,
184 },232 },
185 };233 };
186 },234 },
187 .Int => |int| {235 .Int => |int| {
188 type.specifier = .{236 type_spec.spec = .{
189 .Long = .{237 .Long = .{
190 .long = tok,238 .long = tok,
191 .sign = int.sign,239 .sign = int.sign,
...@@ -207,9 +255,9 @@ const Parser = struct {...@@ -207,9 +255,9 @@ const Parser = struct {
207 }255 }
208 return true;256 return true;
209 } else if (parser.eatToken(.Keyword_int)) |tok| {257 } else if (parser.eatToken(.Keyword_int)) |tok| {
210 switch (type.specifier) {258 switch (type_spec.spec) {
211 .None => {259 .None => {
212 type.specifier = .{260 type_spec.spec = .{
213 .Int = .{261 .Int = .{
214 .int = tok,262 .int = tok,
215 },263 },
...@@ -234,9 +282,9 @@ const Parser = struct {...@@ -234,9 +282,9 @@ const Parser = struct {
234 }282 }
235 return true;283 return true;
236 } else if (parser.eatToken(.Keyword_signed) orelse parser.eatToken(.Keyword_unsigned)) |tok| {284 } else if (parser.eatToken(.Keyword_signed) orelse parser.eatToken(.Keyword_unsigned)) |tok| {
237 switch (type.specifier) {285 switch (type_spec.spec) {
238 .None => {286 .None => {
239 type.specifier = .{287 type_spec.spec = .{
240 .Int = .{288 .Int = .{
241 .sign = tok,289 .sign = tok,
242 },290 },
...@@ -266,30 +314,30 @@ const Parser = struct {...@@ -266,30 +314,30 @@ const Parser = struct {
266 }314 }
267 return true;315 return true;
268 } else if (parser.eatToken(.Keyword_float)) |tok| {316 } else if (parser.eatToken(.Keyword_float)) |tok| {
269 if (type.specifier != .None)317 if (type_spec.spec != .None)
270 break :blk;318 break :blk;
271 type.specifier = .{319 type_spec.spec = .{
272 .Float = .{320 .Float = .{
273 .float = tok,321 .float = tok,
274 },322 },
275 };323 };
276 return true;324 return true;
277 } else if (parser.eatToken(.Keyword_double)) |tok| {325 } else if (parser.eatToken(.Keyword_double)) |tok| {
278 if (type.specifier != .None)326 if (type_spec.spec != .None)
279 break :blk;327 break :blk;
280 type.specifier = .{328 type_spec.spec = .{
281 .Double = .{329 .Double = .{
282 .double = tok,330 .double = tok,
283 },331 },
284 };332 };
285 return true;333 return true;
286 } else if (parser.eatToken(.Keyword_complex)) |tok| {334 } else if (parser.eatToken(.Keyword_complex)) |tok| {
287 switch (type.specifier) {335 switch (type_spec.spec) {
288 .None => {336 .None => {
289 type.specifier = .{337 type_spec.spec = .{
290 .Double = .{338 .Double = .{
291 .complex = tok,339 .complex = tok,
292 .double = null340 .double = null,
293 },341 },
294 };342 };
295 },343 },
...@@ -306,40 +354,41 @@ const Parser = struct {...@@ -306,40 +354,41 @@ const Parser = struct {
306 else => break :blk,354 else => break :blk,
307 }355 }
308 return true;356 return true;
309 } if (parser.eatToken(.Keyword_bool)) |tok| {357 }
310 if (type.specifier != .None)358 if (parser.eatToken(.Keyword_bool)) |tok| {
359 if (type_spec.spec != .None)
311 break :blk;360 break :blk;
312 type.specifier = .{ .Bool = tok };361 type_spec.spec = .{ .Bool = tok };
313 return true;362 return true;
314 } else if (parser.eatToken(.Keyword_atomic)) |tok| {363 } else if (parser.eatToken(.Keyword_atomic)) |tok| {
315 if (type.specifier != .None)364 if (type_spec.spec != .None)
316 break :blk;365 break :blk;
317 _ = try parser.expectToken(.LParen);366 _ = try parser.expectToken(.LParen);
318 const name = try parser.expect(typeName, .{367 const name = try parser.expect(typeName, .{
319 .ExpectedTypeName = .{ .tok = it.index },368 .ExpectedTypeName = .{ .token = parser.it.index },
320 });369 });
321 type.specifier.Atomic = .{370 type_spec.spec.Atomic = .{
322 .atomic = tok,371 .atomic = tok,
323 .typename = name,372 .typename = name,
324 .rparen = try parser.expectToken(.RParen),373 .rparen = try parser.expectToken(.RParen),
325 };374 };
326 return true;375 return true;
327 } else if (parser.eatToken(.Keyword_enum)) |tok| {376 } else if (parser.eatToken(.Keyword_enum)) |tok| {
328 if (type.specifier != .None)377 if (type_spec.spec != .None)
329 break :blk;378 break :blk;
330 @panic("TODO enum type");379 @panic("TODO enum type");
331 // return true;380 // return true;
332 } else if (parser.eatToken(.Keyword_union) orelse parser.eatToken(.Keyword_struct)) |tok| {381 } else if (parser.eatToken(.Keyword_union) orelse parser.eatToken(.Keyword_struct)) |tok| {
333 if (type.specifier != .None)382 if (type_spec.spec != .None)
334 break :blk;383 break :blk;
335 @panic("TODO record type");384 @panic("TODO record type");
336 // return true;385 // return true;
337 } else if (parser.eatToken(.Identifier)) |tok| {386 } else if (parser.eatToken(.Identifier)) |tok| {
338 if (!parser.typedefs.contains(tok)) {387 if (!parser.isTypedef(tok)) {
339 parser.putBackToken(tok);388 parser.putBackToken(tok);
340 return false;389 return false;
341 }390 }
342 type.specifier = .{391 type_spec.spec = .{
343 .Typedef = tok,392 .Typedef = tok,
344 };393 };
345 return true;394 return true;
...@@ -348,44 +397,81 @@ const Parser = struct {...@@ -348,44 +397,81 @@ const Parser = struct {
348 try parser.tree.errors.push(.{397 try parser.tree.errors.push(.{
349 .InvalidTypeSpecifier = .{398 .InvalidTypeSpecifier = .{
350 .token = parser.it.index,399 .token = parser.it.index,
351 .type = type,400 .type_spec = type_spec,
352 },401 },
353 });402 });
354 return error.ParseError;403 return error.ParseError;
355 }404 }
356405
357 /// TypeQualifier <- Keyword_const / Keyword_restrict / Keyword_volatile / Keyword_atomic406 /// TypeQual <- Keyword_const / Keyword_restrict / Keyword_volatile / Keyword_atomic
358 fn typeQualifier(parser: *Parser, qualifiers: *Node.Qualifiers) !bool {407 fn typeQual(parser: *Parser, qual: *Node.TypeQual) !bool {
359 if (parser.eatToken(.Keyword_const)) |tok| {408 blk: {
360 if (qualifiers.@"const" != null)409 if (parser.eatToken(.Keyword_const)) |tok| {
361 return parser.warning(.{410 if (qual.@"const" != null)
362 .DuplicateQualifier = .{ .token = tok },411 break :blk;
363 });412 qual.@"const" = tok;
364 qualifiers.@"const" = tok;413 } else if (parser.eatToken(.Keyword_restrict)) |tok| {
365 } else if (parser.eatToken(.Keyword_restrict)) |tok| {414 if (qual.atomic != null)
366 if (qualifiers.atomic != null)415 break :blk;
367 return parser.warning(.{416 qual.atomic = tok;
368 .DuplicateQualifier = .{ .token = tok },417 } else if (parser.eatToken(.Keyword_volatile)) |tok| {
369 });418 if (qual.@"volatile" != null)
370 qualifiers.atomic = tok;419 break :blk;
371 } else if (parser.eatToken(.Keyword_volatile)) |tok| {420 qual.@"volatile" = tok;
372 if (qualifiers.@"volatile" != null)421 } else if (parser.eatToken(.Keyword_atomic)) |tok| {
373 return parser.warning(.{422 if (qual.atomic != null)
374 .DuplicateQualifier = .{ .token = tok },423 break :blk;
375 });424 qual.atomic = tok;
376 qualifiers.@"volatile" = tok;425 } else return false;
377 } else if (parser.eatToken(.Keyword_atomic)) |tok| {426 return true;
378 if (qualifiers.atomic != null)427 }
379 return parser.warning(.{428 try parser.warning(.{
380 .DuplicateQualifier = .{ .token = tok },429 .DuplicateQualifier = .{ .token = parser.it.index },
381 });430 });
382 qualifiers.atomic = tok;431 return true;
383 } else return false;432 }
433
434 /// FnSpec <- Keyword_inline / Keyword_noreturn
435 fn fnSpec(parser: *Parser, ds: *Node.DeclSpec) !bool {
436 blk: {
437 if (parser.eatToken(.Keyword_inline)) |tok| {
438 if (ds.fn_spec != .None)
439 break :blk;
440 ds.fn_spec = .{ .Inline = tok };
441 } else if (parser.eatToken(.Keyword_noreturn)) |tok| {
442 if (ds.fn_spec != .None)
443 break :blk;
444 ds.fn_spec = .{ .Noreturn = tok };
445 } else return false;
446 return true;
447 }
448 try parser.warning(.{
449 .DuplicateSpecifier = .{ .token = parser.it.index },
450 });
384 return true;451 return true;
385 }452 }
386453
387 /// FunctionSpecifier <- Keyword_inline / Keyword_noreturn454 /// AlignSpec <- Keyword_alignas LPAREN (TypeName / ConstExpr) RPAREN
388 fn functionSpecifier(parser: *Parser) !*Node {}455 fn alignSpec(parser: *Parser, ds: *Node.DeclSpec) !bool {
456 if (parser.eatToken(.Keyword_alignas)) |tok| {
457 _ = try parser.expectToken(.LParen);
458 const node = (try parser.typeName()) orelse (try parser.expect(conditionalExpr, .{
459 .ExpectedExpr = .{ .token = parser.it.index },
460 }));
461 if (ds.align_spec != null) {
462 try parser.warning(.{
463 .DuplicateSpecifier = .{ .token = parser.it.index },
464 });
465 }
466 ds.align_spec = .{
467 .alignas = tok,
468 .expr = node,
469 .rparen = try parser.expectToken(.RParen),
470 };
471 return true;
472 }
473 return false;
474 }
389475
390 /// EnumSpecifier <- Keyword_enum IDENTIFIER? (LBRACE EnumField RBRACE)?476 /// EnumSpecifier <- Keyword_enum IDENTIFIER? (LBRACE EnumField RBRACE)?
391 fn enumSpecifier(parser: *Parser) !*Node {}477 fn enumSpecifier(parser: *Parser) !*Node {}
...@@ -397,13 +483,13 @@ const Parser = struct {...@@ -397,13 +483,13 @@ const Parser = struct {
397 fn recordSpecifier(parser: *Parser) !*Node {}483 fn recordSpecifier(parser: *Parser) !*Node {}
398484
399 /// RecordField485 /// RecordField
400 /// <- Type* (RecordDeclarator (COMMA RecordDeclarator))? SEMICOLON486 /// <- TypeSpec* (RecordDeclarator (COMMA RecordDeclarator))? SEMICOLON
401 /// \ StaticAssertDeclaration487 /// \ StaticAssert
402 fn recordField(parser: *Parser) !*Node {}488 fn recordField(parser: *Parser) !*Node {}
403489
404 /// TypeName490 /// TypeName
405 /// <- Type* AbstractDeclarator?491 /// <- TypeSpec* AbstractDeclarator?
406 fn typeName(parser: *Parser) !*Node {}492 fn typeName(parser: *Parser) !*Node {
407493
408 /// RecordDeclarator <- Declarator? (COLON ConstExpr)?494 /// RecordDeclarator <- Declarator? (COLON ConstExpr)?
409 fn recordDeclarator(parser: *Parser) !*Node {}495 fn recordDeclarator(parser: *Parser) !*Node {}
...@@ -411,7 +497,7 @@ const Parser = struct {...@@ -411,7 +497,7 @@ const Parser = struct {
411 /// Declarator <- Pointer? DirectDeclarator497 /// Declarator <- Pointer? DirectDeclarator
412 fn declarator(parser: *Parser) !*Node {}498 fn declarator(parser: *Parser) !*Node {}
413499
414 /// Pointer <- ASTERISK TypeQualifier* Pointer?500 /// Pointer <- ASTERISK TypeQual* Pointer?
415 fn pointer(parser: *Parser) !*Node {}501 fn pointer(parser: *Parser) !*Node {}
416502
417 /// DirectDeclarator503 /// DirectDeclarator
...@@ -422,13 +508,13 @@ const Parser = struct {...@@ -422,13 +508,13 @@ const Parser = struct {
422 fn directDeclarator(parser: *Parser) !*Node {}508 fn directDeclarator(parser: *Parser) !*Node {}
423509
424 /// BracketDeclarator510 /// BracketDeclarator
425 /// <- Keyword_static TypeQualifier* AssignmentExpr511 /// <- Keyword_static TypeQual* AssignmentExpr
426 /// / TypeQualifier+ (ASTERISK / Keyword_static AssignmentExpr)512 /// / TypeQual+ (ASTERISK / Keyword_static AssignmentExpr)
427 /// / TypeQualifier+ AssignmentExpr?513 /// / TypeQual+ AssignmentExpr?
428 /// / AssignmentExpr514 /// / AssignmentExpr
429 fn bracketDeclarator(parser: *Parser) !*Node {}515 fn bracketDeclarator(parser: *Parser) !*Node {}
430516
431 /// ParamDecl <- DeclarationSpecifiers (Declarator / AbstractDeclarator)517 /// ParamDecl <- DeclSpec (Declarator / AbstractDeclarator)
432 fn paramDecl(parser: *Parser) !*Node {}518 fn paramDecl(parser: *Parser) !*Node {}
433519
434 /// AbstractDeclarator <- Pointer? DirectAbstractDeclarator?520 /// AbstractDeclarator <- Pointer? DirectAbstractDeclarator?
...@@ -647,25 +733,25 @@ const Parser = struct {...@@ -647,25 +733,25 @@ const Parser = struct {
647 return &node.base;733 return &node.base;
648 }734 }
649735
650 fn eatToken(parser: *Parser, id: Token.Id) ?TokenIndex {736 fn eatToken(parser: *Parser, id: @TagType(Token.Id)) ?TokenIndex {
651 while (true) {737 while (true) {
652 const next_tok = parser.it.next() orelse return null;738 const next_tok = parser.it.next() orelse return null;
653 if (next_tok.id != .LineComment and next_tok.id != .MultiLineComment) {739 if (next_tok.id != .LineComment and next_tok.id != .MultiLineComment) {
654 if (next_tok.id == id) {740 if (next_tok.id == id) {
655 return parser.it.index;741 return parser.it.index;
656 }742 }
657 parser.it.prev();743 _ = parser.it.prev();
658 return null;744 return null;
659 }745 }
660 }746 }
661 }747 }
662748
663 fn expectToken(parser: *Parser, id: Token.Id) Error!TokenIndex {749 fn expectToken(parser: *Parser, id: @TagType(Token.Id)) Error!TokenIndex {
664 while (true) {750 while (true) {
665 const next_tok = parser.it.next() orelse return error.ParseError;751 const next_tok = parser.it.next() orelse return error.ParseError;
666 if (next_tok.id != .LineComment and next_tok.id != .MultiLineComment) {752 if (next_tok.id != .LineComment and next_tok.id != .MultiLineComment) {
667 if (next_tok.id != id) {753 if (next_tok.id != id) {
668 try tree.errors.push(.{754 try parser.tree.errors.push(.{
669 .ExpectedToken = .{ .token = parser.it.index, .expected_id = id },755 .ExpectedToken = .{ .token = parser.it.index, .expected_id = id },
670 });756 });
671 return error.ParseError;757 return error.ParseError;
...@@ -678,7 +764,7 @@ const Parser = struct {...@@ -678,7 +764,7 @@ const Parser = struct {
678 fn putBackToken(parser: *Parser, putting_back: TokenIndex) void {764 fn putBackToken(parser: *Parser, putting_back: TokenIndex) void {
679 while (true) {765 while (true) {
680 const prev_tok = parser.it.prev() orelse return;766 const prev_tok = parser.it.prev() orelse return;
681 if (next_tok.id == .LineComment or next_tok.id == .MultiLineComment) continue;767 if (prev_tok.id == .LineComment or prev_tok.id == .MultiLineComment) continue;
682 assert(parser.it.list.at(putting_back) == prev_tok);768 assert(parser.it.list.at(putting_back) == prev_tok);
683 return;769 return;
684 }770 }
...@@ -689,14 +775,17 @@ const Parser = struct {...@@ -689,14 +775,17 @@ const Parser = struct {
689 parseFn: fn (*Parser) Error!?*Node,775 parseFn: fn (*Parser) Error!?*Node,
690 err: ast.Error, // if parsing fails776 err: ast.Error, // if parsing fails
691 ) Error!*Node {777 ) Error!*Node {
692 return (try parseFn(arena, it, tree)) orelse {778 return (try parseFn(parser)) orelse {
693 try parser.tree.errors.push(err);779 try parser.tree.errors.push(err);
694 return error.ParseError;780 return error.ParseError;
695 };781 };
696 }782 }
697783
698 fn warning(parser: *Parser, err: ast.Error) Error {784 fn warning(parser: *Parser, err: ast.Error) Error!void {
699 // if (parser.warnaserror)785 if (parser.tree.warnings) |*w| {
786 try w.push(err);
787 return;
788 }
700 try parser.tree.errors.push(err);789 try parser.tree.errors.push(err);
701 return error.ParseError;790 return error.ParseError;
702 }791 }
lib/std/c/tokenizer.zig+6-2
...@@ -135,8 +135,8 @@ pub const Token = struct {...@@ -135,8 +135,8 @@ pub const Token = struct {
135 Keyword_error,135 Keyword_error,
136 Keyword_pragma,136 Keyword_pragma,
137137
138 pub fn symbol(tok: Token) []const u8 {138 pub fn symbol(id: @TagType(Id)) []const u8 {
139 return switch (tok.id) {139 return switch (id) {
140 .Invalid => "Invalid",140 .Invalid => "Invalid",
141 .Eof => "Eof",141 .Eof => "Eof",
142 .Nl => "NewLine",142 .Nl => "NewLine",
...@@ -347,6 +347,10 @@ pub const Token = struct {...@@ -347,6 +347,10 @@ pub const Token = struct {
347 return null;347 return null;
348 }348 }
349349
350 pub fn slice(tok: Token) []const u8 {
351 return tok.source.buffer[tok.start..tok.end];
352 }
353
350 pub const NumSuffix = enum {354 pub const NumSuffix = enum {
351 None,355 None,
352 F,356 F,