std-c declaration parsing
This commit is contained in:
parent
4184d4c66a
commit
dbc0457068
@ -51,9 +51,14 @@ pub const Error = union(enum) {
|
|||||||
ExpectedEnumField: SingleTokenError("expected enum field, found '{}'"),
|
ExpectedEnumField: SingleTokenError("expected enum field, found '{}'"),
|
||||||
ExpectedType: SingleTokenError("expected enum field, found '{}'"),
|
ExpectedType: SingleTokenError("expected enum field, found '{}'"),
|
||||||
InvalidTypeSpecifier: InvalidTypeSpecifier,
|
InvalidTypeSpecifier: InvalidTypeSpecifier,
|
||||||
|
InvalidStorageClass: SingleTokenError("invalid storage class, found '{}'"),
|
||||||
|
InvalidDeclarator: SimpleError("invalid declarator"),
|
||||||
DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"),
|
DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"),
|
||||||
DuplicateSpecifier: SingleTokenError("duplicate declaration specifier '{}'"),
|
DuplicateSpecifier: SingleTokenError("duplicate declaration specifier '{}'"),
|
||||||
MustUseKwToRefer: MustUseKwToRefer,
|
MustUseKwToRefer: MustUseKwToRefer,
|
||||||
|
FnSpecOnNonFn: SingleTokenError("function specifier '{}' on non function"),
|
||||||
|
NothingDeclared: SimpleError("declaration doesn't declare anything"),
|
||||||
|
QualifierIgnored: SingleTokenError("qualifier '{}' ignored"),
|
||||||
|
|
||||||
pub fn render(self: *const Error, tree: *Tree, stream: var) !void {
|
pub fn render(self: *const Error, tree: *Tree, stream: var) !void {
|
||||||
switch (self.*) {
|
switch (self.*) {
|
||||||
@ -68,9 +73,14 @@ pub const Error = union(enum) {
|
|||||||
.ExpectedEnumField => |*x| return x.render(tree, stream),
|
.ExpectedEnumField => |*x| return x.render(tree, stream),
|
||||||
.ExpectedType => |*x| return x.render(tree, stream),
|
.ExpectedType => |*x| return x.render(tree, stream),
|
||||||
.InvalidTypeSpecifier => |*x| return x.render(tree, stream),
|
.InvalidTypeSpecifier => |*x| return x.render(tree, stream),
|
||||||
|
.InvalidStorageClass => |*x| return x.render(tree, stream),
|
||||||
|
.InvalidDeclarator => |*x| return x.render(tree, stream),
|
||||||
.DuplicateQualifier => |*x| return x.render(tree, stream),
|
.DuplicateQualifier => |*x| return x.render(tree, stream),
|
||||||
.DuplicateSpecifier => |*x| return x.render(tree, stream),
|
.DuplicateSpecifier => |*x| return x.render(tree, stream),
|
||||||
.MustUseKwToRefer => |*x| return x.render(tree, stream),
|
.MustUseKwToRefer => |*x| return x.render(tree, stream),
|
||||||
|
.FnSpecOnNonFn => |*x| return x.render(tree, stream),
|
||||||
|
.NothingDeclared => |*x| return x.render(tree, stream),
|
||||||
|
.QualifierIgnored => |*x| return x.render(tree, stream),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,9 +97,14 @@ pub const Error = union(enum) {
|
|||||||
.ExpectedEnumField => |x| return x.token,
|
.ExpectedEnumField => |x| return x.token,
|
||||||
.ExpectedType => |*x| return x.token,
|
.ExpectedType => |*x| return x.token,
|
||||||
.InvalidTypeSpecifier => |x| return x.token,
|
.InvalidTypeSpecifier => |x| return x.token,
|
||||||
|
.InvalidStorageClass => |x| return x.token,
|
||||||
|
.InvalidDeclarator => |x| return x.token,
|
||||||
.DuplicateQualifier => |x| return x.token,
|
.DuplicateQualifier => |x| return x.token,
|
||||||
.DuplicateSpecifier => |x| return x.token,
|
.DuplicateSpecifier => |x| return x.token,
|
||||||
.MustUseKwToRefer => |*x| return x.name,
|
.MustUseKwToRefer => |*x| return x.name,
|
||||||
|
.FnSpecOnNonFn => |*x| return x.name,
|
||||||
|
.NothingDeclared => |*x| return x.name,
|
||||||
|
.QualifierIgnored => |*x| return x.name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +140,7 @@ pub const Error = union(enum) {
|
|||||||
name: TokenIndex,
|
name: TokenIndex,
|
||||||
|
|
||||||
pub fn render(self: *const ExpectedToken, tree: *Tree, stream: var) !void {
|
pub fn render(self: *const ExpectedToken, tree: *Tree, stream: var) !void {
|
||||||
return stream.print("must use '{}' tag to refer to type '{}'", .{tree.slice(kw), tree.slice(name)});
|
return stream.print("must use '{}' tag to refer to type '{}'", .{ tree.slice(kw), tree.slice(name) });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -139,6 +154,18 @@ pub const Error = union(enum) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn SimpleError(comptime msg: []const u8) type {
|
||||||
|
return struct {
|
||||||
|
const ThisError = @This();
|
||||||
|
|
||||||
|
token: TokenIndex,
|
||||||
|
|
||||||
|
pub fn render(self: *const ThisError, tokens: *Tree.TokenList, stream: var) !void {
|
||||||
|
return stream.write(msg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Type = struct {
|
pub const Type = struct {
|
||||||
@ -194,9 +221,11 @@ pub const Node = struct {
|
|||||||
CompoundStmt,
|
CompoundStmt,
|
||||||
IfStmt,
|
IfStmt,
|
||||||
StaticAssert,
|
StaticAssert,
|
||||||
Fn,
|
Declarator,
|
||||||
|
Pointer,
|
||||||
|
FnDecl,
|
||||||
Typedef,
|
Typedef,
|
||||||
Var,
|
VarDecl,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Root = struct {
|
pub const Root = struct {
|
||||||
@ -457,7 +486,7 @@ pub const Node = struct {
|
|||||||
|
|
||||||
pub const Declarator = struct {
|
pub const Declarator = struct {
|
||||||
base: Node = Node{ .id = .Declarator },
|
base: Node = Node{ .id = .Declarator },
|
||||||
pointer: *Pointer,
|
pointer: ?*Pointer,
|
||||||
prefix: union(enum) {
|
prefix: union(enum) {
|
||||||
None,
|
None,
|
||||||
Identifer: TokenIndex,
|
Identifer: TokenIndex,
|
||||||
@ -482,7 +511,7 @@ pub const Node = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const Array = struct {
|
pub const Array = struct {
|
||||||
rbracket: TokenIndex,
|
lbracket: TokenIndex,
|
||||||
inner: union(enum) {
|
inner: union(enum) {
|
||||||
Inferred,
|
Inferred,
|
||||||
Unspecified: TokenIndex,
|
Unspecified: TokenIndex,
|
||||||
@ -490,7 +519,7 @@ pub const Node = struct {
|
|||||||
asterisk: ?TokenIndex,
|
asterisk: ?TokenIndex,
|
||||||
static: ?TokenIndex,
|
static: ?TokenIndex,
|
||||||
qual: TypeQual,
|
qual: TypeQual,
|
||||||
expr: *Expr,
|
// expr: *Expr,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
rbracket: TokenIndex,
|
rbracket: TokenIndex,
|
||||||
@ -514,10 +543,10 @@ pub const Node = struct {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Fn = struct {
|
pub const FnDecl = struct {
|
||||||
base: Node = Node{ .id = .Fn },
|
base: Node = Node{ .id = .FnDecl },
|
||||||
decl_spec: DeclSpec,
|
decl_spec: DeclSpec,
|
||||||
declarator: *Node,
|
declarator: *Declarator,
|
||||||
old_decls: OldDeclList,
|
old_decls: OldDeclList,
|
||||||
body: ?*CompoundStmt,
|
body: ?*CompoundStmt,
|
||||||
|
|
||||||
@ -528,20 +557,23 @@ pub const Node = struct {
|
|||||||
base: Node = Node{ .id = .Typedef },
|
base: Node = Node{ .id = .Typedef },
|
||||||
decl_spec: DeclSpec,
|
decl_spec: DeclSpec,
|
||||||
declarators: DeclaratorList,
|
declarators: DeclaratorList,
|
||||||
|
semicolon: TokenIndex,
|
||||||
|
|
||||||
pub const DeclaratorList = Root.DeclList;
|
pub const DeclaratorList = Root.DeclList;
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Var = struct {
|
pub const VarDecl = struct {
|
||||||
base: Node = Node{ .id = .Var },
|
base: Node = Node{ .id = .VarDecl },
|
||||||
decl_spec: DeclSpec,
|
decl_spec: DeclSpec,
|
||||||
initializers: Initializers,
|
initializers: Initializers,
|
||||||
|
semicolon: TokenIndex,
|
||||||
|
|
||||||
pub const Initializers = std.SegmentedList(*Initialized, 2);
|
pub const Initializers = Root.DeclList;
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Initialized = struct {
|
pub const Initialized = struct {
|
||||||
declarator: *Node,
|
base: Node = Node{ .id = Initialized },
|
||||||
|
declarator: *Declarator,
|
||||||
eq: TokenIndex,
|
eq: TokenIndex,
|
||||||
init: Initializer,
|
init: Initializer,
|
||||||
};
|
};
|
||||||
|
@ -105,6 +105,10 @@ const Parser = struct {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn declareSymbol(parser: *Parser, decl_spec: *Node.DeclSpec, dr: *Node.Declarator) Error!void {
|
||||||
|
return; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
/// Root <- ExternalDeclaration* eof
|
/// Root <- ExternalDeclaration* eof
|
||||||
fn root(parser: *Parser) Allocator.Error!*Node.Root {
|
fn root(parser: *Parser) Allocator.Error!*Node.Root {
|
||||||
const node = try parser.arena.create(Node.Root);
|
const node = try parser.arena.create(Node.Root);
|
||||||
@ -140,75 +144,125 @@ const Parser = struct {
|
|||||||
|
|
||||||
fn declarationExtra(parser: *Parser, local: bool) !?*Node {
|
fn declarationExtra(parser: *Parser, local: bool) !?*Node {
|
||||||
if (try parser.staticAssert()) |decl| return decl;
|
if (try parser.staticAssert()) |decl| return decl;
|
||||||
|
const begin = parser.it.index + 1;
|
||||||
var ds = Node.DeclSpec{};
|
var ds = Node.DeclSpec{};
|
||||||
const got_ds = try parser.declSpec(&ds);
|
const got_ds = try parser.declSpec(&ds);
|
||||||
if (local and !got_ds) {
|
if (local and !got_ds) {
|
||||||
// not a declaration
|
// not a declaration
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
var dr = try parser.declarator();
|
switch (ds.storage_class) {
|
||||||
// TODO disallow auto and register
|
.Auto, .Register => |tok| return parser.err(.{
|
||||||
const next_tok = parser.it.peek().?;
|
.InvalidStorageClass = .{ .token = tok },
|
||||||
if (next_tok.id == .Eof and !got_ds and dr == null) {
|
}),
|
||||||
return null;
|
.Typedef => {
|
||||||
}
|
const node = try parser.arena.create(Node.Typedef);
|
||||||
switch (next_tok.id) {
|
|
||||||
.Semicolon,
|
|
||||||
.Equal,
|
|
||||||
.Comma,
|
|
||||||
.Eof,
|
|
||||||
=> {
|
|
||||||
while (dr != null) {
|
|
||||||
if (parser.eatToken(.Equal)) |tok| {
|
|
||||||
// TODO typedef
|
|
||||||
// dr.?.init = try parser.expect(initializer, .{
|
|
||||||
// .ExpectedInitializer = .{ .token = parser.it.index },
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
if (parser.eatToken(.Comma) != null) break;
|
|
||||||
dr = (try parser.declarator()) orelse return parser.err(.{
|
|
||||||
.ExpectedDeclarator = .{ .token = parser.it.index },
|
|
||||||
});
|
|
||||||
// .push(dr);
|
|
||||||
}
|
|
||||||
const semicolon = try parser.expectToken(.Semicolon);
|
|
||||||
|
|
||||||
// TODO VarDecl, TypeDecl, TypeDef
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
else => {
|
|
||||||
if (dr == null)
|
|
||||||
return parser.err(.{
|
|
||||||
.ExpectedDeclarator = .{ .token = parser.it.index },
|
|
||||||
});
|
|
||||||
var old_decls = Node.FnDef.OldDeclList.init(parser.arena);
|
|
||||||
while (true) {
|
|
||||||
var old_ds = Node.DeclSpec{};
|
|
||||||
if (!(try parser.declSpec(&old_ds))) {
|
|
||||||
// not old decl
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
var old_dr = (try parser.declarator());
|
|
||||||
// if (old_dr == null)
|
|
||||||
// try parser.err(.{
|
|
||||||
// .NoParamName = .{ .token = parser.it.index },
|
|
||||||
// });
|
|
||||||
// try old_decls.push(decl);
|
|
||||||
}
|
|
||||||
const body = (try parser.compoundStmt()) orelse return parser.err(.{
|
|
||||||
.ExpectedFnBody = .{ .token = parser.it.index },
|
|
||||||
});
|
|
||||||
|
|
||||||
const node = try parser.arena.create(Node.FnDef);
|
|
||||||
node.* = .{
|
node.* = .{
|
||||||
.decl_spec = ds,
|
.decl_spec = ds,
|
||||||
.declarator = dr orelse return null,
|
.declarators = Node.Typedef.DeclaratorList.init(parser.arena),
|
||||||
.old_decls = old_decls,
|
.semicolon = undefined,
|
||||||
.body = @fieldParentPtr(Node.CompoundStmt, "base", body),
|
|
||||||
};
|
};
|
||||||
|
while (true) {
|
||||||
|
const dr = @fieldParentPtr(Node.Declarator, "base", (try parser.declarator(.Must)) orelse return parser.err(.{
|
||||||
|
.ExpectedDeclarator = .{ .token = parser.it.index },
|
||||||
|
}));
|
||||||
|
try parser.declareSymbol(&ds, dr);
|
||||||
|
try node.declarators.push(&dr.base);
|
||||||
|
if (parser.eatToken(.Comma)) |_| {} else break;
|
||||||
|
}
|
||||||
return &node.base;
|
return &node.base;
|
||||||
},
|
},
|
||||||
|
else => {},
|
||||||
}
|
}
|
||||||
|
var first_dr = try parser.declarator(.Must);
|
||||||
|
if (first_dr != null and declaratorIsFunction(first_dr.?)) {
|
||||||
|
const dr = @fieldParentPtr(Node.Declarator, "base", first_dr.?);
|
||||||
|
try parser.declareSymbol(&ds, dr);
|
||||||
|
var old_decls = Node.FnDecl.OldDeclList.init(parser.arena);
|
||||||
|
const body = if (parser.eatToken(.Semicolon)) |_|
|
||||||
|
null
|
||||||
|
else blk: {
|
||||||
|
// TODO first_dr.is_old
|
||||||
|
// while (true) {
|
||||||
|
// var old_ds = Node.DeclSpec{};
|
||||||
|
// if (!(try parser.declSpec(&old_ds))) {
|
||||||
|
// // not old decl
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// var old_dr = (try parser.declarator(.Must));
|
||||||
|
// // if (old_dr == null)
|
||||||
|
// // try parser.err(.{
|
||||||
|
// // .NoParamName = .{ .token = parser.it.index },
|
||||||
|
// // });
|
||||||
|
// // try old_decls.push(decl);
|
||||||
|
// }
|
||||||
|
const body_node = (try parser.compoundStmt()) orelse return parser.err(.{
|
||||||
|
.ExpectedFnBody = .{ .token = parser.it.index },
|
||||||
|
});
|
||||||
|
break :blk @fieldParentPtr(Node.CompoundStmt, "base", body_node);
|
||||||
|
};
|
||||||
|
|
||||||
|
const node = try parser.arena.create(Node.FnDecl);
|
||||||
|
node.* = .{
|
||||||
|
.decl_spec = ds,
|
||||||
|
.declarator = dr,
|
||||||
|
.old_decls = old_decls,
|
||||||
|
.body = body,
|
||||||
|
};
|
||||||
|
return &node.base;
|
||||||
|
} else {
|
||||||
|
switch (ds.fn_spec) {
|
||||||
|
.Inline, .Noreturn => |tok| return parser.err(.{
|
||||||
|
.FnSpecOnNonFn = .{ .token = tok },
|
||||||
|
}),
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
// TODO threadlocal without static or extern on local variable
|
||||||
|
const node = try parser.arena.create(Node.VarDecl);
|
||||||
|
node.* = .{
|
||||||
|
.decl_spec = ds,
|
||||||
|
.initializers = Node.VarDecl.Initializers.init(parser.arena),
|
||||||
|
.semicolon = undefined,
|
||||||
|
};
|
||||||
|
if (first_dr == null) {
|
||||||
|
node.semicolon = try parser.expectToken(.Semicolon);
|
||||||
|
const ok = switch (ds.type_spec.spec) {
|
||||||
|
.Enum => |e| e.name != null,
|
||||||
|
.Record => |r| r.name != null,
|
||||||
|
else => false,
|
||||||
|
};
|
||||||
|
const q = ds.type_spec.qual;
|
||||||
|
if (!ok)
|
||||||
|
try parser.warn(.{
|
||||||
|
.NothingDeclared = .{ .token = begin },
|
||||||
|
})
|
||||||
|
else if (q.@"const" orelse q.atomic orelse q.@"volatile" orelse q.restrict) |tok|
|
||||||
|
try parser.warn(.{
|
||||||
|
.QualifierIgnored = .{ .token = tok },
|
||||||
|
});
|
||||||
|
return &node.base;
|
||||||
|
}
|
||||||
|
var dr = @fieldParentPtr(Node.Declarator, "base", first_dr.?);
|
||||||
|
while (true) {
|
||||||
|
try parser.declareSymbol(&ds, dr);
|
||||||
|
if (parser.eatToken(.Equal)) |tok| {
|
||||||
|
try node.initializers.push((try parser.initializer(dr)) orelse return parser.err(.{
|
||||||
|
.ExpectedInitializer = .{ .token = parser.it.index },
|
||||||
|
}));
|
||||||
|
} else
|
||||||
|
try node.initializers.push(&dr.base);
|
||||||
|
if (parser.eatToken(.Comma) != null) break;
|
||||||
|
dr = @fieldParentPtr(Node.Declarator, "base", (try parser.declarator(.Must)) orelse return parser.err(.{
|
||||||
|
.ExpectedDeclarator = .{ .token = parser.it.index },
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
node.semicolon = try parser.expectToken(.Semicolon);
|
||||||
|
return &node.base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn declaratorIsFunction(dr: *Node) bool {
|
||||||
|
return false; // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
/// StaticAssert <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON
|
/// StaticAssert <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON
|
||||||
@ -733,7 +787,7 @@ const Parser = struct {
|
|||||||
fn recordDeclarator(parser: *Parser) !*Node {}
|
fn recordDeclarator(parser: *Parser) !*Node {}
|
||||||
|
|
||||||
/// Pointer <- ASTERISK TypeQual* Pointer?
|
/// Pointer <- ASTERISK TypeQual* Pointer?
|
||||||
fn pointer(parser: *Parser) Error!?*Node {
|
fn pointer(parser: *Parser) Error!?*Node.Pointer {
|
||||||
const asterisk = parser.eatToken(.Asterisk) orelse return null;
|
const asterisk = parser.eatToken(.Asterisk) orelse return null;
|
||||||
const node = try parser.arena.create(Node.Pointer);
|
const node = try parser.arena.create(Node.Pointer);
|
||||||
node.* = .{
|
node.* = .{
|
||||||
@ -743,7 +797,7 @@ const Parser = struct {
|
|||||||
};
|
};
|
||||||
while (try parser.typeQual(&node.qual)) {}
|
while (try parser.typeQual(&node.qual)) {}
|
||||||
node.pointer = try parser.pointer();
|
node.pointer = try parser.pointer();
|
||||||
return &node.base;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Named = enum {
|
const Named = enum {
|
||||||
@ -772,7 +826,7 @@ const Parser = struct {
|
|||||||
node.* = .{
|
node.* = .{
|
||||||
.pointer = ptr,
|
.pointer = ptr,
|
||||||
.prefix = .{
|
.prefix = .{
|
||||||
.Comples = .{
|
.Complex = .{
|
||||||
.lparen = lparen,
|
.lparen = lparen,
|
||||||
.inner = inner,
|
.inner = inner,
|
||||||
.rparen = try parser.expectToken(.RParen),
|
.rparen = try parser.expectToken(.RParen),
|
||||||
@ -785,7 +839,7 @@ const Parser = struct {
|
|||||||
node = try parser.arena.create(Node.Declarator);
|
node = try parser.arena.create(Node.Declarator);
|
||||||
node.* = .{
|
node.* = .{
|
||||||
.pointer = ptr,
|
.pointer = ptr,
|
||||||
.prefix = .{ .Simple = tok },
|
.prefix = .{ .Identifer = tok },
|
||||||
.suffix = .None,
|
.suffix = .None,
|
||||||
};
|
};
|
||||||
} else if (named == .Must) {
|
} else if (named == .Must) {
|
||||||
@ -793,7 +847,9 @@ const Parser = struct {
|
|||||||
.ExpectedToken = .{ .token = parser.it.index, .expected_id = .Identifier },
|
.ExpectedToken = .{ .token = parser.it.index, .expected_id = .Identifier },
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return ptr;
|
if (ptr) |some|
|
||||||
|
return &some.base;
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
node = try parser.arena.create(Node.Declarator);
|
node = try parser.arena.create(Node.Declarator);
|
||||||
@ -808,16 +864,16 @@ const Parser = struct {
|
|||||||
node.suffix = .{
|
node.suffix = .{
|
||||||
.Fn = .{
|
.Fn = .{
|
||||||
.lparen = lparen,
|
.lparen = lparen,
|
||||||
.params = .Node.Declarator.Params.init(parser.arena),
|
.params = Node.Declarator.Params.init(parser.arena),
|
||||||
.rparen = undefined,
|
.rparen = undefined,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
try parser.ParamDecl(node);
|
try parser.paramDecl(node);
|
||||||
node.suffix.Fn.rparen = try parser.expectToken(.RParen);
|
node.suffix.Fn.rparen = try parser.expectToken(.RParen);
|
||||||
} else {
|
} else {
|
||||||
while (parser.arrayDeclarator()) |arr| {
|
while (try parser.arrayDeclarator()) |arr| {
|
||||||
if (node.suffix == .None)
|
if (node.suffix == .None)
|
||||||
node.suffix = .{ .Array = .Node.Declarator.Arrays.init(parser.arena) };
|
node.suffix = .{ .Array = Node.Declarator.Arrays.init(parser.arena) };
|
||||||
try node.suffix.Array.push(arr);
|
try node.suffix.Array.push(arr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -825,7 +881,7 @@ const Parser = struct {
|
|||||||
return parser.err(.{
|
return parser.err(.{
|
||||||
.InvalidDeclarator = .{ .token = tok },
|
.InvalidDeclarator = .{ .token = tok },
|
||||||
});
|
});
|
||||||
return node;
|
return &node.base;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ArrayDeclarator
|
/// ArrayDeclarator
|
||||||
@ -834,11 +890,11 @@ const Parser = struct {
|
|||||||
/// / TypeQual+ (ASTERISK / Keyword_static AssignmentExpr)
|
/// / TypeQual+ (ASTERISK / Keyword_static AssignmentExpr)
|
||||||
/// / TypeQual+ AssignmentExpr?
|
/// / TypeQual+ AssignmentExpr?
|
||||||
/// / AssignmentExpr
|
/// / AssignmentExpr
|
||||||
fn arrayDeclarator(parser: *Parser, dr: *Node.Declarator) !?*Node.Array {
|
fn arrayDeclarator(parser: *Parser) !?*Node.Array {
|
||||||
const lbracket = parser.eatToken(.LBracket) orelse return null;
|
const lbracket = parser.eatToken(.LBracket) orelse return null;
|
||||||
const arr = try parser.arena.create(Node.Array);
|
const arr = try parser.arena.create(Node.Array);
|
||||||
arr.* = .{
|
arr.* = .{
|
||||||
.lbracket = lbarcket,
|
.lbracket = lbracket,
|
||||||
.inner = .Inferred,
|
.inner = .Inferred,
|
||||||
.rbracket = undefined,
|
.rbracket = undefined,
|
||||||
};
|
};
|
||||||
@ -856,12 +912,12 @@ const Parser = struct {
|
|||||||
fn paramDecl(parser: *Parser, dr: *Node.Declarator) !void {
|
fn paramDecl(parser: *Parser, dr: *Node.Declarator) !void {
|
||||||
var old_style = false;
|
var old_style = false;
|
||||||
while (true) {
|
while (true) {
|
||||||
var ds = Node.DeclSpec;
|
var ds = Node.DeclSpec{};
|
||||||
if (try parser.declSpec(&ds)) {
|
if (try parser.declSpec(&ds)) {
|
||||||
//TODO
|
//TODO
|
||||||
} else if (parser.eatToken(.Identifier)) {
|
} else if (parser.eatToken(.Identifier)) |tok| {
|
||||||
old_style = true;
|
old_style = true;
|
||||||
} else if (parser.eatToken(.Ellipsis)) {
|
} else if (parser.eatToken(.Ellipsis)) |tok| {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user