| ... | @@ -23,6 +23,11 @@ pub const Tree = struct { | ... | @@ -23,6 +23,11 @@ pub const Tree = struct { |
| 23 | arena_allocator.deinit(); | 23 | arena_allocator.deinit(); |
| 24 | // self is destroyed | 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 | pub const Msg = struct { | 33 | pub const Msg = struct { |
| ... | @@ -47,19 +52,19 @@ pub const Error = union(enum) { | ... | @@ -47,19 +52,19 @@ pub const Error = union(enum) { |
| 47 | DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"), | 52 | DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"), |
| 48 | DuplicateSpecifier: SingleTokenError("duplicate declaration specifier '{}'"), | 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 | switch (self.*) { | 56 | switch (self.*) { |
| 52 | .InvalidToken => |*x| return x.render(tokens, stream), | 57 | .InvalidToken => |*x| return x.render(tree, stream), |
| 53 | .ExpectedToken => |*x| return x.render(tokens, stream), | 58 | .ExpectedToken => |*x| return x.render(tree, stream), |
| 54 | .ExpectedExpr => |*x| return x.render(tokens, stream), | 59 | .ExpectedExpr => |*x| return x.render(tree, stream), |
| 55 | .ExpectedStmt => |*x| return x.render(tokens, stream), | 60 | .ExpectedStmt => |*x| return x.render(tree, stream), |
| 56 | .ExpectedTypeName => |*x| return x.render(tokens, stream), | 61 | .ExpectedTypeName => |*x| return x.render(tree, stream), |
| 57 | .ExpectedDeclarator => |*x| return x.render(tokens, stream), | 62 | .ExpectedDeclarator => |*x| return x.render(tree, stream), |
| 58 | .ExpectedFnBody => |*x| return x.render(tokens, stream), | 63 | .ExpectedFnBody => |*x| return x.render(tree, stream), |
| 59 | .ExpectedInitializer => |*x| return x.render(tokens, stream), | 64 | .ExpectedInitializer => |*x| return x.render(tree, stream), |
| 60 | .InvalidTypeSpecifier => |*x| return x.render(tokens, stream), | 65 | .InvalidTypeSpecifier => |*x| return x.render(tree, stream), |
| 61 | .DuplicateQualifier => |*x| return x.render(tokens, stream), | 66 | .DuplicateQualifier => |*x| return x.render(tree, stream), |
| 62 | .DuplicateSpecifier => |*x| return x.render(tokens, 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,8 +88,8 @@ pub const Error = union(enum) { |
| 83 | token: TokenIndex, | 88 | token: TokenIndex, |
| 84 | expected_id: @TagType(Token.Id), | 89 | expected_id: @TagType(Token.Id), |
| 85 | | 90 | |
| 86 | pub fn render(self: *const ExpectedToken, tokens: *Tree.TokenList, stream: var) !void { | 91 | pub fn render(self: *const ExpectedToken, tree: *Tree, stream: var) !void { |
| 87 | const found_token = tokens.at(self.token); | 92 | const found_token = tree.tokens.at(self.token); |
| 88 | if (found_token.id == .Invalid) { | 93 | if (found_token.id == .Invalid) { |
| 89 | return stream.print("expected '{}', found invalid bytes", .{self.expected_id.symbol()}); | 94 | return stream.print("expected '{}', found invalid bytes", .{self.expected_id.symbol()}); |
| 90 | } else { | 95 | } else { |
| ... | @@ -98,10 +103,10 @@ pub const Error = union(enum) { | ... | @@ -98,10 +103,10 @@ pub const Error = union(enum) { |
| 98 | token: TokenIndex, | 103 | token: TokenIndex, |
| 99 | type_spec: *Node.TypeSpec, | 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 | try stream.write("invalid type specifier '"); | 107 | try stream.write("invalid type specifier '"); |
| 103 | try type_spec.spec.print(tokens, stream); | 108 | try type_spec.spec.print(tree, stream); |
| 104 | const token_name = tokens.at(self.token).id.symbol(); | 109 | const token_name = tree.tokens.at(self.token).id.symbol(); |
| 105 | return stream.print("{}'", .{token_name}); | 110 | return stream.print("{}'", .{token_name}); |
| 106 | } | 111 | } |
| 107 | }; | 112 | }; |
| ... | @@ -110,14 +115,59 @@ pub const Error = union(enum) { | ... | @@ -110,14 +115,59 @@ pub const Error = union(enum) { |
| 110 | return struct { | 115 | return struct { |
| 111 | token: TokenIndex, | 116 | token: TokenIndex, |
| 112 | | 117 | |
| 113 | pub fn render(self: *const @This(), tokens: *Tree.TokenList, stream: var) !void { | 118 | pub fn render(self: *const @This(), tree: *Tree, stream: var) !void { |
| 114 | const actual_token = tokens.at(self.token); | 119 | const actual_token = tree.tokens.at(self.token); |
| 115 | return stream.print(msg, .{actual_token.id.symbol()}); | 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 | pub const Node = struct { | 171 | pub const Node = struct { |
| 122 | id: Id, | 172 | id: Id, |
| 123 | | 173 | |
| ... | @@ -205,22 +255,128 @@ pub const Node = struct { | ... | @@ -205,22 +255,128 @@ pub const Node = struct { |
| 205 | typename: *Node, | 255 | typename: *Node, |
| 206 | rparen: TokenIndex, | 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 | 265 | pub fn print(self: *@This(), self: *const @This(), tree: *Tree, stream: var) !void { |
| 210 | // @"enum", | 266 | switch (self.spec) { |
| 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) { | | |
| 217 | .None => unreachable, | 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 | } = .None, | 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 | pub const TypeQual = struct { | 380 | pub const TypeQual = struct { |
| 225 | @"const": ?TokenIndex = null, | 381 | @"const": ?TokenIndex = null, |
| 226 | atomic: ?TokenIndex = null, | 382 | atomic: ?TokenIndex = null, |