authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-11 21:46:36+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-11 21:48:12+02:00
log4c0776b2a5a8a92e770fe0b08a15e06671000cb6
tree5a3fbe1bf0cee6f05e5804e3c192f36fe4ff0614
parente21ea5bd9583e583c1691b05df682178f1bea10f
signature Commit is signed but in an unrecognized format.

std-c parse switch


2 files changed, 94 insertions(+), 54 deletions(-)

lib/std/c/ast.zig+22-13
...@@ -48,7 +48,6 @@ pub const Error = union(enum) {...@@ -48,7 +48,6 @@ pub const Error = union(enum) {
48 InvalidToken: SingleTokenError("invalid token '{}'"),48 InvalidToken: SingleTokenError("invalid token '{}'"),
49 ExpectedToken: ExpectedToken,49 ExpectedToken: ExpectedToken,
50 ExpectedExpr: SingleTokenError("expected expression, found '{}'"),50 ExpectedExpr: SingleTokenError("expected expression, found '{}'"),
51 ExpectedStmt: SingleTokenError("expected statement, found '{}'"),
52 ExpectedTypeName: SingleTokenError("expected type name, found '{}'"),51 ExpectedTypeName: SingleTokenError("expected type name, found '{}'"),
53 ExpectedFnBody: SingleTokenError("expected function body, found '{}'"),52 ExpectedFnBody: SingleTokenError("expected function body, found '{}'"),
54 ExpectedDeclarator: SingleTokenError("expected declarator, found '{}'"),53 ExpectedDeclarator: SingleTokenError("expected declarator, found '{}'"),
...@@ -70,7 +69,6 @@ pub const Error = union(enum) {...@@ -70,7 +69,6 @@ pub const Error = union(enum) {
70 .InvalidToken => |*x| return x.render(tree, stream),69 .InvalidToken => |*x| return x.render(tree, stream),
71 .ExpectedToken => |*x| return x.render(tree, stream),70 .ExpectedToken => |*x| return x.render(tree, stream),
72 .ExpectedExpr => |*x| return x.render(tree, stream),71 .ExpectedExpr => |*x| return x.render(tree, stream),
73 .ExpectedStmt => |*x| return x.render(tree, stream),
74 .ExpectedTypeName => |*x| return x.render(tree, stream),72 .ExpectedTypeName => |*x| return x.render(tree, stream),
75 .ExpectedDeclarator => |*x| return x.render(tree, stream),73 .ExpectedDeclarator => |*x| return x.render(tree, stream),
76 .ExpectedFnBody => |*x| return x.render(tree, stream),74 .ExpectedFnBody => |*x| return x.render(tree, stream),
...@@ -94,7 +92,6 @@ pub const Error = union(enum) {...@@ -94,7 +92,6 @@ pub const Error = union(enum) {
94 .InvalidToken => |x| return x.token,92 .InvalidToken => |x| return x.token,
95 .ExpectedToken => |x| return x.token,93 .ExpectedToken => |x| return x.token,
96 .ExpectedExpr => |x| return x.token,94 .ExpectedExpr => |x| return x.token,
97 .ExpectedStmt => |x| return x.token,
98 .ExpectedTypeName => |x| return x.token,95 .ExpectedTypeName => |x| return x.token,
99 .ExpectedDeclarator => |x| return x.token,96 .ExpectedDeclarator => |x| return x.token,
100 .ExpectedFnBody => |x| return x.token,97 .ExpectedFnBody => |x| return x.token,
...@@ -226,9 +223,10 @@ pub const Node = struct {...@@ -226,9 +223,10 @@ pub const Node = struct {
226 RecordField,223 RecordField,
227 JumpStmt,224 JumpStmt,
228 ExprStmt,225 ExprStmt,
229 Label,226 LabeledStmt,
230 CompoundStmt,227 CompoundStmt,
231 IfStmt,228 IfStmt,
229 SwitchStmt,
232 WhileStmt,230 WhileStmt,
233 DoStmt,231 DoStmt,
234 ForStmt,232 ForStmt,
...@@ -454,26 +452,29 @@ pub const Node = struct {...@@ -454,26 +452,29 @@ pub const Node = struct {
454 pub const JumpStmt = struct {452 pub const JumpStmt = struct {
455 base: Node = Node{ .id = .JumpStmt },453 base: Node = Node{ .id = .JumpStmt },
456 ltoken: TokenIndex,454 ltoken: TokenIndex,
457 kind: Kind,455 kind: union(enum) {
458 semicolon: TokenIndex,
459
460 pub const Kind = union(enum) {
461 Break,456 Break,
462 Continue,457 Continue,
463 Return: ?*Node,458 Return: ?*Node,
464 Goto: TokenIndex,459 Goto: TokenIndex,
465 };460 },
461 semicolon: TokenIndex,
466 };462 };
467463
468 pub const ExprStmt = struct {464 pub const ExprStmt = struct {
469 base: Node = Node{ .id = .ExprStmt },465 base: Node = Node{ .id = .ExprStmt },
470 expr: ?*Node,466 expr: ?*Expr,
471 semicolon: TokenIndex,467 semicolon: TokenIndex,
472 };468 };
473469
474 pub const Label = struct {470 pub const LabeledStmt = struct {
475 base: Node = Node{ .id = .Label },471 base: Node = Node{ .id = .LabeledStmt },
476 identifier: TokenIndex,472 kind: union(enum) {
473 Label: TokenIndex,
474 Case: TokenIndex,
475 Default: TokenIndex,
476 },
477 stmt: *Node,
477 };478 };
478479
479 pub const CompoundStmt = struct {480 pub const CompoundStmt = struct {
...@@ -496,6 +497,14 @@ pub const Node = struct {...@@ -496,6 +497,14 @@ pub const Node = struct {
496 },497 },
497 };498 };
498499
500 pub const SwitchStmt = struct {
501 base: Node = Node{ .id = .SwitchStmt },
502 @"switch": TokenIndex,
503 expr: *Expr,
504 rparen: TokenIndex,
505 stmt: *Node,
506 };
507
499 pub const WhileStmt = struct {508 pub const WhileStmt = struct {
500 base: Node = Node{ .id = .WhileStmt },509 base: Node = Node{ .id = .WhileStmt },
501 @"while": TokenIndex,510 @"while": TokenIndex,
lib/std/c/parse.zig+72-41
...@@ -104,7 +104,14 @@ const Parser = struct {...@@ -104,7 +104,14 @@ const Parser = struct {
104 ty: *Type,104 ty: *Type,
105 };105 };
106106
107 fn pushScope(parser: *Parser) usize {107 const ScopeKind = enum {
108 Block,
109 Loop,
110 Root,
111 Switch,
112 };
113
114 fn pushScope(parser: *Parser, kind: ScopeKind) usize {
108 return parser.symbols.len;115 return parser.symbols.len;
109 }116 }
110117
...@@ -130,6 +137,8 @@ const Parser = struct {...@@ -130,6 +137,8 @@ const Parser = struct {
130137
131 /// Root <- ExternalDeclaration* eof138 /// Root <- ExternalDeclaration* eof
132 fn root(parser: *Parser) Allocator.Error!*Node.Root {139 fn root(parser: *Parser) Allocator.Error!*Node.Root {
140 const scope = parser.pushScope(.Root);
141 defer parser.popScope(scope);
133 const node = try parser.arena.create(Node.Root);142 const node = try parser.arena.create(Node.Root);
134 node.* = .{143 node.* = .{
135 .decls = Node.Root.DeclList.init(parser.arena),144 .decls = Node.Root.DeclList.init(parser.arena),
...@@ -779,7 +788,7 @@ const Parser = struct {...@@ -779,7 +788,7 @@ const Parser = struct {
779 .ty = ty,788 .ty = ty,
780 });789 });
781 if (parser.eatToken(.LBrace)) |lbrace| {790 if (parser.eatToken(.LBrace)) |lbrace| {
782 const scope = parser.pushScope();791 const scope = parser.pushScope(.Block);
783 defer parser.popScope(scope);792 defer parser.popScope(scope);
784 var fields = Node.RecordType.FieldList.init(parser.arena);793 var fields = Node.RecordType.FieldList.init(parser.arena);
785 while (true) {794 while (true) {
...@@ -1079,18 +1088,22 @@ const Parser = struct {...@@ -1079,18 +1088,22 @@ const Parser = struct {
10791088
1080 /// CompoundStmt <- LBRACE (Declaration / Stmt)* RBRACE1089 /// CompoundStmt <- LBRACE (Declaration / Stmt)* RBRACE
1081 fn compoundStmt(parser: *Parser) Error!?*Node {1090 fn compoundStmt(parser: *Parser) Error!?*Node {
1082 const scope = parser.pushScope();
1083 defer parser.popScope(scope);
1084 const lbrace = parser.eatToken(.LBrace) orelse return null;1091 const lbrace = parser.eatToken(.LBrace) orelse return null;
1092 const scope = parser.pushScope(.Block);
1093 defer parser.popScope(scope);
1085 const body_node = try parser.arena.create(Node.CompoundStmt);1094 const body_node = try parser.arena.create(Node.CompoundStmt);
1086 body_node.* = .{1095 body_node.* = .{
1087 .lbrace = lbrace,1096 .lbrace = lbrace,
1088 .statements = Node.CompoundStmt.StmtList.init(parser.arena),1097 .statements = Node.CompoundStmt.StmtList.init(parser.arena),
1089 .rbrace = undefined,1098 .rbrace = undefined,
1090 };1099 };
1091 while ((try parser.declaration()) orelse (try parser.stmt())) |node|1100 while (true) {
1092 try body_node.statements.push(node);1101 if (parser.eatToken(.RBRACE)) |rbrace| {
1093 body_node.rbrace = try parser.expectToken(.RBrace);1102 body_node.rbrace = rbrace;
1103 break;
1104 }
1105 try body_node.statements.push((try parser.declaration()) orelse (try parser.stmt()));
1106 }
1094 return &body_node.base;1107 return &body_node.base;
1095 }1108 }
10961109
...@@ -1109,7 +1122,7 @@ const Parser = struct {...@@ -1109,7 +1122,7 @@ const Parser = struct {
1109 /// / Keyword_return Expr? SEMICOLON1122 /// / Keyword_return Expr? SEMICOLON
1110 /// / IDENTIFIER COLON Stmt1123 /// / IDENTIFIER COLON Stmt
1111 /// / ExprStmt1124 /// / ExprStmt
1112 fn stmt(parser: *Parser) Error!?*Node {1125 fn stmt(parser: *Parser) Error!*Node {
1113 if (try parser.compoundStmt()) |node| return node;1126 if (try parser.compoundStmt()) |node| return node;
1114 if (parser.eatToken(.Keyword_if)) |tok| {1127 if (parser.eatToken(.Keyword_if)) |tok| {
1115 const node = try parser.arena.create(Node.IfStmt);1128 const node = try parser.arena.create(Node.IfStmt);
...@@ -1123,22 +1136,18 @@ const Parser = struct {...@@ -1123,22 +1136,18 @@ const Parser = struct {
1123 .@"else" = null,1136 .@"else" = null,
1124 };1137 };
1125 _ = try parser.expectToken(.RParen);1138 _ = try parser.expectToken(.RParen);
1126 node.body = (try parser.stmt()) orelse return parser.err(.{1139 node.body = try parser.stmt();
1127 .ExpectedStmt = .{ .token = parser.it.index },
1128 });
1129 if (parser.eatToken(.Keyword_else)) |else_tok| {1140 if (parser.eatToken(.Keyword_else)) |else_tok| {
1130 node.@"else" = .{1141 node.@"else" = .{
1131 .tok = else_tok,1142 .tok = else_tok,
1132 .body = (try parser.stmt()) orelse return parser.err(.{1143 .body = try parser.stmt(),
1133 .ExpectedStmt = .{ .token = parser.it.index },
1134 }),
1135 };1144 };
1136 }1145 }
1137 return &node.base;1146 return &node.base;
1138 }1147 }
1139
1140 // TODO loop scope
1141 if (parser.eatToken(.Keyword_while)) |tok| {1148 if (parser.eatToken(.Keyword_while)) |tok| {
1149 const scope = parser.pushScope(.Loop);
1150 defer parser.popScope(scope);
1142 _ = try parser.expectToken(.LParen);1151 _ = try parser.expectToken(.LParen);
1143 const cond = (try parser.expr()) orelse return parser.err(.{1152 const cond = (try parser.expr()) orelse return parser.err(.{
1144 .ExpectedExpr = .{ .token = parser.it.index },1153 .ExpectedExpr = .{ .token = parser.it.index },
...@@ -1149,18 +1158,15 @@ const Parser = struct {...@@ -1149,18 +1158,15 @@ const Parser = struct {
1149 .@"while" = tok,1158 .@"while" = tok,
1150 .cond = cond,1159 .cond = cond,
1151 .rparen = rparen,1160 .rparen = rparen,
1152 .body = (try parser.stmt()) orelse return parser.err(.{1161 .body = try parser.stmt(),
1153 .ExpectedStmt = .{ .token = parser.it.index },
1154 }),
1155 .semicolon = try parser.expectToken(.Semicolon),1162 .semicolon = try parser.expectToken(.Semicolon),
1156 };1163 };
1157 return &node.base;1164 return &node.base;
1158 }1165 }
1159 if (parser.eatToken(.Keyword_do)) |tok| {1166 if (parser.eatToken(.Keyword_do)) |tok| {
1160 const body = (try parser.stmt()) orelse return parser.err(.{1167 const scope = parser.pushScope(.Loop);
1161 .ExpectedStmt = .{ .token = parser.it.index },1168 defer parser.popScope(scope);
1162 });1169 const body = try parser.stmt();
1163 const @"while" = try parser.expectToken(.Keyword_while);
1164 _ = try parser.expectToken(.LParen);1170 _ = try parser.expectToken(.LParen);
1165 const cond = (try parser.expr()) orelse return parser.err(.{1171 const cond = (try parser.expr()) orelse return parser.err(.{
1166 .ExpectedExpr = .{ .token = parser.it.index },1172 .ExpectedExpr = .{ .token = parser.it.index },
...@@ -1177,6 +1183,8 @@ const Parser = struct {...@@ -1177,6 +1183,8 @@ const Parser = struct {
1177 return &node.base;1183 return &node.base;
1178 }1184 }
1179 if (parser.eatToken(.Keyword_for)) |tok| {1185 if (parser.eatToken(.Keyword_for)) |tok| {
1186 const scope = parser.pushScope(.Loop);
1187 defer parser.popScope(scope);
1180 _ = try parser.expectToken(.LParen);1188 _ = try parser.expectToken(.LParen);
1181 const init = if (try parser.declaration()) |decl| blk:{1189 const init = if (try parser.declaration()) |decl| blk:{
1182 // TODO disallow storage class other than auto and register1190 // TODO disallow storage class other than auto and register
...@@ -1194,15 +1202,43 @@ const Parser = struct {...@@ -1194,15 +1202,43 @@ const Parser = struct {
1194 .semicolon = semicolon,1202 .semicolon = semicolon,
1195 .incr = incr,1203 .incr = incr,
1196 .rparen = rparen,1204 .rparen = rparen,
1197 .body = (try parser.stmt()) orelse return parser.err(.{1205 .body = try parser.stmt(),
1198 .ExpectedStmt = .{ .token = parser.it.index },1206 };
1199 }),1207 return &node.base;
1208 }
1209 if (parser.eatToken(.Keyword_switch)) |tok| {
1210 const scope = parser.pushScope(.Switch);
1211 defer parser.popScope(scope);
1212 _ = try parser.expectToken(.LParen);
1213 const switch_expr = try parser.exprStmt();
1214 const rparen = try parser.expectToken(.RParen);
1215 const node = try parser.arena.create(Node.SwitchStmt);
1216 node.* = .{
1217 .@"switch" = tok,
1218 .expr = switch_expr,
1219 .rparen = rparen,
1220 .body = try parser.stmt(),
1221 };
1222 return &node.base;
1223 }
1224 if (parser.eatToken(.Keyword_default)) |tok| {
1225 _ = try parser.expectToken(.Colon);
1226 const node = try parser.arena.create(Node.LabeledStmt);
1227 node.* = .{
1228 .kind = .{.Default = tok },
1229 .stmt = try parser.stmt(),
1230 };
1231 return &node.base;
1232 }
1233 if (parser.eatToken(.Keyword_case)) |tok| {
1234 _ = try parser.expectToken(.Colon);
1235 const node = try parser.arena.create(Node.LabeledStmt);
1236 node.* = .{
1237 .kind = .{.Case = tok },
1238 .stmt = try parser.stmt(),
1200 };1239 };
1201 return &node.base;1240 return &node.base;
1202 }1241 }
1203 // if (parser.eatToken(.Keyword_switch)) |tok| {}
1204 // if (parser.eatToken(.Keyword_default)) |tok| {}
1205 // if (parser.eatToken(.Keyword_case)) |tok| {}
1206 if (parser.eatToken(.Keyword_goto)) |tok| {1242 if (parser.eatToken(.Keyword_goto)) |tok| {
1207 const node = try parser.arena.create(Node.JumpStmt);1243 const node = try parser.arena.create(Node.JumpStmt);
1208 node.* = .{1244 node.* = .{
...@@ -1241,29 +1277,24 @@ const Parser = struct {...@@ -1241,29 +1277,24 @@ const Parser = struct {
1241 }1277 }
1242 if (parser.eatToken(.Identifier)) |tok| {1278 if (parser.eatToken(.Identifier)) |tok| {
1243 if (parser.eatToken(.Colon)) |_| {1279 if (parser.eatToken(.Colon)) |_| {
1244 const node = try parser.arena.create(Node.Label);1280 const node = try parser.arena.create(Node.LabeledStmt);
1245 node.* = .{1281 node.* = .{
1246 .identifier = tok,1282 .kind = .{.Label = tok },
1283 .stmt = try parser.stmt(),
1247 };1284 };
1248 return &node.base;1285 return &node.base;
1249 }1286 }
1250 parser.putBackToken(tok);1287 parser.putBackToken(tok);
1251 }1288 }
1252 if (try parser.exprStmt()) |node| return node;1289 return parser.exprStmt();
1253 return null;
1254 }1290 }
12551291
1256 /// ExprStmt <- Expr? SEMICOLON1292 /// ExprStmt <- Expr? SEMICOLON
1257 fn exprStmt(parser: *Parser) !?*Node {1293 fn exprStmt(parser: *Parser) !*Node {
1258 const node = try parser.arena.create(Node.ExprStmt);1294 const node = try parser.arena.create(Node.ExprStmt);
1259 const expr_node = try parser.expr();
1260 const semicolon = if (expr_node != null)
1261 try parser.expectToken(.Semicolon)
1262 else
1263 parser.eatToken(.Semicolon) orelse return null;
1264 node.* = .{1295 node.* = .{
1265 .expr = expr_node,1296 .expr = try parser.expr(),
1266 .semicolon = semicolon,1297 .semicolon = try parser.expectToken(.Semicolon),
1267 };1298 };
1268 return &node.base;1299 return &node.base;
1269 }1300 }