| author | |
| committer | |
| log | dccf1247b21ee2b15f6ec3c01c908b29b5c60f24 |
| tree | 5804f1c6e72bbc23f704540aaa348c79e2b2a0ff |
| parent | a20c0b31de2b6d8de568707429754a6d39d3346d |
| signature | Commit is signed but in an unrecognized format. |
3 files changed, 211 insertions(+), 10 deletions(-)
lib/std/c/ast.zig+48-5| ... | ... | @@ -26,21 +26,43 @@ pub const Tree = struct { |
| 26 | 26 | }; |
| 27 | 27 | |
| 28 | 28 | pub 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 '{}'"), | |
| 30 | 33 | |
| 31 | 34 | pub fn render(self: *const Error, tokens: *Tree.TokenList, stream: var) !void { |
| 32 | 35 | switch (self.*) { |
| 33 | 36 | .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), | |
| 34 | 40 | } |
| 35 | 41 | } |
| 36 | 42 | |
| 37 | 43 | pub fn loc(self: *const Error) TokenIndex { |
| 38 | 44 | switch (self.*) { |
| 39 | 45 | .InvalidToken => |x| return x.token, |
| 46 | .ExpectedToken => |x| return x.token, | |
| 47 | .ExpectedExpr => |x| return x.token, | |
| 48 | .ExpectedStmt => |x| return x.token, | |
| 40 | 49 | } |
| 41 | 50 | } |
| 42 | 51 | |
| 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 | }; | |
| 44 | 66 | |
| 45 | 67 | fn SingleTokenError(comptime msg: []const u8) type { |
| 46 | 68 | return struct { |
| ... | ... | @@ -62,6 +84,8 @@ pub const Node = struct { |
| 62 | 84 | JumpStmt, |
| 63 | 85 | ExprStmt, |
| 64 | 86 | Label, |
| 87 | CompoundStmt, | |
| 88 | IfStmt, | |
| 65 | 89 | }; |
| 66 | 90 | |
| 67 | 91 | pub const Root = struct { |
| ... | ... | @@ -73,7 +97,7 @@ pub const Node = struct { |
| 73 | 97 | }; |
| 74 | 98 | |
| 75 | 99 | pub const JumpStmt = struct { |
| 76 | base: Node = Node{ .id = .JumpStmt}, | |
| 100 | base: Node = Node{ .id = .JumpStmt }, | |
| 77 | 101 | ltoken: TokenIndex, |
| 78 | 102 | kind: Kind, |
| 79 | 103 | semicolon: TokenIndex, |
| ... | ... | @@ -87,14 +111,33 @@ pub const Node = struct { |
| 87 | 111 | }; |
| 88 | 112 | |
| 89 | 113 | pub const ExprStmt = struct { |
| 90 | base: Node = Node{ .id = .ExprStmt}, | |
| 114 | base: Node = Node{ .id = .ExprStmt }, | |
| 91 | 115 | expr: ?*Node, |
| 92 | 116 | semicolon: TokenIndex, |
| 93 | 117 | }; |
| 94 | 118 | |
| 95 | 119 | pub const Label = struct { |
| 96 | base: Node = Node{ .id = .Label}, | |
| 120 | base: Node = Node{ .id = .Label }, | |
| 97 | 121 | identifier: TokenIndex, |
| 98 | 122 | colon: TokenIndex, |
| 99 | 123 | }; |
| 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 | }; | |
| 100 | 143 | }; |
lib/std/c/parse.zig+45-2| ... | ... | @@ -284,7 +284,19 @@ const Parser = struct { |
| 284 | 284 | fn designator(parser: *Parser) !*Node {} |
| 285 | 285 | |
| 286 | 286 | /// 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 | } | |
| 288 | 300 | |
| 289 | 301 | /// Stmt |
| 290 | 302 | /// <- CompoundStmt |
| ... | ... | @@ -303,7 +315,27 @@ const Parser = struct { |
| 303 | 315 | /// / ExprStmt |
| 304 | 316 | fn stmt(parser: *Parser) !?*Node { |
| 305 | 317 | 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 | } | |
| 307 | 339 | // if (parser.eatToken(.Keyword_switch)) |tok| {} |
| 308 | 340 | // if (parser.eatToken(.Keyword_while)) |tok| {} |
| 309 | 341 | // if (parser.eatToken(.Keyword_do)) |tok| {} |
| ... | ... | @@ -407,4 +439,15 @@ const Parser = struct { |
| 407 | 439 | return; |
| 408 | 440 | } |
| 409 | 441 | } |
| 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 | } | |
| 410 | 453 | }; |
lib/std/c/tokenizer.zig+118-3| ... | ... | @@ -6,7 +6,7 @@ pub const Source = struct { |
| 6 | 6 | file_name: []const u8, |
| 7 | 7 | tokens: TokenList, |
| 8 | 8 | |
| 9 | pub const TokenList = SegmentedList(Token, 64); | |
| 9 | pub const TokenList = std.SegmentedList(Token, 64); | |
| 10 | 10 | }; |
| 11 | 11 | |
| 12 | 12 | pub const Token = struct { |
| ... | ... | @@ -134,6 +134,121 @@ pub const Token = struct { |
| 134 | 134 | Keyword_ifndef, |
| 135 | 135 | Keyword_error, |
| 136 | 136 | 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 | } | |
| 137 | 252 | }; |
| 138 | 253 | |
| 139 | 254 | pub const Keyword = struct { |
| ... | ... | @@ -1121,8 +1236,7 @@ pub const Tokenizer = struct { |
| 1121 | 1236 | } |
| 1122 | 1237 | } else if (self.index == self.source.buffer.len) { |
| 1123 | 1238 | switch (state) { |
| 1124 | .AfterStringLiteral, | |
| 1125 | .Start => {}, | |
| 1239 | .AfterStringLiteral, .Start => {}, | |
| 1126 | 1240 | .u, .u8, .U, .L, .Identifier => { |
| 1127 | 1241 | result.id = Token.getKeyword(self.source.buffer[result.start..self.index], self.prev_tok_id == .Hash and !self.pp_directive) orelse .Identifier; |
| 1128 | 1242 | }, |
| ... | ... | @@ -1416,6 +1530,7 @@ fn expectTokens(source: []const u8, expected_tokens: []const Token.Id) void { |
| 1416 | 1530 | .source = &Source{ |
| 1417 | 1531 | .buffer = source, |
| 1418 | 1532 | .file_name = undefined, |
| 1533 | .tokens = undefined, | |
| 1419 | 1534 | }, |
| 1420 | 1535 | }; |
| 1421 | 1536 | for (expected_tokens) |expected_token_id| { |