authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-04 22:27:05+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-05 20:25:51+02:00
logdccf1247b21ee2b15f6ec3c01c908b29b5c60f24
tree5804f1c6e72bbc23f704540aaa348c79e2b2a0ff
parenta20c0b31de2b6d8de568707429754a6d39d3346d
signaturelock-open Commit is signed but in an unrecognized format.

std-c ifstmt compoundstmt and errors


3 files changed, 211 insertions(+), 10 deletions(-)

lib/std/c/ast.zig+48-5
......@@ -26,21 +26,43 @@ pub const Tree = struct {
2626};
2727
2828pub const Error = union(enum) {
29 InvalidToken: InvalidToken,
29 InvalidToken: SingleTokenError("Invalid token '{}'"),
30 ExpectedToken: ExpectedToken,
31 ExpectedExpr: SingleTokenError("Expected expression, found '{}'"),
32 ExpectedStmt: SingleTokenError("Expected statement, found '{}'"),
3033
3134 pub fn render(self: *const Error, tokens: *Tree.TokenList, stream: var) !void {
3235 switch (self.*) {
3336 .InvalidToken => |*x| return x.render(tokens, stream),
37 .ExpectedToken => |*x| return x.render(tokens, stream),
38 .ExpectedExpr => |*x| return x.render(tokens, stream),
39 .ExpectedStmt => |*x| return x.render(tokens, stream),
3440 }
3541 }
3642
3743 pub fn loc(self: *const Error) TokenIndex {
3844 switch (self.*) {
3945 .InvalidToken => |x| return x.token,
46 .ExpectedToken => |x| return x.token,
47 .ExpectedExpr => |x| return x.token,
48 .ExpectedStmt => |x| return x.token,
4049 }
4150 }
4251
43 pub const InvalidToken = SingleTokenError("Invalid token '{}'");
52 pub const ExpectedToken = struct {
53 token: TokenIndex,
54 expected_id: @TagType(Token.Id),
55
56 pub fn render(self: *const ExpectedToken, tokens: *Tree.TokenList, stream: var) !void {
57 const found_token = tokens.at(self.token);
58 if (found_token.id == .Invalid) {
59 return stream.print("expected '{}', found invalid bytes", .{self.expected_id.symbol()});
60 } else {
61 const token_name = found_token.id.symbol();
62 return stream.print("expected '{}', found '{}'", .{ self.expected_id.symbol(), token_name });
63 }
64 }
65 };
4466
4567 fn SingleTokenError(comptime msg: []const u8) type {
4668 return struct {
......@@ -62,6 +84,8 @@ pub const Node = struct {
6284 JumpStmt,
6385 ExprStmt,
6486 Label,
87 CompoundStmt,
88 IfStmt,
6589 };
6690
6791 pub const Root = struct {
......@@ -73,7 +97,7 @@ pub const Node = struct {
7397 };
7498
7599 pub const JumpStmt = struct {
76 base: Node = Node{ .id = .JumpStmt},
100 base: Node = Node{ .id = .JumpStmt },
77101 ltoken: TokenIndex,
78102 kind: Kind,
79103 semicolon: TokenIndex,
......@@ -87,14 +111,33 @@ pub const Node = struct {
87111 };
88112
89113 pub const ExprStmt = struct {
90 base: Node = Node{ .id = .ExprStmt},
114 base: Node = Node{ .id = .ExprStmt },
91115 expr: ?*Node,
92116 semicolon: TokenIndex,
93117 };
94118
95119 pub const Label = struct {
96 base: Node = Node{ .id = .Label},
120 base: Node = Node{ .id = .Label },
97121 identifier: TokenIndex,
98122 colon: TokenIndex,
99123 };
124
125 pub const CompoundStmt = struct {
126 base: Node = Node{ .id = .CompoundStmt },
127 lbrace: TokenIndex,
128 statements: StmtList,
129 rbrace: TokenIndex,
130
131 pub const StmtList = Root.DeclList;
132 };
133
134 pub const IfStmt = struct {
135 base: Node = Node{ .id = .IfStmt },
136 @"if": TokenIndex,
137 cond: *Node,
138 @"else": ?struct {
139 tok: TokenIndex,
140 stmt: *Node,
141 },
142 };
100143};
lib/std/c/parse.zig+45-2
......@@ -284,7 +284,19 @@ const Parser = struct {
284284 fn designator(parser: *Parser) !*Node {}
285285
286286 /// CompoundStmt <- LBRACE (Declaration / Stmt)* RBRACE
287 fn compoundStmt(parser: *Parser) !?*Node {}
287 fn compoundStmt(parser: *Parser) !?*Node {
288 const lbrace = parser.eatToken(.LBrace) orelse return null;
289 const node = try parser.arena.create(Node.CompoundStmt);
290 node.* = .{
291 .lbrace = lbrace,
292 .statements = Node.JumpStmt.StmtList.init(parser.arena),
293 .rbrace = undefined,
294 };
295 while (parser.declaration() orelse parser.stmt()) |node|
296 try node.statements.push(node);
297 node.rbrace = try parser.expectToken(.RBrace);
298 return &node.base;
299 }
288300
289301 /// Stmt
290302 /// <- CompoundStmt
......@@ -303,7 +315,27 @@ const Parser = struct {
303315 /// / ExprStmt
304316 fn stmt(parser: *Parser) !?*Node {
305317 if (parser.compoundStmt()) |node| return node;
306 // if (parser.eatToken(.Keyword_if)) |tok| {}
318 if (parser.eatToken(.Keyword_if)) |tok| {
319 const node = try parser.arena.create(Node.IfStmt);
320 _ = try parser.expectToken(.LParen);
321 node.* = .{
322 .@"if" = tok,
323 .cond = try parser.expect(expr, .{
324 .ExpectedExpr = .{ .token = it.index },
325 }),
326 .@"else" = null,
327 };
328 _ = try parser.expectToken(.RParen);
329 if (parser.eatToken(.Keyword_else)) |else_tok| {
330 node.@"else" = .{
331 .tok = else_tok,
332 .stmt = try parser.stmt(expr, .{
333 .ExpectedStmt = .{ .token = it.index },
334 }),
335 };
336 }
337 return &node.base;
338 }
307339 // if (parser.eatToken(.Keyword_switch)) |tok| {}
308340 // if (parser.eatToken(.Keyword_while)) |tok| {}
309341 // if (parser.eatToken(.Keyword_do)) |tok| {}
......@@ -407,4 +439,15 @@ const Parser = struct {
407439 return;
408440 }
409441 }
442
443 fn expect(
444 parser: *Parser,
445 parseFn: fn (*Parser) Error!?*Node,
446 err: ast.Error, // if parsing fails
447 ) Error!*Node {
448 return (try parseFn(arena, it, tree)) orelse {
449 try parser.tree.errors.push(err);
450 return error.ParseError;
451 };
452 }
410453};
lib/std/c/tokenizer.zig+118-3
......@@ -6,7 +6,7 @@ pub const Source = struct {
66 file_name: []const u8,
77 tokens: TokenList,
88
9 pub const TokenList = SegmentedList(Token, 64);
9 pub const TokenList = std.SegmentedList(Token, 64);
1010};
1111
1212pub const Token = struct {
......@@ -134,6 +134,121 @@ pub const Token = struct {
134134 Keyword_ifndef,
135135 Keyword_error,
136136 Keyword_pragma,
137
138 pub fn symbol(tok: Token) []const u8 {
139 return switch (tok.id) {
140 .Invalid => "Invalid",
141 .Eof => "Eof",
142 .Nl => "NewLine",
143 .Identifier => "Identifier",
144 .MacroString => "MacroString",
145 .StringLiteral => "StringLiteral",
146 .CharLiteral => "CharLiteral",
147 .IntegerLiteral => "IntegerLiteral",
148 .FloatLiteral => "FloatLiteral",
149 .LineComment => "LineComment",
150 .MultiLineComment => "MultiLineComment",
151
152 .Bang => "!",
153 .BangEqual => "!=",
154 .Pipe => "|",
155 .PipePipe => "||",
156 .PipeEqual => "|=",
157 .Equal => "=",
158 .EqualEqual => "==",
159 .LParen => "(",
160 .RParen => ")",
161 .LBrace => "{",
162 .RBrace => "}",
163 .LBracket => "[",
164 .RBracket => "]",
165 .Period => ".",
166 .Ellipsis => "...",
167 .Caret => "^",
168 .CaretEqual => "^=",
169 .Plus => "+",
170 .PlusPlus => "++",
171 .PlusEqual => "+=",
172 .Minus => "-",
173 .MinusMinus => "--",
174 .MinusEqual => "-=",
175 .Asterisk => "*",
176 .AsteriskEqual => "*=",
177 .Percent => "%",
178 .PercentEqual => "%=",
179 .Arrow => "->",
180 .Colon => ":",
181 .Semicolon => ";",
182 .Slash => "/",
183 .SlashEqual => "/=",
184 .Comma => ",",
185 .Ampersand => "&",
186 .AmpersandAmpersand => "&&",
187 .AmpersandEqual => "&=",
188 .QuestionMark => "?",
189 .AngleBracketLeft => "<",
190 .AngleBracketLeftEqual => "<=",
191 .AngleBracketAngleBracketLeft => "<<",
192 .AngleBracketAngleBracketLeftEqual => "<<=",
193 .AngleBracketRight => ">",
194 .AngleBracketRightEqual => ">=",
195 .AngleBracketAngleBracketRight => ">>",
196 .AngleBracketAngleBracketRightEqual => ">>=",
197 .Tilde => "~",
198 .Hash => "#",
199 .HashHash => "##",
200 .Keyword_auto => "auto",
201 .Keyword_break => "break",
202 .Keyword_case => "case",
203 .Keyword_char => "char",
204 .Keyword_const => "const",
205 .Keyword_continue => "continue",
206 .Keyword_default => "default",
207 .Keyword_do => "do",
208 .Keyword_double => "double",
209 .Keyword_else => "else",
210 .Keyword_enum => "enum",
211 .Keyword_extern => "extern",
212 .Keyword_float => "float",
213 .Keyword_for => "for",
214 .Keyword_goto => "goto",
215 .Keyword_if => "if",
216 .Keyword_int => "int",
217 .Keyword_long => "long",
218 .Keyword_register => "register",
219 .Keyword_return => "return",
220 .Keyword_short => "short",
221 .Keyword_signed => "signed",
222 .Keyword_sizeof => "sizeof",
223 .Keyword_static => "static",
224 .Keyword_struct => "struct",
225 .Keyword_switch => "switch",
226 .Keyword_typedef => "typedef",
227 .Keyword_union => "union",
228 .Keyword_unsigned => "unsigned",
229 .Keyword_void => "void",
230 .Keyword_volatile => "volatile",
231 .Keyword_while => "while",
232 .Keyword_bool => "_Bool",
233 .Keyword_complex => "_Complex",
234 .Keyword_imaginary => "_Imaginary",
235 .Keyword_inline => "inline",
236 .Keyword_restrict => "restrict",
237 .Keyword_alignas => "_Alignas",
238 .Keyword_alignof => "_Alignof",
239 .Keyword_atomic => "_Atomic",
240 .Keyword_generic => "_Generic",
241 .Keyword_noreturn => "_Noreturn",
242 .Keyword_static_assert => "_Static_assert",
243 .Keyword_thread_local => "_Thread_local",
244 .Keyword_include => "include",
245 .Keyword_define => "define",
246 .Keyword_ifdef => "ifdef",
247 .Keyword_ifndef => "ifndef",
248 .Keyword_error => "error",
249 .Keyword_pragma => "pragma",
250 };
251 }
137252 };
138253
139254 pub const Keyword = struct {
......@@ -1121,8 +1236,7 @@ pub const Tokenizer = struct {
11211236 }
11221237 } else if (self.index == self.source.buffer.len) {
11231238 switch (state) {
1124 .AfterStringLiteral,
1125 .Start => {},
1239 .AfterStringLiteral, .Start => {},
11261240 .u, .u8, .U, .L, .Identifier => {
11271241 result.id = Token.getKeyword(self.source.buffer[result.start..self.index], self.prev_tok_id == .Hash and !self.pp_directive) orelse .Identifier;
11281242 },
......@@ -1416,6 +1530,7 @@ fn expectTokens(source: []const u8, expected_tokens: []const Token.Id) void {
14161530 .source = &Source{
14171531 .buffer = source,
14181532 .file_name = undefined,
1533 .tokens = undefined,
14191534 },
14201535 };
14211536 for (expected_tokens) |expected_token_id| {