| ... | @@ -104,7 +104,14 @@ const Parser = struct { | ... | @@ -104,7 +104,14 @@ const Parser = struct { |
| 104 | ty: *Type, | 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 | return parser.symbols.len; | 115 | return parser.symbols.len; |
| 109 | } | 116 | } |
| 110 | | 117 | |
| ... | @@ -130,6 +137,8 @@ const Parser = struct { | ... | @@ -130,6 +137,8 @@ const Parser = struct { |
| 130 | | 137 | |
| 131 | /// Root <- ExternalDeclaration* eof | 138 | /// 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 { |
| 1079 | | 1088 | |
| 1080 | /// CompoundStmt <- LBRACE (Declaration / Stmt)* RBRACE | 1089 | /// 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 | } |
| 1096 | | 1109 | |
| ... | @@ -1109,7 +1122,7 @@ const Parser = struct { | ... | @@ -1109,7 +1122,7 @@ const Parser = struct { |
| 1109 | /// / Keyword_return Expr? SEMICOLON | 1122 | /// / Keyword_return Expr? SEMICOLON |
| 1110 | /// / IDENTIFIER COLON Stmt | 1123 | /// / IDENTIFIER COLON Stmt |
| 1111 | /// / ExprStmt | 1124 | /// / 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 register | 1190 | // 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 | } |
| 1255 | | 1291 | |
| 1256 | /// ExprStmt <- Expr? SEMICOLON | 1292 | /// 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 | } |