| ... | ... | @@ -1119,23 +1119,88 @@ const Parser = struct { |
| 1119 | 1119 | .cond = (try parser.expr()) orelse return parser.err(.{ |
| 1120 | 1120 | .ExpectedExpr = .{ .token = parser.it.index }, |
| 1121 | 1121 | }), |
| 1122 | .body = undefined, |
| 1122 | 1123 | .@"else" = null, |
| 1123 | 1124 | }; |
| 1124 | 1125 | _ = try parser.expectToken(.RParen); |
| 1126 | node.body = (try parser.stmt()) orelse return parser.err(.{ |
| 1127 | .ExpectedStmt = .{ .token = parser.it.index }, |
| 1128 | }); |
| 1125 | 1129 | if (parser.eatToken(.Keyword_else)) |else_tok| { |
| 1126 | 1130 | node.@"else" = .{ |
| 1127 | 1131 | .tok = else_tok, |
| 1128 | | .stmt = (try parser.stmt()) orelse return parser.err(.{ |
| 1132 | .body = (try parser.stmt()) orelse return parser.err(.{ |
| 1129 | 1133 | .ExpectedStmt = .{ .token = parser.it.index }, |
| 1130 | 1134 | }), |
| 1131 | 1135 | }; |
| 1132 | 1136 | } |
| 1133 | 1137 | return &node.base; |
| 1134 | 1138 | } |
| 1139 | |
| 1140 | // TODO loop scope |
| 1141 | if (parser.eatToken(.Keyword_while)) |tok| { |
| 1142 | _ = try parser.expectToken(.LParen); |
| 1143 | const cond = (try parser.expr()) orelse return parser.err(.{ |
| 1144 | .ExpectedExpr = .{ .token = parser.it.index }, |
| 1145 | }); |
| 1146 | const rparen = try parser.expectToken(.RParen); |
| 1147 | const node = try parser.arena.create(Node.WhileStmt); |
| 1148 | node.* = .{ |
| 1149 | .@"while" = tok, |
| 1150 | .cond = cond, |
| 1151 | .rparen = rparen, |
| 1152 | .body = (try parser.stmt()) orelse return parser.err(.{ |
| 1153 | .ExpectedStmt = .{ .token = parser.it.index }, |
| 1154 | }), |
| 1155 | .semicolon = try parser.expectToken(.Semicolon), |
| 1156 | }; |
| 1157 | return &node.base; |
| 1158 | } |
| 1159 | if (parser.eatToken(.Keyword_do)) |tok| { |
| 1160 | const body = (try parser.stmt()) orelse return parser.err(.{ |
| 1161 | .ExpectedStmt = .{ .token = parser.it.index }, |
| 1162 | }); |
| 1163 | const @"while" = try parser.expectToken(.Keyword_while); |
| 1164 | _ = try parser.expectToken(.LParen); |
| 1165 | const cond = (try parser.expr()) orelse return parser.err(.{ |
| 1166 | .ExpectedExpr = .{ .token = parser.it.index }, |
| 1167 | }); |
| 1168 | _ = try parser.expectToken(.RParen); |
| 1169 | const node = try parser.arena.create(Node.DoStmt); |
| 1170 | node.* = .{ |
| 1171 | .do = tok, |
| 1172 | .body = body, |
| 1173 | .cond = cond, |
| 1174 | .@"while" = @"while", |
| 1175 | .semicolon = try parser.expectToken(.Semicolon), |
| 1176 | }; |
| 1177 | return &node.base; |
| 1178 | } |
| 1179 | if (parser.eatToken(.Keyword_for)) |tok| { |
| 1180 | _ = try parser.expectToken(.LParen); |
| 1181 | const init = if (try parser.declaration()) |decl| blk:{ |
| 1182 | // TODO disallow storage class other than auto and register |
| 1183 | break :blk decl; |
| 1184 | } else try parser.exprStmt(); |
| 1185 | const cond = try parser.expr(); |
| 1186 | const semicolon = try parser.expectToken(.Semicolon); |
| 1187 | const incr = try parser.expr(); |
| 1188 | const rparen = try parser.expectToken(.RParen); |
| 1189 | const node = try parser.arena.create(Node.ForStmt); |
| 1190 | node.* = .{ |
| 1191 | .@"for" = tok, |
| 1192 | .init = init, |
| 1193 | .cond = cond, |
| 1194 | .semicolon = semicolon, |
| 1195 | .incr = incr, |
| 1196 | .rparen = rparen, |
| 1197 | .body = (try parser.stmt()) orelse return parser.err(.{ |
| 1198 | .ExpectedStmt = .{ .token = parser.it.index }, |
| 1199 | }), |
| 1200 | }; |
| 1201 | return &node.base; |
| 1202 | } |
| 1135 | 1203 | // if (parser.eatToken(.Keyword_switch)) |tok| {} |
| 1136 | | // if (parser.eatToken(.Keyword_while)) |tok| {} |
| 1137 | | // if (parser.eatToken(.Keyword_do)) |tok| {} |
| 1138 | | // if (parser.eatToken(.Keyword_for)) |tok| {} |
| 1139 | 1204 | // if (parser.eatToken(.Keyword_default)) |tok| {} |
| 1140 | 1205 | // if (parser.eatToken(.Keyword_case)) |tok| {} |
| 1141 | 1206 | if (parser.eatToken(.Keyword_goto)) |tok| { |