| ... | @@ -1119,23 +1119,88 @@ const Parser = struct { | ... | @@ -1119,23 +1119,88 @@ const Parser = struct { |
| 1119 | .cond = (try parser.expr()) orelse return parser.err(.{ | 1119 | .cond = (try parser.expr()) orelse return parser.err(.{ |
| 1120 | .ExpectedExpr = .{ .token = parser.it.index }, | 1120 | .ExpectedExpr = .{ .token = parser.it.index }, |
| 1121 | }), | 1121 | }), |
| | 1122 | .body = undefined, |
| 1122 | .@"else" = null, | 1123 | .@"else" = null, |
| 1123 | }; | 1124 | }; |
| 1124 | _ = try parser.expectToken(.RParen); | 1125 | _ = try parser.expectToken(.RParen); |
| | 1126 | node.body = (try parser.stmt()) orelse return parser.err(.{ |
| | 1127 | .ExpectedStmt = .{ .token = parser.it.index }, |
| | 1128 | }); |
| 1125 | if (parser.eatToken(.Keyword_else)) |else_tok| { | 1129 | if (parser.eatToken(.Keyword_else)) |else_tok| { |
| 1126 | node.@"else" = .{ | 1130 | node.@"else" = .{ |
| 1127 | .tok = else_tok, | 1131 | .tok = else_tok, |
| 1128 | .stmt = (try parser.stmt()) orelse return parser.err(.{ | 1132 | .body = (try parser.stmt()) orelse return parser.err(.{ |
| 1129 | .ExpectedStmt = .{ .token = parser.it.index }, | 1133 | .ExpectedStmt = .{ .token = parser.it.index }, |
| 1130 | }), | 1134 | }), |
| 1131 | }; | 1135 | }; |
| 1132 | } | 1136 | } |
| 1133 | return &node.base; | 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 | // if (parser.eatToken(.Keyword_switch)) |tok| {} | 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 | // if (parser.eatToken(.Keyword_default)) |tok| {} | 1204 | // if (parser.eatToken(.Keyword_default)) |tok| {} |
| 1140 | // if (parser.eatToken(.Keyword_case)) |tok| {} | 1205 | // if (parser.eatToken(.Keyword_case)) |tok| {} |
| 1141 | if (parser.eatToken(.Keyword_goto)) |tok| { | 1206 | if (parser.eatToken(.Keyword_goto)) |tok| { |