std-c parser loops

This commit is contained in:
Vexu 2020-01-08 00:00:14 +02:00
parent 83b4163591
commit e21ea5bd95
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
2 changed files with 103 additions and 6 deletions

View File

@ -229,6 +229,9 @@ pub const Node = struct {
Label,
CompoundStmt,
IfStmt,
WhileStmt,
DoStmt,
ForStmt,
StaticAssert,
Declarator,
Pointer,
@ -438,7 +441,7 @@ pub const Node = struct {
pub const RecordDeclarator = struct {
base: Node = Node{ .id = .RecordField },
declarator: *Declarator,
// bit_field_expr: ?*Expr,
bit_field_expr: ?*Expr,
};
pub const TypeQual = struct {
@ -486,12 +489,41 @@ pub const Node = struct {
base: Node = Node{ .id = .IfStmt },
@"if": TokenIndex,
cond: *Node,
body: *Node,
@"else": ?struct {
tok: TokenIndex,
stmt: *Node,
body: *Node,
},
};
pub const WhileStmt = struct {
base: Node = Node{ .id = .WhileStmt },
@"while": TokenIndex,
cond: *Expr,
rparen: TokenIndex,
body: *Node,
};
pub const DoStmt = struct {
base: Node = Node{ .id = .DoStmt },
do: TokenIndex,
body: *Node,
@"while": TokenIndex,
cond: *Expr,
semicolon: TokenIndex,
};
pub const ForStmt = struct {
base: Node = Node{ .id = .ForStmt },
@"for": TokenIndex,
init: ?*Node,
cond: ?*Expr,
semicolon: TokenIndex,
incr: ?*Expr,
rparen: TokenIndex,
body: *Node,
};
pub const StaticAssert = struct {
base: Node = Node{ .id = .StaticAssert },
assert: TokenIndex,

View File

@ -1119,23 +1119,88 @@ const Parser = struct {
.cond = (try parser.expr()) orelse return parser.err(.{
.ExpectedExpr = .{ .token = parser.it.index },
}),
.body = undefined,
.@"else" = null,
};
_ = try parser.expectToken(.RParen);
node.body = (try parser.stmt()) orelse return parser.err(.{
.ExpectedStmt = .{ .token = parser.it.index },
});
if (parser.eatToken(.Keyword_else)) |else_tok| {
node.@"else" = .{
.tok = else_tok,
.stmt = (try parser.stmt()) orelse return parser.err(.{
.body = (try parser.stmt()) orelse return parser.err(.{
.ExpectedStmt = .{ .token = parser.it.index },
}),
};
}
return &node.base;
}
// TODO loop scope
if (parser.eatToken(.Keyword_while)) |tok| {
_ = try parser.expectToken(.LParen);
const cond = (try parser.expr()) orelse return parser.err(.{
.ExpectedExpr = .{ .token = parser.it.index },
});
const rparen = try parser.expectToken(.RParen);
const node = try parser.arena.create(Node.WhileStmt);
node.* = .{
.@"while" = tok,
.cond = cond,
.rparen = rparen,
.body = (try parser.stmt()) orelse return parser.err(.{
.ExpectedStmt = .{ .token = parser.it.index },
}),
.semicolon = try parser.expectToken(.Semicolon),
};
return &node.base;
}
if (parser.eatToken(.Keyword_do)) |tok| {
const body = (try parser.stmt()) orelse return parser.err(.{
.ExpectedStmt = .{ .token = parser.it.index },
});
const @"while" = try parser.expectToken(.Keyword_while);
_ = try parser.expectToken(.LParen);
const cond = (try parser.expr()) orelse return parser.err(.{
.ExpectedExpr = .{ .token = parser.it.index },
});
_ = try parser.expectToken(.RParen);
const node = try parser.arena.create(Node.DoStmt);
node.* = .{
.do = tok,
.body = body,
.cond = cond,
.@"while" = @"while",
.semicolon = try parser.expectToken(.Semicolon),
};
return &node.base;
}
if (parser.eatToken(.Keyword_for)) |tok| {
_ = try parser.expectToken(.LParen);
const init = if (try parser.declaration()) |decl| blk:{
// TODO disallow storage class other than auto and register
break :blk decl;
} else try parser.exprStmt();
const cond = try parser.expr();
const semicolon = try parser.expectToken(.Semicolon);
const incr = try parser.expr();
const rparen = try parser.expectToken(.RParen);
const node = try parser.arena.create(Node.ForStmt);
node.* = .{
.@"for" = tok,
.init = init,
.cond = cond,
.semicolon = semicolon,
.incr = incr,
.rparen = rparen,
.body = (try parser.stmt()) orelse return parser.err(.{
.ExpectedStmt = .{ .token = parser.it.index },
}),
};
return &node.base;
}
// if (parser.eatToken(.Keyword_switch)) |tok| {}
// if (parser.eatToken(.Keyword_while)) |tok| {}
// if (parser.eatToken(.Keyword_do)) |tok| {}
// if (parser.eatToken(.Keyword_for)) |tok| {}
// if (parser.eatToken(.Keyword_default)) |tok| {}
// if (parser.eatToken(.Keyword_case)) |tok| {}
if (parser.eatToken(.Keyword_goto)) |tok| {