| author | |
| committer | |
| log | 4184d4c66a26ba10fbc78cc21f2c73db8f0cfcb2 |
| tree | ce96a5cbe63f8bd86ab1cfeb3892e1fea44005d0 |
| parent | df12c1328eb9c2af006dfd9e5cf69046ad6fc235 |
| signature |
2 files changed, 151 insertions(+), 31 deletions(-)
lib/std/c/ast.zig+36-16| ... | @@ -48,9 +48,12 @@ pub const Error = union(enum) { | ... | @@ -48,9 +48,12 @@ pub const Error = union(enum) { |
| 48 | ExpectedFnBody: SingleTokenError("expected function body, found '{}'"), | 48 | ExpectedFnBody: SingleTokenError("expected function body, found '{}'"), |
| 49 | ExpectedDeclarator: SingleTokenError("expected declarator, found '{}'"), | 49 | ExpectedDeclarator: SingleTokenError("expected declarator, found '{}'"), |
| 50 | ExpectedInitializer: SingleTokenError("expected initializer, found '{}'"), | 50 | ExpectedInitializer: SingleTokenError("expected initializer, found '{}'"), |
| 51 | ExpectedEnumField: SingleTokenError("expected enum field, found '{}'"), | ||
| 52 | ExpectedType: SingleTokenError("expected enum field, found '{}'"), | ||
| 51 | InvalidTypeSpecifier: InvalidTypeSpecifier, | 53 | InvalidTypeSpecifier: InvalidTypeSpecifier, |
| 52 | DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"), | 54 | DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"), |
| 53 | DuplicateSpecifier: SingleTokenError("duplicate declaration specifier '{}'"), | 55 | DuplicateSpecifier: SingleTokenError("duplicate declaration specifier '{}'"), |
| 56 | MustUseKwToRefer: MustUseKwToRefer, | ||
| 54 | 57 | ||
| 55 | pub fn render(self: *const Error, tree: *Tree, stream: var) !void { | 58 | pub fn render(self: *const Error, tree: *Tree, stream: var) !void { |
| 56 | switch (self.*) { | 59 | switch (self.*) { |
| ... | @@ -62,9 +65,12 @@ pub const Error = union(enum) { | ... | @@ -62,9 +65,12 @@ pub const Error = union(enum) { |
| 62 | .ExpectedDeclarator => |*x| return x.render(tree, stream), | 65 | .ExpectedDeclarator => |*x| return x.render(tree, stream), |
| 63 | .ExpectedFnBody => |*x| return x.render(tree, stream), | 66 | .ExpectedFnBody => |*x| return x.render(tree, stream), |
| 64 | .ExpectedInitializer => |*x| return x.render(tree, stream), | 67 | .ExpectedInitializer => |*x| return x.render(tree, stream), |
| 68 | .ExpectedEnumField => |*x| return x.render(tree, stream), | ||
| 69 | .ExpectedType => |*x| return x.render(tree, stream), | ||
| 65 | .InvalidTypeSpecifier => |*x| return x.render(tree, stream), | 70 | .InvalidTypeSpecifier => |*x| return x.render(tree, stream), |
| 66 | .DuplicateQualifier => |*x| return x.render(tree, stream), | 71 | .DuplicateQualifier => |*x| return x.render(tree, stream), |
| 67 | .DuplicateSpecifier => |*x| return x.render(tree, stream), | 72 | .DuplicateSpecifier => |*x| return x.render(tree, stream), |
| 73 | .MustUseKwToRefer => |*x| return x.render(tree, stream), | ||
| 68 | } | 74 | } |
| 69 | } | 75 | } |
| 70 | 76 | ||
| ... | @@ -78,9 +84,12 @@ pub const Error = union(enum) { | ... | @@ -78,9 +84,12 @@ pub const Error = union(enum) { |
| 78 | .ExpectedDeclarator => |x| return x.token, | 84 | .ExpectedDeclarator => |x| return x.token, |
| 79 | .ExpectedFnBody => |x| return x.token, | 85 | .ExpectedFnBody => |x| return x.token, |
| 80 | .ExpectedInitializer => |x| return x.token, | 86 | .ExpectedInitializer => |x| return x.token, |
| 87 | .ExpectedEnumField => |x| return x.token, | ||
| 88 | .ExpectedType => |*x| return x.token, | ||
| 81 | .InvalidTypeSpecifier => |x| return x.token, | 89 | .InvalidTypeSpecifier => |x| return x.token, |
| 82 | .DuplicateQualifier => |x| return x.token, | 90 | .DuplicateQualifier => |x| return x.token, |
| 83 | .DuplicateSpecifier => |x| return x.token, | 91 | .DuplicateSpecifier => |x| return x.token, |
| 92 | .MustUseKwToRefer => |*x| return x.name, | ||
| 84 | } | 93 | } |
| 85 | } | 94 | } |
| 86 | 95 | ||
| ... | @@ -111,6 +120,15 @@ pub const Error = union(enum) { | ... | @@ -111,6 +120,15 @@ pub const Error = union(enum) { |
| 111 | } | 120 | } |
| 112 | }; | 121 | }; |
| 113 | 122 | ||
| 123 | pub const MustUseKwToRefer = struct { | ||
| 124 | kw: TokenIndex, | ||
| 125 | name: TokenIndex, | ||
| 126 | |||
| 127 | pub fn render(self: *const ExpectedToken, tree: *Tree, stream: var) !void { | ||
| 128 | return stream.print("must use '{}' tag to refer to type '{}'", .{tree.slice(kw), tree.slice(name)}); | ||
| 129 | } | ||
| 130 | }; | ||
| 131 | |||
| 114 | fn SingleTokenError(comptime msg: []const u8) type { | 132 | fn SingleTokenError(comptime msg: []const u8) type { |
| 115 | return struct { | 133 | return struct { |
| 116 | token: TokenIndex, | 134 | token: TokenIndex, |
| ... | @@ -125,14 +143,13 @@ pub const Error = union(enum) { | ... | @@ -125,14 +143,13 @@ pub const Error = union(enum) { |
| 125 | 143 | ||
| 126 | pub const Type = struct { | 144 | pub const Type = struct { |
| 127 | pub const TypeList = std.SegmentedList(*Type, 4); | 145 | pub const TypeList = std.SegmentedList(*Type, 4); |
| 128 | @"const": bool, | 146 | @"const": bool = false, |
| 129 | atomic: bool, | 147 | atomic: bool = false, |
| 130 | @"volatile": bool, | 148 | @"volatile": bool = false, |
| 131 | restrict: bool, | 149 | restrict: bool = false, |
| 132 | 150 | ||
| 133 | id: union(enum) { | 151 | id: union(enum) { |
| 134 | Int: struct { | 152 | Int: struct { |
| 135 | quals: Qualifiers, | ||
| 136 | id: Id, | 153 | id: Id, |
| 137 | is_signed: bool, | 154 | is_signed: bool, |
| 138 | 155 | ||
| ... | @@ -145,7 +162,6 @@ pub const Type = struct { | ... | @@ -145,7 +162,6 @@ pub const Type = struct { |
| 145 | }; | 162 | }; |
| 146 | }, | 163 | }, |
| 147 | Float: struct { | 164 | Float: struct { |
| 148 | quals: Qualifiers, | ||
| 149 | id: Id, | 165 | id: Id, |
| 150 | 166 | ||
| 151 | pub const Id = enum { | 167 | pub const Id = enum { |
| ... | @@ -154,10 +170,7 @@ pub const Type = struct { | ... | @@ -154,10 +170,7 @@ pub const Type = struct { |
| 154 | LongDouble, | 170 | LongDouble, |
| 155 | }; | 171 | }; |
| 156 | }, | 172 | }, |
| 157 | Pointer: struct { | 173 | Pointer: *Type, |
| 158 | quals: Qualifiers, | ||
| 159 | child_type: *Type, | ||
| 160 | }, | ||
| 161 | Function: struct { | 174 | Function: struct { |
| 162 | return_type: *Type, | 175 | return_type: *Type, |
| 163 | param_types: TypeList, | 176 | param_types: TypeList, |
| ... | @@ -173,6 +186,8 @@ pub const Node = struct { | ... | @@ -173,6 +186,8 @@ pub const Node = struct { |
| 173 | 186 | ||
| 174 | pub const Id = enum { | 187 | pub const Id = enum { |
| 175 | Root, | 188 | Root, |
| 189 | EnumField, | ||
| 190 | RecordField, | ||
| 176 | JumpStmt, | 191 | JumpStmt, |
| 177 | ExprStmt, | 192 | ExprStmt, |
| 178 | Label, | 193 | Label, |
| ... | @@ -350,15 +365,16 @@ pub const Node = struct { | ... | @@ -350,15 +365,16 @@ pub const Node = struct { |
| 350 | }; | 365 | }; |
| 351 | 366 | ||
| 352 | pub const EnumField = struct { | 367 | pub const EnumField = struct { |
| 353 | base: Node = Node{ .id = EnumField }, | 368 | base: Node = Node{ .id = .EnumField }, |
| 354 | name: TokenIndex, | 369 | name: TokenIndex, |
| 355 | value: ?*Node, | 370 | value: ?*Node, |
| 356 | }; | 371 | }; |
| 357 | 372 | ||
| 358 | pub const RecordType = struct { | 373 | pub const RecordType = struct { |
| 359 | kind: union(enum) { | 374 | tok: TokenIndex, |
| 360 | Struct: TokenIndex, | 375 | kind: enum { |
| 361 | Union: TokenIndex, | 376 | Struct, |
| 377 | Union, | ||
| 362 | }, | 378 | }, |
| 363 | name: ?TokenIndex, | 379 | name: ?TokenIndex, |
| 364 | body: ?struct { | 380 | body: ?struct { |
| ... | @@ -373,8 +389,12 @@ pub const Node = struct { | ... | @@ -373,8 +389,12 @@ pub const Node = struct { |
| 373 | }; | 389 | }; |
| 374 | 390 | ||
| 375 | pub const RecordField = struct { | 391 | pub const RecordField = struct { |
| 376 | base: Node = Node{ .id = RecordField }, | 392 | base: Node = Node{ .id = .RecordField }, |
| 377 | // TODO | 393 | type_spec: TypeSpec, |
| 394 | declarators: DeclaratorList, | ||
| 395 | semicolon: TokenIndex, | ||
| 396 | |||
| 397 | pub const DeclaratorList = Root.DeclList; | ||
| 378 | }; | 398 | }; |
| 379 | 399 | ||
| 380 | pub const TypeQual = struct { | 400 | pub const TypeQual = struct { |
lib/std/c/parse.zig+115-15| ... | @@ -94,12 +94,11 @@ const Parser = struct { | ... | @@ -94,12 +94,11 @@ const Parser = struct { |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | fn getSymbol(parser: *Parser, tok: TokenIndex) ?*Type { | 96 | fn getSymbol(parser: *Parser, tok: TokenIndex) ?*Type { |
| 97 | const token = parser.it.list.at(tok); | 97 | const name = parser.tree.slice(tok); |
| 98 | const name = parser.tree.slice(token); | ||
| 99 | const syms = parser.symbols.toSliceConst(); | 98 | const syms = parser.symbols.toSliceConst(); |
| 100 | var i = syms.len; | 99 | var i = syms.len; |
| 101 | while (i > 0) : (i -= 1) { | 100 | while (i > 0) : (i -= 1) { |
| 102 | if (mem.eql(u8, name, syms[i].name)) { | 101 | if (std.mem.eql(u8, name, syms[i].name)) { |
| 103 | return syms[i].ty; | 102 | return syms[i].ty; |
| 104 | } | 103 | } |
| 105 | } | 104 | } |
| ... | @@ -492,31 +491,29 @@ const Parser = struct { | ... | @@ -492,31 +491,29 @@ const Parser = struct { |
| 492 | } else if (parser.eatToken(.Keyword_enum)) |tok| { | 491 | } else if (parser.eatToken(.Keyword_enum)) |tok| { |
| 493 | if (type_spec.spec != .None) | 492 | if (type_spec.spec != .None) |
| 494 | break :blk; | 493 | break :blk; |
| 495 | type_spec.Enum = try parser.enumSpec(tok); | 494 | type_spec.spec.Enum = try parser.enumSpec(tok); |
| 496 | return true; | 495 | return true; |
| 497 | } else if (parser.eatToken(.Keyword_union) orelse parser.eatToken(.Keyword_struct)) |tok| { | 496 | } else if (parser.eatToken(.Keyword_union) orelse parser.eatToken(.Keyword_struct)) |tok| { |
| 498 | if (type_spec.spec != .None) | 497 | if (type_spec.spec != .None) |
| 499 | break :blk; | 498 | break :blk; |
| 500 | type_spec.Record = try parser.recordSpec(); | 499 | type_spec.spec.Record = try parser.recordSpec(tok); |
| 501 | return true; | 500 | return true; |
| 502 | } else if (parser.eatToken(.Identifier)) |tok| { | 501 | } else if (parser.eatToken(.Identifier)) |tok| { |
| 503 | const ty = parser.getSymbol(tok) orelse { | 502 | const ty = parser.getSymbol(tok) orelse { |
| 504 | parser.putBackToken(tok); | 503 | parser.putBackToken(tok); |
| 505 | return false; | 504 | return false; |
| 506 | }; | 505 | }; |
| 507 | switch (ty) { | 506 | switch (ty.id) { |
| 508 | .Enum => |e| { | 507 | .Enum => |e| { |
| 509 | return parser.err(.{ | 508 | return parser.err(.{ |
| 510 | .MustUseKwToRefer = .{ .kw = e.identifier, .sym = tok }, | 509 | .MustUseKwToRefer = .{ .kw = e.tok, .name = tok }, |
| 511 | }); | 510 | }); |
| 512 | }, | 511 | }, |
| 513 | .Record => |r| { | 512 | .Record => |r| { |
| 514 | return parser.err(.{ | 513 | return parser.err(.{ |
| 515 | .MustUseKwToRefer = .{ | 514 | .MustUseKwToRefer = .{ |
| 516 | .kw = switch (r.kind) { | 515 | .kw = r.tok, |
| 517 | .Struct, .Union => |kw| kw, | 516 | .name = tok, |
| 518 | }, | ||
| 519 | .sym = tok, | ||
| 520 | }, | 517 | }, |
| 521 | }); | 518 | }); |
| 522 | }, | 519 | }, |
| ... | @@ -613,18 +610,121 @@ const Parser = struct { | ... | @@ -613,18 +610,121 @@ const Parser = struct { |
| 613 | } | 610 | } |
| 614 | 611 | ||
| 615 | /// EnumSpec <- Keyword_enum IDENTIFIER? (LBRACE EnumField RBRACE)? | 612 | /// EnumSpec <- Keyword_enum IDENTIFIER? (LBRACE EnumField RBRACE)? |
| 616 | fn enumSpecifier(parser: *Parser) !*Node {} | 613 | fn enumSpec(parser: *Parser, tok: TokenIndex) !*Node.EnumType { |
| 614 | const node = try parser.arena.create(Node.EnumType); | ||
| 615 | const name = parser.eatToken(.Identifier); | ||
| 616 | node.* = .{ | ||
| 617 | .tok = tok, | ||
| 618 | .name = name, | ||
| 619 | .body = null, | ||
| 620 | }; | ||
| 621 | const ty = try parser.arena.create(Type); | ||
| 622 | ty.* = .{ | ||
| 623 | .id = .{ | ||
| 624 | .Enum = node, | ||
| 625 | }, | ||
| 626 | }; | ||
| 627 | if (name) |some| | ||
| 628 | try parser.symbols.append(.{ | ||
| 629 | .name = parser.tree.slice(some), | ||
| 630 | .ty = ty, | ||
| 631 | }); | ||
| 632 | if (parser.eatToken(.LBrace)) |lbrace| { | ||
| 633 | var fields = Node.EnumType.FieldList.init(parser.arena); | ||
| 634 | try fields.push((try parser.enumField()) orelse return parser.err(.{ | ||
| 635 | .ExpectedEnumField = .{ .token = parser.it.index }, | ||
| 636 | })); | ||
| 637 | while (parser.eatToken(.Comma)) |_| { | ||
| 638 | try fields.push((try parser.enumField()) orelse break); | ||
| 639 | } | ||
| 640 | node.body = .{ | ||
| 641 | .lbrace = lbrace, | ||
| 642 | .fields = fields, | ||
| 643 | .rbrace = try parser.expectToken(.RBrace), | ||
| 644 | }; | ||
| 645 | } | ||
| 646 | return node; | ||
| 647 | } | ||
| 617 | 648 | ||
| 618 | /// EnumField <- IDENTIFIER (EQUAL ConstExpr)? (COMMA EnumField) COMMA? | 649 | /// EnumField <- IDENTIFIER (EQUAL ConstExpr)? (COMMA EnumField) COMMA? |
| 619 | fn enumField(parser: *Parser) !*Node {} | 650 | fn enumField(parser: *Parser) !?*Node { |
| 651 | const name = parser.eatToken(.Identifier) orelse return null; | ||
| 652 | const node = try parser.arena.create(Node.EnumField); | ||
| 653 | node.* = .{ | ||
| 654 | .name = name, | ||
| 655 | .value = null, | ||
| 656 | }; | ||
| 657 | if (parser.eatToken(.Equal)) |eq| { | ||
| 658 | node.value = try parser.constExpr(); | ||
| 659 | } | ||
| 660 | return &node.base; | ||
| 661 | } | ||
| 620 | 662 | ||
| 621 | /// RecordSpec <- (Keyword_struct / Keyword_union) IDENTIFIER? (LBRACE RecordField+ RBRACE)? | 663 | /// RecordSpec <- (Keyword_struct / Keyword_union) IDENTIFIER? (LBRACE RecordField+ RBRACE)? |
| 622 | fn recordSpecifier(parser: *Parser) !*Node {} | 664 | fn recordSpec(parser: *Parser, tok: TokenIndex) !*Node.RecordType { |
| 665 | const node = try parser.arena.create(Node.RecordType); | ||
| 666 | const name = parser.eatToken(.Identifier); | ||
| 667 | const is_struct = parser.tree.slice(tok)[0] == 's'; | ||
| 668 | node.* = .{ | ||
| 669 | .tok = tok, | ||
| 670 | .kind = if (is_struct) .Struct else .Union, | ||
| 671 | .name = name, | ||
| 672 | .body = null, | ||
| 673 | }; | ||
| 674 | const ty = try parser.arena.create(Type); | ||
| 675 | ty.* = .{ | ||
| 676 | .id = .{ | ||
| 677 | .Record = node, | ||
| 678 | }, | ||
| 679 | }; | ||
| 680 | if (name) |some| | ||
| 681 | try parser.symbols.append(.{ | ||
| 682 | .name = parser.tree.slice(some), | ||
| 683 | .ty = ty, | ||
| 684 | }); | ||
| 685 | if (parser.eatToken(.LBrace)) |lbrace| { | ||
| 686 | var fields = Node.RecordType.FieldList.init(parser.arena); | ||
| 687 | while (true) { | ||
| 688 | if (parser.eatToken(.RBrace)) |rbrace| { | ||
| 689 | node.body = .{ | ||
| 690 | .lbrace = lbrace, | ||
| 691 | .fields = fields, | ||
| 692 | .rbrace = rbrace, | ||
| 693 | }; | ||
| 694 | break; | ||
| 695 | } | ||
| 696 | try fields.push(try parser.recordField()); | ||
| 697 | } | ||
| 698 | } | ||
| 699 | return node; | ||
| 700 | } | ||
| 623 | 701 | ||
| 624 | /// RecordField | 702 | /// RecordField |
| 625 | /// <- TypeSpec* (RecordDeclarator (COMMA RecordDeclarator))? SEMICOLON | 703 | /// <- TypeSpec* (RecordDeclarator (COMMA RecordDeclarator))? SEMICOLON |
| 626 | /// \ StaticAssert | 704 | /// \ StaticAssert |
| 627 | fn recordField(parser: *Parser) !*Node {} | 705 | fn recordField(parser: *Parser) Error!*Node { |
| 706 | if (try parser.staticAssert()) |decl| return decl; | ||
| 707 | var got = false; | ||
| 708 | var type_spec = Node.TypeSpec{}; | ||
| 709 | while (try parser.typeSpec(&type_spec)) got = true; | ||
| 710 | if (!got) | ||
| 711 | return parser.err(.{ | ||
| 712 | .ExpectedType = .{ .token = parser.it.index }, | ||
| 713 | }); | ||
| 714 | const node = try parser.arena.create(Node.RecordField); | ||
| 715 | node.* = .{ | ||
| 716 | .type_spec = type_spec, | ||
| 717 | .declarators = Node.RecordField.DeclaratorList.init(parser.arena), | ||
| 718 | .semicolon = undefined, | ||
| 719 | }; | ||
| 720 | while (true) { | ||
| 721 | try node.declarators.push(try parser.recordDeclarator()); | ||
| 722 | if (parser.eatToken(.Comma)) |_| {} else break; | ||
| 723 | } | ||
| 724 | |||
| 725 | node.semicolon = try parser.expectToken(.Semicolon); | ||
| 726 | return &node.base; | ||
| 727 | } | ||
| 628 | 728 | ||
| 629 | /// TypeName <- TypeSpec* AbstractDeclarator? | 729 | /// TypeName <- TypeSpec* AbstractDeclarator? |
| 630 | fn typeName(parser: *Parser) !*Node { | 730 | fn typeName(parser: *Parser) !*Node { |