| ... | ... | @@ -104,7 +104,14 @@ const Parser = struct { |
| 104 | 104 | ty: *Type, |
| 105 | 105 | }; |
| 106 | 106 | |
| 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 | 115 | return parser.symbols.len; |
| 109 | 116 | } |
| 110 | 117 | |
| ... | ... | @@ -130,6 +137,8 @@ const Parser = struct { |
| 130 | 137 | |
| 131 | 138 | /// Root <- ExternalDeclaration* eof |
| 132 | 139 | fn root(parser: *Parser) Allocator.Error!*Node.Root { |
| 140 | const scope = parser.pushScope(.Root); |
| 141 | defer parser.popScope(scope); |
| 133 | 142 | const node = try parser.arena.create(Node.Root); |
| 134 | 143 | node.* = .{ |
| 135 | 144 | .decls = Node.Root.DeclList.init(parser.arena), |
| ... | ... | @@ -779,7 +788,7 @@ const Parser = struct { |
| 779 | 788 | .ty = ty, |
| 780 | 789 | }); |
| 781 | 790 | if (parser.eatToken(.LBrace)) |lbrace| { |
| 782 | | const scope = parser.pushScope(); |
| 791 | const scope = parser.pushScope(.Block); |
| 783 | 792 | defer parser.popScope(scope); |
| 784 | 793 | var fields = Node.RecordType.FieldList.init(parser.arena); |
| 785 | 794 | while (true) { |
| ... | ... | @@ -1079,18 +1088,22 @@ const Parser = struct { |
| 1079 | 1088 | |
| 1080 | 1089 | /// CompoundStmt <- LBRACE (Declaration / Stmt)* RBRACE |
| 1081 | 1090 | fn compoundStmt(parser: *Parser) Error!?*Node { |
| 1082 | | const scope = parser.pushScope(); |
| 1083 | | defer parser.popScope(scope); |
| 1084 | 1091 | const lbrace = parser.eatToken(.LBrace) orelse return null; |
| 1092 | const scope = parser.pushScope(.Block); |
| 1093 | defer parser.popScope(scope); |
| 1085 | 1094 | const body_node = try parser.arena.create(Node.CompoundStmt); |
| 1086 | 1095 | body_node.* = .{ |
| 1087 | 1096 | .lbrace = lbrace, |
| 1088 | 1097 | .statements = Node.CompoundStmt.StmtList.init(parser.arena), |
| 1089 | 1098 | .rbrace = undefined, |
| 1090 | 1099 | }; |
| 1091 | | while ((try parser.declaration()) orelse (try parser.stmt())) |node| |
| 1092 | | try body_node.statements.push(node); |
| 1093 | | body_node.rbrace = try parser.expectToken(.RBrace); |
| 1100 | while (true) { |
| 1101 | if (parser.eatToken(.RBRACE)) |rbrace| { |
| 1102 | body_node.rbrace = rbrace; |
| 1103 | break; |
| 1104 | } |
| 1105 | try body_node.statements.push((try parser.declaration()) orelse (try parser.stmt())); |
| 1106 | } |
| 1094 | 1107 | return &body_node.base; |
| 1095 | 1108 | } |
| 1096 | 1109 | |
| ... | ... | @@ -1109,7 +1122,7 @@ const Parser = struct { |
| 1109 | 1122 | /// / Keyword_return Expr? SEMICOLON |
| 1110 | 1123 | /// / IDENTIFIER COLON Stmt |
| 1111 | 1124 | /// / ExprStmt |
| 1112 | | fn stmt(parser: *Parser) Error!?*Node { |
| 1125 | fn stmt(parser: *Parser) Error!*Node { |
| 1113 | 1126 | if (try parser.compoundStmt()) |node| return node; |
| 1114 | 1127 | if (parser.eatToken(.Keyword_if)) |tok| { |
| 1115 | 1128 | const node = try parser.arena.create(Node.IfStmt); |
| ... | ... | @@ -1123,22 +1136,18 @@ const Parser = struct { |
| 1123 | 1136 | .@"else" = null, |
| 1124 | 1137 | }; |
| 1125 | 1138 | _ = try parser.expectToken(.RParen); |
| 1126 | | node.body = (try parser.stmt()) orelse return parser.err(.{ |
| 1127 | | .ExpectedStmt = .{ .token = parser.it.index }, |
| 1128 | | }); |
| 1139 | node.body = try parser.stmt(); |
| 1129 | 1140 | if (parser.eatToken(.Keyword_else)) |else_tok| { |
| 1130 | 1141 | node.@"else" = .{ |
| 1131 | 1142 | .tok = else_tok, |
| 1132 | | .body = (try parser.stmt()) orelse return parser.err(.{ |
| 1133 | | .ExpectedStmt = .{ .token = parser.it.index }, |
| 1134 | | }), |
| 1143 | .body = try parser.stmt(), |
| 1135 | 1144 | }; |
| 1136 | 1145 | } |
| 1137 | 1146 | return &node.base; |
| 1138 | 1147 | } |
| 1139 | | |
| 1140 | | // TODO loop scope |
| 1141 | 1148 | if (parser.eatToken(.Keyword_while)) |tok| { |
| 1149 | const scope = parser.pushScope(.Loop); |
| 1150 | defer parser.popScope(scope); |
| 1142 | 1151 | _ = try parser.expectToken(.LParen); |
| 1143 | 1152 | const cond = (try parser.expr()) orelse return parser.err(.{ |
| 1144 | 1153 | .ExpectedExpr = .{ .token = parser.it.index }, |
| ... | ... | @@ -1149,18 +1158,15 @@ const Parser = struct { |
| 1149 | 1158 | .@"while" = tok, |
| 1150 | 1159 | .cond = cond, |
| 1151 | 1160 | .rparen = rparen, |
| 1152 | | .body = (try parser.stmt()) orelse return parser.err(.{ |
| 1153 | | .ExpectedStmt = .{ .token = parser.it.index }, |
| 1154 | | }), |
| 1161 | .body = try parser.stmt(), |
| 1155 | 1162 | .semicolon = try parser.expectToken(.Semicolon), |
| 1156 | 1163 | }; |
| 1157 | 1164 | return &node.base; |
| 1158 | 1165 | } |
| 1159 | 1166 | 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); |
| 1167 | const scope = parser.pushScope(.Loop); |
| 1168 | defer parser.popScope(scope); |
| 1169 | const body = try parser.stmt(); |
| 1164 | 1170 | _ = try parser.expectToken(.LParen); |
| 1165 | 1171 | const cond = (try parser.expr()) orelse return parser.err(.{ |
| 1166 | 1172 | .ExpectedExpr = .{ .token = parser.it.index }, |
| ... | ... | @@ -1177,6 +1183,8 @@ const Parser = struct { |
| 1177 | 1183 | return &node.base; |
| 1178 | 1184 | } |
| 1179 | 1185 | if (parser.eatToken(.Keyword_for)) |tok| { |
| 1186 | const scope = parser.pushScope(.Loop); |
| 1187 | defer parser.popScope(scope); |
| 1180 | 1188 | _ = try parser.expectToken(.LParen); |
| 1181 | 1189 | const init = if (try parser.declaration()) |decl| blk:{ |
| 1182 | 1190 | // TODO disallow storage class other than auto and register |
| ... | ... | @@ -1194,15 +1202,43 @@ const Parser = struct { |
| 1194 | 1202 | .semicolon = semicolon, |
| 1195 | 1203 | .incr = incr, |
| 1196 | 1204 | .rparen = rparen, |
| 1197 | | .body = (try parser.stmt()) orelse return parser.err(.{ |
| 1198 | | .ExpectedStmt = .{ .token = parser.it.index }, |
| 1199 | | }), |
| 1205 | .body = try parser.stmt(), |
| 1206 | }; |
| 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 | 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 | 1242 | if (parser.eatToken(.Keyword_goto)) |tok| { |
| 1207 | 1243 | const node = try parser.arena.create(Node.JumpStmt); |
| 1208 | 1244 | node.* = .{ |
| ... | ... | @@ -1241,29 +1277,24 @@ const Parser = struct { |
| 1241 | 1277 | } |
| 1242 | 1278 | if (parser.eatToken(.Identifier)) |tok| { |
| 1243 | 1279 | if (parser.eatToken(.Colon)) |_| { |
| 1244 | | const node = try parser.arena.create(Node.Label); |
| 1280 | const node = try parser.arena.create(Node.LabeledStmt); |
| 1245 | 1281 | node.* = .{ |
| 1246 | | .identifier = tok, |
| 1282 | .kind = .{.Label = tok }, |
| 1283 | .stmt = try parser.stmt(), |
| 1247 | 1284 | }; |
| 1248 | 1285 | return &node.base; |
| 1249 | 1286 | } |
| 1250 | 1287 | parser.putBackToken(tok); |
| 1251 | 1288 | } |
| 1252 | | if (try parser.exprStmt()) |node| return node; |
| 1253 | | return null; |
| 1289 | return parser.exprStmt(); |
| 1254 | 1290 | } |
| 1255 | 1291 | |
| 1256 | 1292 | /// ExprStmt <- Expr? SEMICOLON |
| 1257 | | fn exprStmt(parser: *Parser) !?*Node { |
| 1293 | fn exprStmt(parser: *Parser) !*Node { |
| 1258 | 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 | 1295 | node.* = .{ |
| 1265 | | .expr = expr_node, |
| 1266 | | .semicolon = semicolon, |
| 1296 | .expr = try parser.expr(), |
| 1297 | .semicolon = try parser.expectToken(.Semicolon), |
| 1267 | 1298 | }; |
| 1268 | 1299 | return &node.base; |
| 1269 | 1300 | } |