authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-05 15:15:55+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-05 20:25:51+02:00
logf934f9b41938ee6208d7cdd8a26687bffbe171cf
tree86b7a259399f765054b85b0379eaff2ebf76324d
parent46f292982d6035c7d57ae8d637c770a121c40e37
signaturelock-open Commit is signed but in an unrecognized format.

std-c parser fndef and static assert


2 files changed, 132 insertions(+), 46 deletions(-)

lib/std/c/ast.zig+27-3
......@@ -32,6 +32,8 @@ pub const Error = union(enum) {
3232 ExpectedExpr: SingleTokenError("expected expression, found '{}'"),
3333 ExpectedStmt: SingleTokenError("expected statement, found '{}'"),
3434 ExpectedTypeName: SingleTokenError("expected type name, found '{}'"),
35 ExpectedFnBody: SingleTokenError("expected function body, found '{}'"),
36 ExpectedInitializer: SingleTokenError("expected initializer, found '{}'"),
3537 InvalidTypeSpecifier: InvalidTypeSpecifier,
3638 DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"),
3739 DuplicateSpecifier: SingleTokenError("duplicate declaration specifier '{}'"),
......@@ -43,6 +45,8 @@ pub const Error = union(enum) {
4345 .ExpectedExpr => |*x| return x.render(tokens, stream),
4446 .ExpectedStmt => |*x| return x.render(tokens, stream),
4547 .ExpectedTypeName => |*x| return x.render(tokens, stream),
48 .ExpectedDeclarator => |*x| return x.render(tokens, stream),
49 .ExpectedFnBody => |*x| return x.render(tokens, stream),
4650 .InvalidTypeSpecifier => |*x| return x.render(tokens, stream),
4751 .DuplicateQualifier => |*x| return x.render(tokens, stream),
4852 .DuplicateSpecifier => |*x| return x.render(tokens, stream),
......@@ -56,6 +60,8 @@ pub const Error = union(enum) {
5660 .ExpectedExpr => |x| return x.token,
5761 .ExpectedStmt => |x| return x.token,
5862 .ExpectedTypeName => |x| return x.token,
63 .ExpectedDeclarator => |x| return x.token,
64 .ExpectedFnBody => |x| return x.token,
5965 .InvalidTypeSpecifier => |x| return x.token,
6066 .DuplicateQualifier => |x| return x.token,
6167 .DuplicateSpecifier => |x| return x.token,
......@@ -85,7 +91,7 @@ pub const Error = union(enum) {
8591 try stream.write("invalid type specifier '");
8692 try type_spec.spec.print(tokens, stream);
8793 const token_name = tokens.at(self.token).id.symbol();
88 return stream.print("{}'", .{ token_name });
94 return stream.print("{}'", .{token_name});
8995 }
9096 };
9197
......@@ -111,10 +117,12 @@ pub const Node = struct {
111117 Label,
112118 CompoundStmt,
113119 IfStmt,
120 StaticAssert,
121 FnDef,
114122 };
115123
116124 pub const Root = struct {
117 base: Node,
125 base: Node = Node{ .id = .Root },
118126 decls: DeclList,
119127 eof: TokenIndex,
120128
......@@ -230,7 +238,6 @@ pub const Node = struct {
230238 pub const Label = struct {
231239 base: Node = Node{ .id = .Label },
232240 identifier: TokenIndex,
233 colon: TokenIndex,
234241 };
235242
236243 pub const CompoundStmt = struct {
......@@ -251,4 +258,21 @@ pub const Node = struct {
251258 stmt: *Node,
252259 },
253260 };
261
262 pub const StaticAssert = struct {
263 base: Node = Node{ .id = .StaticAssert },
264 assert: TokenIndex,
265 expr: *Node,
266 semicolon: TokenIndex,
267 };
268
269 pub const FnDef = struct {
270 base: Node = Node{ .id = .FnDef },
271 decl_spec: *DeclSpec,
272 declarator: *Node,
273 old_decls: OldDeclList,
274 body: *CompoundStmt,
275
276 pub const OldDeclList = SegmentedList(*Node, 0);
277 };
254278};
lib/std/c/parse.zig+105-43
......@@ -78,10 +78,10 @@ const Parser = struct {
7878 }
7979
8080 /// Root <- ExternalDeclaration* eof
81 fn root(parser: *Parser) Allocator.Error!*Node {
82 const node = try arena.create(ast.Root);
81 fn root(parser: *Parser) Allocator.Error!*Node.Root {
82 const node = try parser.arena.create(Node.Root);
8383 node.* = .{
84 .decls = ast.Node.DeclList.init(arena),
84 .decls = Node.Root.DeclList.init(parser.arena),
8585 .eof = undefined,
8686 };
8787 while (parser.externalDeclarations() catch |err| switch (err) {
......@@ -90,31 +90,87 @@ const Parser = struct {
9090 }) |decl| {
9191 try node.decls.push(decl);
9292 }
93 node.eof = eatToken(it, .Eof) orelse {
94 try tree.errors.push(.{
95 .ExpectedDecl = .{ .token = it.index },
96 });
97 return node;
98 };
93 node.eof = parser.eatToken(.Eof) orelse return node;
9994 return node;
10095 }
10196
10297 /// ExternalDeclaration
10398 /// <- DeclSpec Declarator Declaration* CompoundStmt
104 /// / DeclSpec (Declarator (EQUAL Initializer)?)* SEMICOLON
105 /// / StaticAssert
99 /// / Declaration
106100 fn externalDeclarations(parser: *Parser) !?*Node {
107 if (try Declaration(parser)) |decl| {}
108 return null;
101 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 });
108 // TODO disallow auto and register
109 const next_tok = parser.it.peek().?;
110 switch (next_tok.id) {
111 .Semicolon,
112 .Equal,
113 .Comma,
114 .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;
109135 }
110136
111137 /// Declaration
112 /// <- DeclSpec (Declarator (EQUAL Initializer)?)* SEMICOLON
138 /// <- DeclSpec (Declarator (EQUAL Initializer)? COMMA)* SEMICOLON
113139 /// / StaticAssert
114 fn declaration(parser: *Parser) !?*Node {}
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 }
151
152 fn declarationExtra(parser: *Parser, ds: *Node.DeclSpec, dr: ?*Node, local: bool) !?*Node {
153 }
115154
116155 /// StaticAssert <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON
117 fn StaticAssert(parser: *Parser) !?*Node {}
156 fn staticAssert(parser: *Parser) !?*Node {
157 const tok = parser.eatToken(.Keyword_static_assert) orelse return null;
158 _ = try parser.expectToken(.LParen);
159 const const_expr = try parser.expect(constExpr, .{
160 .ExpectedExpr = .{ .token = parser.it.index },
161 });
162 _ = try parser.expectToken(.Comma);
163 const str = try parser.expectToken(.StringLiteral);
164 _ = try parser.expectToken(.RParen);
165 const semicolon = try parser.expectToken(.Semicolon);
166 const node = try parser.arena.create(Node.StaticAssert);
167 node.* = .{
168 .assert = tok,
169 .expr = const_expr,
170 .semicolon = semicolon,
171 };
172 return &node.base;
173 }
118174
119175 /// DeclSpec <- (StorageClassSpec / TypeSpec / FnSpec / AlignSpec)*
120176 fn declSpec(parser: *Parser) !*Node.DeclSpec {
......@@ -455,7 +511,7 @@ const Parser = struct {
455511 fn alignSpec(parser: *Parser, ds: *Node.DeclSpec) !bool {
456512 if (parser.eatToken(.Keyword_alignas)) |tok| {
457513 _ = try parser.expectToken(.LParen);
458 const node = (try parser.typeName()) orelse (try parser.expect(conditionalExpr, .{
514 const node = (try parser.typeName()) orelse (try parser.expect(constExpr, .{
459515 .ExpectedExpr = .{ .token = parser.it.index },
460516 }));
461517 if (ds.align_spec != null) {
......@@ -538,6 +594,8 @@ const Parser = struct {
538594 fn assignmentExpr(parser: *Parser) !*Node {}
539595
540596 /// ConstExpr <- ConditionalExpr
597 const constExpr = conditionalExpr;
598
541599 /// ConditionalExpr <- LogicalOrExpr (QUESTIONMARK Expr COLON ConditionalExpr)?
542600 fn conditionalExpr(parser: *Parser) !*Node {}
543601
......@@ -613,19 +671,19 @@ const Parser = struct {
613671 /// / PERIOD IDENTIFIER
614672 fn designator(parser: *Parser) !*Node {}
615673
616 /// CompoundStmt <- LBRACE (Declaration / Stmt)* RBRACE
617 fn compoundStmt(parser: *Parser) !?*Node {
674 /// CompoundStmt <- LBRACE (Stmt / Declaration)* RBRACE
675 fn compoundStmt(parser: *Parser) Error!?*Node {
618676 const lbrace = parser.eatToken(.LBrace) orelse return null;
619 const node = try parser.arena.create(Node.CompoundStmt);
620 node.* = .{
677 const body_node = try parser.arena.create(Node.CompoundStmt);
678 body_node.* = .{
621679 .lbrace = lbrace,
622 .statements = Node.JumpStmt.StmtList.init(parser.arena),
680 .statements = Node.CompoundStmt.StmtList.init(parser.arena),
623681 .rbrace = undefined,
624682 };
625 while (parser.declaration() orelse parser.stmt()) |node|
626 try node.statements.push(node);
627 node.rbrace = try parser.expectToken(.RBrace);
628 return &node.base;
683 while ((try parser.stmt()) orelse (try parser.declaration())) |node|
684 try body_node.statements.push(node);
685 body_node.rbrace = try parser.expectToken(.RBrace);
686 return &body_node.base;
629687 }
630688
631689 /// Stmt
......@@ -643,15 +701,15 @@ const Parser = struct {
643701 /// / Keyword_return Expr? SEMICOLON
644702 /// / IDENTIFIER COLON Stmt
645703 /// / ExprStmt
646 fn stmt(parser: *Parser) !?*Node {
647 if (parser.compoundStmt()) |node| return node;
704 fn stmt(parser: *Parser) Error!?*Node {
705 if (try parser.compoundStmt()) |node| return node;
648706 if (parser.eatToken(.Keyword_if)) |tok| {
649707 const node = try parser.arena.create(Node.IfStmt);
650708 _ = try parser.expectToken(.LParen);
651709 node.* = .{
652710 .@"if" = tok,
653711 .cond = try parser.expect(expr, .{
654 .ExpectedExpr = .{ .token = it.index },
712 .ExpectedExpr = .{ .token = parser.it.index },
655713 }),
656714 .@"else" = null,
657715 };
......@@ -659,8 +717,8 @@ const Parser = struct {
659717 if (parser.eatToken(.Keyword_else)) |else_tok| {
660718 node.@"else" = .{
661719 .tok = else_tok,
662 .stmt = try parser.stmt(expr, .{
663 .ExpectedStmt = .{ .token = it.index },
720 .stmt = try parser.expect(stmt, .{
721 .ExpectedStmt = .{ .token = parser.it.index },
664722 }),
665723 };
666724 }
......@@ -676,8 +734,8 @@ const Parser = struct {
676734 const node = try parser.arena.create(Node.JumpStmt);
677735 node.* = .{
678736 .ltoken = tok,
679 .kind = .Goto,
680 .semicolon = parser.expectToken(.Semicolon),
737 .kind = .{ .Goto = tok },
738 .semicolon = try parser.expectToken(.Semicolon),
681739 };
682740 return &node.base;
683741 }
......@@ -686,7 +744,7 @@ const Parser = struct {
686744 node.* = .{
687745 .ltoken = tok,
688746 .kind = .Continue,
689 .semicolon = parser.expectToken(.Semicolon),
747 .semicolon = try parser.expectToken(.Semicolon),
690748 };
691749 return &node.base;
692750 }
......@@ -695,7 +753,7 @@ const Parser = struct {
695753 node.* = .{
696754 .ltoken = tok,
697755 .kind = .Break,
698 .semicolon = parser.expectToken(.Semicolon),
756 .semicolon = try parser.expectToken(.Semicolon),
699757 };
700758 return &node.base;
701759 }
......@@ -704,31 +762,35 @@ const Parser = struct {
704762 node.* = .{
705763 .ltoken = tok,
706764 .kind = .{ .Return = try parser.expr() },
707 .semicolon = parser.expectToken(.Semicolon),
765 .semicolon = try parser.expectToken(.Semicolon),
708766 };
709767 return &node.base;
710768 }
711769 if (parser.eatToken(.Identifier)) |tok| {
712 if (parser.eatToken(.Colon)) |col| {
770 if (parser.eatToken(.Colon)) |_| {
713771 const node = try parser.arena.create(Node.Label);
714772 node.* = .{
715773 .identifier = tok,
716 .semicolon = parser.expectToken(.Colon),
717774 };
718775 return &node.base;
719776 }
720 putBackToken(tok);
777 parser.putBackToken(tok);
721778 }
722 if (parser.exprStmt()) |node| return node;
779 if (try parser.exprStmt()) |node| return node;
723780 return null;
724781 }
725782
726783 /// ExprStmt <- Expr? SEMICOLON
727 fn exprStmt(parser: *Parser) !*Node {
784 fn exprStmt(parser: *Parser) !?*Node {
728785 const node = try parser.arena.create(Node.ExprStmt);
786 const expr_node = try parser.expr();
787 const semicolon = if (expr_node != null)
788 try parser.expectToken(.Semicolon)
789 else
790 parser.eatToken(.Semicolon) orelse return null;
729791 node.* = .{
730 .expr = try parser.expr(),
731 .semicolon = parser.expectToken(.Semicolon),
792 .expr = expr_node,
793 .semicolon = semicolon,
732794 };
733795 return &node.base;
734796 }