authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-05 20:19:17+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-05 20:25:52+02:00
log5feeff71236eb7bf8257b247660b6e9c33495ee8
treecb5f56b76bdc0371d91debf4916ba692f0bd6fae
parent795a5039995a1a23ba00d15488565f1a79d3f25b
signaturelock-open Commit is signed but in an unrecognized format.

std-c improve error reporting and decl parsing


2 files changed, 155 insertions(+), 96 deletions(-)

lib/std/c/ast.zig+12-4
......@@ -10,12 +10,11 @@ pub const Tree = struct {
1010 sources: SourceList,
1111 root_node: *Node.Root,
1212 arena_allocator: std.heap.ArenaAllocator,
13 errors: ErrorList,
14 warnings: ?ErrorList,
13 msgs: MsgList,
1514
1615 pub const SourceList = SegmentedList(Source, 4);
1716 pub const TokenList = Source.TokenList;
18 pub const ErrorList = SegmentedList(Error, 0);
17 pub const MsgList = SegmentedList(Msg, 0);
1918
2019 pub fn deinit(self: *Tree) void {
2120 // Here we copy the arena allocator into stack memory, because
......@@ -26,6 +25,15 @@ pub const Tree = struct {
2625 }
2726};
2827
28pub const Msg = struct {
29 kind: enum {
30 Error,
31 Warning,
32 Note,
33 },
34 inner: Error,
35};
36
2937pub const Error = union(enum) {
3038 InvalidToken: SingleTokenError("invalid token '{}'"),
3139 ExpectedToken: ExpectedToken,
......@@ -268,7 +276,7 @@ pub const Node = struct {
268276
269277 pub const FnDef = struct {
270278 base: Node = Node{ .id = .FnDef },
271 decl_spec: *DeclSpec,
279 decl_spec: DeclSpec,
272280 declarator: *Node,
273281 old_decls: OldDeclList,
274282 body: *CompoundStmt,
lib/std/c/parse.zig+143-92
......@@ -70,11 +70,21 @@ const Parser = struct {
7070 arena: *Allocator,
7171 it: *TokenIterator,
7272 tree: *Tree,
73 typedefs: std.StringHashMap(void),
7473
75 fn isTypedef(parser: *Parser, tok: TokenIndex) bool {
76 const token = parser.it.list.at(tok);
77 return parser.typedefs.contains(token.slice());
74 /// only used for scopes
75 arena_allocator: std.heap.ArenaAllocator,
76 // scopes: std.SegmentedLists(Scope),
77 warnings: bool = true,
78
79 // const Scope = struct {
80 // types:
81 // syms:
82 // };
83
84 fn getTypeDef(parser: *Parser, tok: TokenIndex) bool {
85 return false; // TODO
86 // const token = parser.it.list.at(tok);
87 // return parser.typedefs.contains(token.slice());
7888 }
7989
8090 /// Root <- ExternalDeclaration* eof
......@@ -84,7 +94,7 @@ const Parser = struct {
8494 .decls = Node.Root.DeclList.init(parser.arena),
8595 .eof = undefined,
8696 };
87 while (parser.externalDeclarations() catch |err| switch (err) {
97 while (parser.externalDeclarations() catch |e| switch (e) {
8898 error.OutOfMemory => return error.OutOfMemory,
8999 error.ParseError => return node,
90100 }) |decl| {
......@@ -95,70 +105,99 @@ const Parser = struct {
95105 }
96106
97107 /// ExternalDeclaration
98 /// <- DeclSpec Declarator Declaration* CompoundStmt
108 /// <- DeclSpec Declarator OldStyleDecl* CompoundStmt
99109 /// / Declaration
110 /// OldStyleDecl <- DeclSpec Declarator (COMMA Declarator)* SEMICOLON
100111 fn externalDeclarations(parser: *Parser) !?*Node {
112 return parser.declarationExtra(false);
113 }
114
115 /// Declaration
116 /// <- DeclSpec DeclInit SEMICOLON
117 /// / StaticAssert
118 /// DeclInit <- Declarator (EQUAL Initializer)? (COMMA Declarator (EQUAL Initializer)?)*
119 fn declaration(parser: *Parser) !?*Node {
120 return parser.declarationExtra(true);
121 }
122
123 fn declarationExtra(parser: *Parser, local: bool) !?*Node {
101124 if (try parser.staticAssert()) |decl| return decl;
102 const ds = try parser.declSpec();
103 const dr = (try parser.declarator());
104 if (dr == null)
105 try parser.warning(.{
106 .ExpectedDeclarator = .{ .token = parser.it.index },
107 });
125 var ds = Node.DeclSpec{};
126 const got_ds = try parser.declSpec(&ds);
127 if (local and !got_ds) {
128 // not a declaration
129 return null;
130 }
131 var dr = try parser.declarator();
108132 // TODO disallow auto and register
109133 const next_tok = parser.it.peek().?;
134 if (next_tok.id == .Eof and !got_ds and dr == null) {
135 return null;
136 }
110137 switch (next_tok.id) {
111138 .Semicolon,
112139 .Equal,
113140 .Comma,
114141 .Eof,
115 => return parser.declarationExtra(ds, dr, false),
116 else => {},
117 }
118 var old_decls = Node.FnDef.OldDeclList.init(parser.arena);
119 while (try parser.declaration()) |decl| {
120 // validate declaration
121 try old_decls.push(decl);
122 }
123 const body = try parser.expect(compoundStmt, .{
124 .ExpectedFnBody = .{ .token = parser.it.index },
125 });
126
127 const node = try parser.arena.create(Node.FnDef);
128 node.* = .{
129 .decl_spec = ds,
130 .declarator = dr orelse return null,
131 .old_decls = old_decls,
132 .body = @fieldParentPtr(Node.CompoundStmt, "base", body),
133 };
134 return &node.base;
135 }
142 => {
143 while (dr != null) {
144 if (parser.eatToken(.Equal)) |tok| {
145 // TODO typedef
146 // dr.?.init = try parser.expect(initializer, .{
147 // .ExpectedInitializer = .{ .token = parser.it.index },
148 // });
149 }
150 if (parser.eatToken(.Comma) != null) break;
151 dr = (try parser.declarator()) orelse return parser.err(.{
152 .ExpectedDeclarator = .{ .token = parser.it.index },
153 });
154 // .push(dr);
155 }
156 const semicolon = try parser.expectToken(.Semicolon);
136157
137 /// Declaration
138 /// <- DeclSpec (Declarator (EQUAL Initializer)? COMMA)* SEMICOLON
139 /// / StaticAssert
140 fn declaration(parser: *Parser) !?*Node {
141 if (try parser.staticAssert()) |decl| return decl;
142 const ds = try parser.declSpec();
143 const dr = (try parser.declarator());
144 if (dr == null)
145 try parser.warning(.{
146 .ExpectedDeclarator = .{ .token = parser.it.index },
147 });
148 // TODO disallow threadlocal without static or extern
149 return parser.declarationExtra(ds, dr, true);
150 }
158 // TODO VarDecl, TypeDecl, TypeDef
159 return null;
160 },
161 else => {
162 if (dr == null)
163 return parser.err(.{
164 .ExpectedDeclarator = .{ .token = parser.it.index },
165 });
166 var old_decls = Node.FnDef.OldDeclList.init(parser.arena);
167 while (true) {
168 var old_ds = Node.DeclSpec{};
169 if (!(try parser.declSpec(&old_ds))) {
170 // not old decl
171 break;
172 }
173 var old_dr = (try parser.declarator());
174 // if (old_dr == null)
175 // try parser.err(.{
176 // .NoParamName = .{ .token = parser.it.index },
177 // });
178 // try old_decls.push(decl);
179 }
180 const body = (try parser.compoundStmt()) orelse return parser.err(.{
181 .ExpectedFnBody = .{ .token = parser.it.index },
182 });
151183
152 fn declarationExtra(parser: *Parser, ds: *Node.DeclSpec, dr: ?*Node, local: bool) !?*Node {
184 const node = try parser.arena.create(Node.FnDef);
185 node.* = .{
186 .decl_spec = ds,
187 .declarator = dr orelse return null,
188 .old_decls = old_decls,
189 .body = @fieldParentPtr(Node.CompoundStmt, "base", body),
190 };
191 return &node.base;
192 },
193 }
153194 }
154195
155196 /// StaticAssert <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON
156197 fn staticAssert(parser: *Parser) !?*Node {
157198 const tok = parser.eatToken(.Keyword_static_assert) orelse return null;
158199 _ = try parser.expectToken(.LParen);
159 const const_expr = try parser.expect(constExpr, .{
160 .ExpectedExpr = .{ .token = parser.it.index },
161 });
200 const const_expr = try parser.constExpr();
162201 _ = try parser.expectToken(.Comma);
163202 const str = try parser.expectToken(.StringLiteral);
164203 _ = try parser.expectToken(.RParen);
......@@ -173,11 +212,13 @@ const Parser = struct {
173212 }
174213
175214 /// DeclSpec <- (StorageClassSpec / TypeSpec / FnSpec / AlignSpec)*
176 fn declSpec(parser: *Parser) !*Node.DeclSpec {
177 const ds = try parser.arena.create(Node.DeclSpec);
178 ds.* = .{};
179 while ((try parser.storageClassSpec(ds)) or (try parser.typeSpec(&ds.type_spec)) or (try parser.fnSpec(ds)) or (try parser.alignSpec(ds))) {}
180 return ds;
215 /// returns true if any tokens were consumed
216 fn declSpec(parser: *Parser, ds: *Node.DeclSpec) !bool {
217 var got = false;
218 while ((try parser.storageClassSpec(ds)) or (try parser.typeSpec(&ds.type_spec)) or (try parser.fnSpec(ds)) or (try parser.alignSpec(ds))) {
219 got = true;
220 }
221 return got;
181222 }
182223
183224 /// StorageClassSpec
......@@ -213,7 +254,7 @@ const Parser = struct {
213254 } else return false;
214255 return true;
215256 }
216 try parser.warning(.{
257 try parser.warn(.{
217258 .DuplicateSpecifier = .{ .token = parser.it.index },
218259 });
219260 return true;
......@@ -420,7 +461,7 @@ const Parser = struct {
420461 if (type_spec.spec != .None)
421462 break :blk;
422463 _ = try parser.expectToken(.LParen);
423 const name = try parser.expect(typeName, .{
464 const name = (try parser.typeName()) orelse return parser.err(.{
424465 .ExpectedTypeName = .{ .token = parser.it.index },
425466 });
426467 type_spec.spec.Atomic = .{
......@@ -440,7 +481,7 @@ const Parser = struct {
440481 @panic("TODO record type");
441482 // return true;
442483 } else if (parser.eatToken(.Identifier)) |tok| {
443 if (!parser.isTypedef(tok)) {
484 if (!parser.getTypeDef(tok)) {
444485 parser.putBackToken(tok);
445486 return false;
446487 }
......@@ -450,13 +491,12 @@ const Parser = struct {
450491 return true;
451492 }
452493 }
453 try parser.tree.errors.push(.{
494 return parser.err(.{
454495 .InvalidTypeSpecifier = .{
455496 .token = parser.it.index,
456497 .type_spec = type_spec,
457498 },
458499 });
459 return error.ParseError;
460500 }
461501
462502 /// TypeQual <- Keyword_const / Keyword_restrict / Keyword_volatile / Keyword_atomic
......@@ -481,7 +521,7 @@ const Parser = struct {
481521 } else return false;
482522 return true;
483523 }
484 try parser.warning(.{
524 try parser.warn(.{
485525 .DuplicateQualifier = .{ .token = parser.it.index },
486526 });
487527 return true;
......@@ -501,7 +541,7 @@ const Parser = struct {
501541 } else return false;
502542 return true;
503543 }
504 try parser.warning(.{
544 try parser.warn(.{
505545 .DuplicateSpecifier = .{ .token = parser.it.index },
506546 });
507547 return true;
......@@ -511,11 +551,9 @@ const Parser = struct {
511551 fn alignSpec(parser: *Parser, ds: *Node.DeclSpec) !bool {
512552 if (parser.eatToken(.Keyword_alignas)) |tok| {
513553 _ = try parser.expectToken(.LParen);
514 const node = (try parser.typeName()) orelse (try parser.expect(constExpr, .{
515 .ExpectedExpr = .{ .token = parser.it.index },
516 }));
554 const node = (try parser.typeName()) orelse (try parser.constExpr());
517555 if (ds.align_spec != null) {
518 try parser.warning(.{
556 try parser.warn(.{
519557 .DuplicateSpecifier = .{ .token = parser.it.index },
520558 });
521559 }
......@@ -594,7 +632,16 @@ const Parser = struct {
594632 fn assignmentExpr(parser: *Parser) !*Node {}
595633
596634 /// ConstExpr <- ConditionalExpr
597 const constExpr = conditionalExpr;
635 fn constExpr(parser: *Parser) Error!*Node {
636 const start = parser.it.index;
637 const expression = try parser.conditionalExpr();
638 // TODO
639 // if (expression == nullor expression.?.value == null)
640 // return parser.err(.{
641 // .ConsExpr = start,
642 // });
643 return expression.?;
644 }
598645
599646 /// ConditionalExpr <- LogicalOrExpr (QUESTIONMARK Expr COLON ConditionalExpr)?
600647 fn conditionalExpr(parser: *Parser) !*Node {}
......@@ -671,7 +718,7 @@ const Parser = struct {
671718 /// / PERIOD IDENTIFIER
672719 fn designator(parser: *Parser) !*Node {}
673720
674 /// CompoundStmt <- LBRACE (Stmt / Declaration)* RBRACE
721 /// CompoundStmt <- LBRACE (Declaration / Stmt)* RBRACE
675722 fn compoundStmt(parser: *Parser) Error!?*Node {
676723 const lbrace = parser.eatToken(.LBrace) orelse return null;
677724 const body_node = try parser.arena.create(Node.CompoundStmt);
......@@ -680,7 +727,7 @@ const Parser = struct {
680727 .statements = Node.CompoundStmt.StmtList.init(parser.arena),
681728 .rbrace = undefined,
682729 };
683 while ((try parser.stmt()) orelse (try parser.declaration())) |node|
730 while ((try parser.declaration()) orelse (try parser.stmt())) |node|
684731 try body_node.statements.push(node);
685732 body_node.rbrace = try parser.expectToken(.RBrace);
686733 return &body_node.base;
......@@ -708,7 +755,7 @@ const Parser = struct {
708755 _ = try parser.expectToken(.LParen);
709756 node.* = .{
710757 .@"if" = tok,
711 .cond = try parser.expect(expr, .{
758 .cond = (try parser.expr()) orelse return parser.err(.{
712759 .ExpectedExpr = .{ .token = parser.it.index },
713760 }),
714761 .@"else" = null,
......@@ -717,7 +764,7 @@ const Parser = struct {
717764 if (parser.eatToken(.Keyword_else)) |else_tok| {
718765 node.@"else" = .{
719766 .tok = else_tok,
720 .stmt = try parser.expect(stmt, .{
767 .stmt = (try parser.stmt()) orelse return parser.err(.{
721768 .ExpectedStmt = .{ .token = parser.it.index },
722769 }),
723770 };
......@@ -797,7 +844,7 @@ const Parser = struct {
797844
798845 fn eatToken(parser: *Parser, id: @TagType(Token.Id)) ?TokenIndex {
799846 while (true) {
800 switch (parser.it.next() orelse return null) {
847 switch ((parser.it.next() orelse return null).id) {
801848 .LineComment, .MultiLineComment, .Nl => continue,
802849 else => |next_id| if (next_id == id) {
803850 return parser.it.index;
......@@ -811,7 +858,7 @@ const Parser = struct {
811858
812859 fn expectToken(parser: *Parser, id: @TagType(Token.Id)) Error!TokenIndex {
813860 while (true) {
814 switch (parser.it.next() orelse return null) {
861 switch ((parser.it.next() orelse return error.ParseError).id) {
815862 .LineComment, .MultiLineComment, .Nl => continue,
816863 else => |next_id| if (next_id != id) {
817864 return parser.err(.{
......@@ -826,9 +873,10 @@ const Parser = struct {
826873
827874 fn putBackToken(parser: *Parser, putting_back: TokenIndex) void {
828875 while (true) {
829 switch (parser.it.next() orelse return null) {
876 const prev_tok = parser.it.next() orelse return;
877 switch (prev_tok.id) {
830878 .LineComment, .MultiLineComment, .Nl => continue,
831 else => |next_id| {
879 else => {
832880 assert(parser.it.list.at(putting_back) == prev_tok);
833881 return;
834882 },
......@@ -836,23 +884,26 @@ const Parser = struct {
836884 }
837885 }
838886
839 fn expect(
840 parser: *Parser,
841 parseFn: fn (*Parser) Error!?*Node,
842 err: ast.Error, // if parsing fails
843 ) Error!*Node {
844 return (try parseFn(parser)) orelse {
845 try parser.tree.errors.push(err);
846 return error.ParseError;
847 };
887 fn err(parser: *Parser, msg: ast.Error) Error {
888 try parser.tree.msgs.push(.{
889 .kind = .Error,
890 .inner = msg,
891 });
892 return error.ParseError;
848893 }
849894
850 fn warning(parser: *Parser, err: ast.Error) Error!void {
851 if (parser.tree.warnings) |*w| {
852 try w.push(err);
853 return;
854 }
855 try parser.tree.errors.push(err);
856 return error.ParseError;
895 fn warn(parser: *Parser, msg: ast.Error) Error!void {
896 try parser.tree.msgs.push(.{
897 .kind = if (parser.warnings) .Warning else .Error,
898 .inner = msg,
899 });
900 if (!parser.warnings) return error.ParseError;
901 }
902
903 fn note(parser: *Parser, msg: ast.Error) Error!void {
904 try parser.tree.msgs.push(.{
905 .kind = .Note,
906 .inner = msg,
907 });
857908 }
858909};