Commit 3ed6d7d245
lib/std/c/ast.zig
@@ -41,6 +41,7 @@ pub const Error = union(enum) {
ExpectedStmt: SingleTokenError("expected statement, found '{}'"),
ExpectedTypeName: SingleTokenError("expected type name, found '{}'"),
ExpectedFnBody: SingleTokenError("expected function body, found '{}'"),
+ ExpectedDeclarator: SingleTokenError("expected declarator, found '{}'"),
ExpectedInitializer: SingleTokenError("expected initializer, found '{}'"),
InvalidTypeSpecifier: InvalidTypeSpecifier,
DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"),
@@ -55,6 +56,7 @@ pub const Error = union(enum) {
.ExpectedTypeName => |*x| return x.render(tokens, stream),
.ExpectedDeclarator => |*x| return x.render(tokens, stream),
.ExpectedFnBody => |*x| return x.render(tokens, stream),
+ .ExpectedInitializer => |*x| return x.render(tokens, stream),
.InvalidTypeSpecifier => |*x| return x.render(tokens, stream),
.DuplicateQualifier => |*x| return x.render(tokens, stream),
.DuplicateSpecifier => |*x| return x.render(tokens, stream),
@@ -70,6 +72,7 @@ pub const Error = union(enum) {
.ExpectedTypeName => |x| return x.token,
.ExpectedDeclarator => |x| return x.token,
.ExpectedFnBody => |x| return x.token,
+ .ExpectedInitializer => |x| return x.token,
.InvalidTypeSpecifier => |x| return x.token,
.DuplicateQualifier => |x| return x.token,
.DuplicateSpecifier => |x| return x.token,
@@ -277,30 +280,48 @@ pub const Node = struct {
};
pub const Declarator = struct {
+ base: Node = Node{ .id = .Declarator },
pointer: *Pointer,
- identifier: ?TokenIndex,
- kind: union(enum) {
- Simple,
+ prefix: union(enum) {
+ None,
+ Identifer: TokenIndex,
Complex: struct {
lparen: TokenIndex,
- inner: *Declarator,
+ inner: *Node,
rparen: TokenIndex,
},
- Fn: ParamList,
- Array: ArrayList,
+ },
+ suffix: union(enum) {
+ None,
+ Fn: struct {
+ lparen: TokenIndex,
+ params: Params,
+ rparen: TokenIndex,
+ },
+ Array: Arrays,
},
- pub const ArrayList = std.SegmentedList(*Array, 2);
- pub const ParamList = std.SegmentedList(*Param, 4);
+ pub const Arrays = std.SegmentedList(*Array, 2);
+ pub const Params = std.SegmentedList(*Param, 4);
};
- pub const Array = union(enum) {
- Unspecified,
- Variable: TokenIndex,
- Known: *Expr,
+ pub const Array = struct {
+ rbracket: TokenIndex,
+ inner: union(enum) {
+ Inferred,
+ Unspecified: TokenIndex,
+ Variable: struct {
+ asterisk: ?TokenIndex,
+ static: ?TokenIndex,
+ qual: TypeQual,
+ expr: *Expr,
+ },
+ },
+ rbracket: TokenIndex,
};
pub const Pointer = struct {
+ base: Node = Node{ .id = .Pointer },
asterisk: TokenIndex,
qual: TypeQual,
pointer: ?*Pointer,
@@ -312,7 +333,7 @@ pub const Node = struct {
Old: TokenIndex,
Normal: struct {
decl_spec: *DeclSpec,
- declarator: *Declarator,
+ declarator: *Node,
},
},
};
@@ -320,7 +341,7 @@ pub const Node = struct {
pub const Fn = struct {
base: Node = Node{ .id = .Fn },
decl_spec: DeclSpec,
- declarator: *Declarator,
+ declarator: *Node,
old_decls: OldDeclList,
body: ?*CompoundStmt,
@@ -332,7 +353,7 @@ pub const Node = struct {
decl_spec: DeclSpec,
declarators: DeclaratorList,
- pub const DeclaratorList = std.SegmentedList(*Declarator, 2);
+ pub const DeclaratorList = Root.DeclList;
};
pub const Var = struct {
@@ -344,7 +365,7 @@ pub const Node = struct {
};
pub const Initialized = struct {
- declarator: *Declarator,
+ declarator: *Node,
eq: TokenIndex,
init: Initializer,
};
lib/std/c/parse.zig
@@ -589,7 +589,7 @@ const Parser = struct {
fn recordDeclarator(parser: *Parser) !*Node {}
/// Pointer <- ASTERISK TypeQual* Pointer?
- fn pointer(parser: *Parser) !?*Node.Pointer {
+ fn pointer(parser: *Parser) Error!?*Node {
const asterisk = parser.eatToken(.Asterisk) orelse return null;
const node = try parser.arena.create(Node.Pointer);
node.* = .{
@@ -599,34 +599,129 @@ const Parser = struct {
};
while (try parser.typeQual(&node.qual)) {}
node.pointer = try parser.pointer();
- return node;
+ return &node.base;
}
- /// DirectDeclarator
- /// <- IDENTIFIER
+
+ const Named = enum {
+ Must,
+ Allowed,
+ Forbidden,
+ };
+
+ /// Declarator <- Pointer? DeclaratorSuffix
+ /// DeclaratorPrefix
+ /// <- IDENTIFIER // if named != .Forbidden
/// / LPAREN Declarator RPAREN
- /// / DirectDeclarator LBRACKET (ASTERISK / BracketDeclarator)? RBRACKET
- /// / DirectDeclarator LPAREN (ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?)? RPAREN
- fn directDeclarator(parser: *Parser) !*Node {}
+ /// / (none) // if named != .Must
+ /// DeclaratorSuffix
+ /// <. DeclaratorPrefix (LBRACKET ArrayDeclarator? RBRACKET)*
+ /// / DeclaratorPrefix LPAREN (ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?)? RPAREN
+ fn declarator(parser: *Parser, named: Named) Error!?*Node {
+ const ptr = try parser.pointer();
+ var node: *Node.Declarator = undefined;
+ // prefix
+ if (parser.eatToken(.LParen)) |lparen| {
+ const inner = (try parser.declarator(named)) orelse return parser.err(.{
+ .ExpectedDeclarator = .{ .token = lparen + 1 },
+ });
+ node = try parser.arena.create(Node.Declarator);
+ node.* = .{
+ .pointer = ptr,
+ .prefix = .{
+ .Comples = .{
+ .lparen = lparen,
+ .inner = inner,
+ .rparen = try parser.expectToken(.RParen),
+ },
+ },
+ .suffix = .None,
+ };
+ } else if (named != .Forbidden) {
+ if (parser.eatToken(.Identifier)) |tok| {
+ node = try parser.arena.create(Node.Declarator);
+ node.* = .{
+ .pointer = ptr,
+ .prefix = .{ .Simple = tok },
+ .suffix = .None,
+ };
+ } else if (named == .Must) {
+ return parser.err(.{
+ .ExpectedToken = .{ .token = parser.it.index, .expected_id = .Identifier },
+ });
+ } else {
+ return ptr;
+ }
+ } else {
+ node = try parser.arena.create(Node.Declarator);
+ node.* = .{
+ .pointer = ptr,
+ .prefix = .None,
+ .suffix = .None,
+ };
+ }
+ // suffix
+ if (parser.eatToken(.LParen)) |lparen| {
+ node.suffix = .{
+ .Fn = .{
+ .lparen = lparen,
+ .params = .Node.Declarator.Params.init(parser.arena),
+ .rparen = undefined,
+ },
+ };
+ try parser.ParamDecl(node);
+ node.suffix.Fn.rparen = try parser.expectToken(.RParen);
+ } else {
+ while (parser.arrayDeclarator()) |arr| {
+ if (node.suffix == .None)
+ node.suffix = .{ .Array = .Node.Declarator.Arrays.init(parser.arena) };
+ try node.suffix.Array.push(arr);
+ }
+ }
+ if (parser.eatToken(.LParen) orelse parser.eatToken(.LBracket)) |tok|
+ return parser.err(.{
+ .InvalidDeclarator = .{ .token = tok },
+ });
+ return node;
+ }
- /// BracketDeclarator
- /// <- Keyword_static TypeQual* AssignmentExpr
+ /// ArrayDeclarator
+ /// <- ASTERISK
+ /// / Keyword_static TypeQual* AssignmentExpr
/// / TypeQual+ (ASTERISK / Keyword_static AssignmentExpr)
/// / TypeQual+ AssignmentExpr?
/// / AssignmentExpr
- fn bracketDeclarator(parser: *Parser) !*Node {}
+ fn arrayDeclarator(parser: *Parser, dr: *Node.Declarator) !?*Node.Array {
+ const lbracket = parser.eatToken(.LBracket) orelse return null;
+ const arr = try parser.arena.create(Node.Array);
+ arr.* = .{
+ .lbracket = lbarcket,
+ .inner = .Inferred,
+ .rbracket = undefined,
+ };
+ if (parser.eatToken(.Asterisk)) |tok| {
+ arr.inner = .{ .Unspecified = tok };
+ } else {
+ // TODO
+ }
+ arr.rbracket = try parser.expectToken(.RBracket);
+ return arr;
+ }
+ /// Params <- ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?
/// ParamDecl <- DeclSpec (Declarator / AbstractDeclarator)
- fn paramDecl(parser: *Parser) !*Node {}
-
- /// AbstractDeclarator <- Pointer? DirectAbstractDeclarator?
- fn abstractDeclarator(parser: *Parser) !*Node {}
-
- /// DirectAbstractDeclarator
- /// <- IDENTIFIER
- /// / LPAREN DirectAbstractDeclarator RPAREN
- /// / DirectAbstractDeclarator? LBRACKET (ASTERISK / BracketDeclarator)? RBRACKET
- /// / DirectAbstractDeclarator? LPAREN (ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?)? RPAREN
- fn directAbstractDeclarator(parser: *Parser) !*Node {}
+ fn paramDecl(parser: *Parser, dr: *Node.Declarator) !void {
+ var old_style = false;
+ while (true) {
+ var ds = Node.DeclSpec;
+ if (try parser.declSpec(&ds)) {
+ //TODO
+ } else if (parser.eatToken(.Identifier)) {
+ old_style = true;
+ } else if (parser.eatToken(.Ellipsis)) {
+ // TODO
+ }
+ }
+ }
/// Expr <- AssignmentExpr (COMMA Expr)*
fn expr(parser: *Parser) !*Node {}