std-c parser declarator

master
Vexu 2020-01-06 14:41:53 +02:00
parent d5d52af26e
commit 3ed6d7d245
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
2 changed files with 153 additions and 37 deletions

View File

@ -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,
};

View File

@ -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.base;
}
const Named = enum {
Must,
Allowed,
Forbidden,
};
/// Declarator <- Pointer? DeclaratorSuffix
/// DeclaratorPrefix
/// <- IDENTIFIER // if named != .Forbidden
/// / LPAREN Declarator RPAREN
/// / (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;
}
/// DirectDeclarator
/// <- IDENTIFIER
/// / LPAREN Declarator RPAREN
/// / DirectDeclarator LBRACKET (ASTERISK / BracketDeclarator)? RBRACKET
/// / DirectDeclarator LPAREN (ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?)? RPAREN
fn directDeclarator(parser: *Parser) !*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 {}