| ... | ... | @@ -23,6 +23,11 @@ pub const Tree = struct { |
| 23 | 23 | arena_allocator.deinit(); |
| 24 | 24 | // self is destroyed |
| 25 | 25 | } |
| 26 | |
| 27 | pub fn slice(tree: *Tree, token: TokenIndex) []const u8 { |
| 28 | const tok = tree.tokens.at(token); |
| 29 | return tok.source.buffer[tok.start..tok.end]; |
| 30 | } |
| 26 | 31 | }; |
| 27 | 32 | |
| 28 | 33 | pub const Msg = struct { |
| ... | ... | @@ -47,19 +52,19 @@ pub const Error = union(enum) { |
| 47 | 52 | DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"), |
| 48 | 53 | DuplicateSpecifier: SingleTokenError("duplicate declaration specifier '{}'"), |
| 49 | 54 | |
| 50 | | pub fn render(self: *const Error, tokens: *Tree.TokenList, stream: var) !void { |
| 55 | pub fn render(self: *const Error, tree: *Tree, stream: var) !void { |
| 51 | 56 | switch (self.*) { |
| 52 | | .InvalidToken => |*x| return x.render(tokens, stream), |
| 53 | | .ExpectedToken => |*x| return x.render(tokens, stream), |
| 54 | | .ExpectedExpr => |*x| return x.render(tokens, stream), |
| 55 | | .ExpectedStmt => |*x| return x.render(tokens, stream), |
| 56 | | .ExpectedTypeName => |*x| return x.render(tokens, stream), |
| 57 | | .ExpectedDeclarator => |*x| return x.render(tokens, stream), |
| 58 | | .ExpectedFnBody => |*x| return x.render(tokens, stream), |
| 59 | | .ExpectedInitializer => |*x| return x.render(tokens, stream), |
| 60 | | .InvalidTypeSpecifier => |*x| return x.render(tokens, stream), |
| 61 | | .DuplicateQualifier => |*x| return x.render(tokens, stream), |
| 62 | | .DuplicateSpecifier => |*x| return x.render(tokens, stream), |
| 57 | .InvalidToken => |*x| return x.render(tree, stream), |
| 58 | .ExpectedToken => |*x| return x.render(tree, stream), |
| 59 | .ExpectedExpr => |*x| return x.render(tree, stream), |
| 60 | .ExpectedStmt => |*x| return x.render(tree, stream), |
| 61 | .ExpectedTypeName => |*x| return x.render(tree, stream), |
| 62 | .ExpectedDeclarator => |*x| return x.render(tree, stream), |
| 63 | .ExpectedFnBody => |*x| return x.render(tree, stream), |
| 64 | .ExpectedInitializer => |*x| return x.render(tree, stream), |
| 65 | .InvalidTypeSpecifier => |*x| return x.render(tree, stream), |
| 66 | .DuplicateQualifier => |*x| return x.render(tree, stream), |
| 67 | .DuplicateSpecifier => |*x| return x.render(tree, stream), |
| 63 | 68 | } |
| 64 | 69 | } |
| 65 | 70 | |
| ... | ... | @@ -83,8 +88,8 @@ pub const Error = union(enum) { |
| 83 | 88 | token: TokenIndex, |
| 84 | 89 | expected_id: @TagType(Token.Id), |
| 85 | 90 | |
| 86 | | pub fn render(self: *const ExpectedToken, tokens: *Tree.TokenList, stream: var) !void { |
| 87 | | const found_token = tokens.at(self.token); |
| 91 | pub fn render(self: *const ExpectedToken, tree: *Tree, stream: var) !void { |
| 92 | const found_token = tree.tokens.at(self.token); |
| 88 | 93 | if (found_token.id == .Invalid) { |
| 89 | 94 | return stream.print("expected '{}', found invalid bytes", .{self.expected_id.symbol()}); |
| 90 | 95 | } else { |
| ... | ... | @@ -98,10 +103,10 @@ pub const Error = union(enum) { |
| 98 | 103 | token: TokenIndex, |
| 99 | 104 | type_spec: *Node.TypeSpec, |
| 100 | 105 | |
| 101 | | pub fn render(self: *const ExpectedToken, tokens: *Tree.TokenList, stream: var) !void { |
| 106 | pub fn render(self: *const ExpectedToken, tree: *Tree, stream: var) !void { |
| 102 | 107 | try stream.write("invalid type specifier '"); |
| 103 | | try type_spec.spec.print(tokens, stream); |
| 104 | | const token_name = tokens.at(self.token).id.symbol(); |
| 108 | try type_spec.spec.print(tree, stream); |
| 109 | const token_name = tree.tokens.at(self.token).id.symbol(); |
| 105 | 110 | return stream.print("{}'", .{token_name}); |
| 106 | 111 | } |
| 107 | 112 | }; |
| ... | ... | @@ -110,14 +115,59 @@ pub const Error = union(enum) { |
| 110 | 115 | return struct { |
| 111 | 116 | token: TokenIndex, |
| 112 | 117 | |
| 113 | | pub fn render(self: *const @This(), tokens: *Tree.TokenList, stream: var) !void { |
| 114 | | const actual_token = tokens.at(self.token); |
| 118 | pub fn render(self: *const @This(), tree: *Tree, stream: var) !void { |
| 119 | const actual_token = tree.tokens.at(self.token); |
| 115 | 120 | return stream.print(msg, .{actual_token.id.symbol()}); |
| 116 | 121 | } |
| 117 | 122 | }; |
| 118 | 123 | } |
| 119 | 124 | }; |
| 120 | 125 | |
| 126 | pub const Type = struct { |
| 127 | pub const TypeList = std.SegmentedList(*Type, 4); |
| 128 | @"const": bool, |
| 129 | atomic: bool, |
| 130 | @"volatile": bool, |
| 131 | restrict: bool, |
| 132 | |
| 133 | id: union(enum) { |
| 134 | Int: struct { |
| 135 | quals: Qualifiers, |
| 136 | id: Id, |
| 137 | is_signed: bool, |
| 138 | |
| 139 | pub const Id = enum { |
| 140 | Char, |
| 141 | Short, |
| 142 | Int, |
| 143 | Long, |
| 144 | LongLong, |
| 145 | }; |
| 146 | }, |
| 147 | Float: struct { |
| 148 | quals: Qualifiers, |
| 149 | id: Id, |
| 150 | |
| 151 | pub const Id = enum { |
| 152 | Float, |
| 153 | Double, |
| 154 | LongDouble, |
| 155 | }; |
| 156 | }, |
| 157 | Pointer: struct { |
| 158 | quals: Qualifiers, |
| 159 | child_type: *Type, |
| 160 | }, |
| 161 | Function: struct { |
| 162 | return_type: *Type, |
| 163 | param_types: TypeList, |
| 164 | }, |
| 165 | Typedef: *Type, |
| 166 | Record: *Node.RecordType, |
| 167 | Enum: *Node.EnumType, |
| 168 | }, |
| 169 | }; |
| 170 | |
| 121 | 171 | pub const Node = struct { |
| 122 | 172 | id: Id, |
| 123 | 173 | |
| ... | ... | @@ -205,22 +255,128 @@ pub const Node = struct { |
| 205 | 255 | typename: *Node, |
| 206 | 256 | rparen: TokenIndex, |
| 207 | 257 | }, |
| 258 | Enum: *EnumType, |
| 259 | Record: *RecordType, |
| 260 | Typedef: struct { |
| 261 | sym: TokenIndex, |
| 262 | sym_type: *Type, |
| 263 | }, |
| 208 | 264 | |
| 209 | | //todo |
| 210 | | // @"enum", |
| 211 | | // record, |
| 212 | | |
| 213 | | Typedef: TokenIndex, |
| 214 | | |
| 215 | | pub fn print(self: *@This(), self: *const @This(), tokens: *Tree.TokenList, stream: var) !void { |
| 216 | | switch (self) { |
| 265 | pub fn print(self: *@This(), self: *const @This(), tree: *Tree, stream: var) !void { |
| 266 | switch (self.spec) { |
| 217 | 267 | .None => unreachable, |
| 218 | | else => @panic("TODO print type specifier"), |
| 268 | .Void => |index| try stream.write(tree.slice(index)), |
| 269 | .Char => |char| { |
| 270 | if (char.sign) |s| { |
| 271 | try stream.write(tree.slice(s)); |
| 272 | try stream.writeByte(' '); |
| 273 | } |
| 274 | try stream.write(tree.slice(char.char)); |
| 275 | }, |
| 276 | .Short => |short| { |
| 277 | if (short.sign) |s| { |
| 278 | try stream.write(tree.slice(s)); |
| 279 | try stream.writeByte(' '); |
| 280 | } |
| 281 | try stream.write(tree.slice(short.short)); |
| 282 | if (short.int) |i| { |
| 283 | try stream.writeByte(' '); |
| 284 | try stream.write(tree.slice(i)); |
| 285 | } |
| 286 | }, |
| 287 | .Int => |int| { |
| 288 | if (int.sign) |s| { |
| 289 | try stream.write(tree.slice(s)); |
| 290 | try stream.writeByte(' '); |
| 291 | } |
| 292 | if (int.int) |i| { |
| 293 | try stream.writeByte(' '); |
| 294 | try stream.write(tree.slice(i)); |
| 295 | } |
| 296 | }, |
| 297 | .Long => |long| { |
| 298 | if (long.sign) |s| { |
| 299 | try stream.write(tree.slice(s)); |
| 300 | try stream.writeByte(' '); |
| 301 | } |
| 302 | try stream.write(tree.slice(long.long)); |
| 303 | if (long.longlong) |l| { |
| 304 | try stream.writeByte(' '); |
| 305 | try stream.write(tree.slice(l)); |
| 306 | } |
| 307 | if (long.int) |i| { |
| 308 | try stream.writeByte(' '); |
| 309 | try stream.write(tree.slice(i)); |
| 310 | } |
| 311 | }, |
| 312 | .Float => |float| { |
| 313 | try stream.write(tree.slice(float.float)); |
| 314 | if (float.complex) |c| { |
| 315 | try stream.writeByte(' '); |
| 316 | try stream.write(tree.slice(c)); |
| 317 | } |
| 318 | }, |
| 319 | .Double => |double| { |
| 320 | if (double.long) |l| { |
| 321 | try stream.write(tree.slice(l)); |
| 322 | try stream.writeByte(' '); |
| 323 | } |
| 324 | try stream.write(tree.slice(double.double)); |
| 325 | if (double.complex) |c| { |
| 326 | try stream.writeByte(' '); |
| 327 | try stream.write(tree.slice(c)); |
| 328 | } |
| 329 | }, |
| 330 | .Bool => |index| try stream.write(tree.slice(index)), |
| 331 | .Typedef => |typedef| try stream.write(tree.slice(typedef.sym)), |
| 332 | else => try stream.print("TODO print {}", self.spec), |
| 219 | 333 | } |
| 220 | 334 | } |
| 221 | 335 | } = .None, |
| 222 | 336 | }; |
| 223 | 337 | |
| 338 | pub const EnumType = struct { |
| 339 | tok: TokenIndex, |
| 340 | name: ?TokenIndex, |
| 341 | body: ?struct { |
| 342 | lbrace: TokenIndex, |
| 343 | |
| 344 | /// always EnumField |
| 345 | fields: FieldList, |
| 346 | rbrace: TokenIndex, |
| 347 | }, |
| 348 | |
| 349 | pub const FieldList = Root.DeclList; |
| 350 | }; |
| 351 | |
| 352 | pub const EnumField = struct { |
| 353 | base: Node = Node{ .id = EnumField }, |
| 354 | name: TokenIndex, |
| 355 | value: ?*Node, |
| 356 | }; |
| 357 | |
| 358 | pub const RecordType = struct { |
| 359 | kind: union(enum) { |
| 360 | Struct: TokenIndex, |
| 361 | Union: TokenIndex, |
| 362 | }, |
| 363 | name: ?TokenIndex, |
| 364 | body: ?struct { |
| 365 | lbrace: TokenIndex, |
| 366 | |
| 367 | /// RecordField or StaticAssert |
| 368 | fields: FieldList, |
| 369 | rbrace: TokenIndex, |
| 370 | }, |
| 371 | |
| 372 | pub const FieldList = Root.DeclList; |
| 373 | }; |
| 374 | |
| 375 | pub const RecordField = struct { |
| 376 | base: Node = Node{ .id = RecordField }, |
| 377 | // TODO |
| 378 | }; |
| 379 | |
| 224 | 380 | pub const TypeQual = struct { |
| 225 | 381 | @"const": ?TokenIndex = null, |
| 226 | 382 | atomic: ?TokenIndex = null, |