| ... | @@ -410,10 +410,16 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No | ... | @@ -410,10 +410,16 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No |
| 410 | var align_expr: ?*Node = null; | 410 | var align_expr: ?*Node = null; |
| 411 | var type_expr: ?*Node = null; | 411 | var type_expr: ?*Node = null; |
| 412 | if (eatToken(it, .Colon)) |_| { | 412 | if (eatToken(it, .Colon)) |_| { |
| 413 | type_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{ | 413 | if (eatToken(it, .Keyword_var)) |var_tok| { |
| 414 | .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index }, | 414 | const node = try arena.create(ast.Node.VarType); |
| 415 | }); | 415 | node.* = .{ .token = var_tok }; |
| 416 | align_expr = try parseByteAlign(arena, it, tree); | 416 | type_expr = &node.base; |
| | 417 | } else { |
| | 418 | type_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{ |
| | 419 | .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index }, |
| | 420 | }); |
| | 421 | align_expr = try parseByteAlign(arena, it, tree); |
| | 422 | } |
| 417 | } | 423 | } |
| 418 | | 424 | |
| 419 | const value_expr = if (eatToken(it, .Equal)) |_| | 425 | const value_expr = if (eatToken(it, .Equal)) |_| |
| ... | @@ -576,7 +582,8 @@ fn parseIfStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node | ... | @@ -576,7 +582,8 @@ fn parseIfStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node |
| 576 | | 582 | |
| 577 | /// LabeledStatement <- BlockLabel? (Block / LoopStatement) | 583 | /// LabeledStatement <- BlockLabel? (Block / LoopStatement) |
| 578 | fn parseLabeledStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { | 584 | fn parseLabeledStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 579 | const label_token = parseBlockLabel(arena, it, tree); | 585 | var colon: TokenIndex = undefined; |
| | 586 | const label_token = parseBlockLabel(arena, it, tree, &colon); |
| 580 | | 587 | |
| 581 | if (try parseBlock(arena, it, tree)) |node| { | 588 | if (try parseBlock(arena, it, tree)) |node| { |
| 582 | node.cast(Node.Block).?.label = label_token; | 589 | node.cast(Node.Block).?.label = label_token; |
| ... | @@ -757,7 +764,8 @@ fn parseBlockExprStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) ! | ... | @@ -757,7 +764,8 @@ fn parseBlockExprStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) ! |
| 757 | | 764 | |
| 758 | /// BlockExpr <- BlockLabel? Block | 765 | /// BlockExpr <- BlockLabel? Block |
| 759 | fn parseBlockExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*Node { | 766 | fn parseBlockExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*Node { |
| 760 | const label_token = parseBlockLabel(arena, it, tree); | 767 | var colon: TokenIndex = undefined; |
| | 768 | const label_token = parseBlockLabel(arena, it, tree, &colon); |
| 761 | const block_node = (try parseBlock(arena, it, tree)) orelse { | 769 | const block_node = (try parseBlock(arena, it, tree)) orelse { |
| 762 | if (label_token) |label| { | 770 | if (label_token) |label| { |
| 763 | putBackToken(it, label + 1); // ":" | 771 | putBackToken(it, label + 1); // ":" |
| ... | @@ -913,7 +921,8 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node | ... | @@ -913,7 +921,8 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node |
| 913 | return &node.base; | 921 | return &node.base; |
| 914 | } | 922 | } |
| 915 | | 923 | |
| 916 | const label = parseBlockLabel(arena, it, tree); | 924 | var colon: TokenIndex = undefined; |
| | 925 | const label = parseBlockLabel(arena, it, tree, &colon); |
| 917 | if (try parseLoopExpr(arena, it, tree)) |node| { | 926 | if (try parseLoopExpr(arena, it, tree)) |node| { |
| 918 | if (node.cast(Node.For)) |for_node| { | 927 | if (node.cast(Node.For)) |for_node| { |
| 919 | for_node.label = label; | 928 | for_node.label = label; |
| ... | @@ -1354,7 +1363,8 @@ fn parseIfTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { | ... | @@ -1354,7 +1363,8 @@ fn parseIfTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 1354 | /// <- BlockLabel Block | 1363 | /// <- BlockLabel Block |
| 1355 | /// / BlockLabel? LoopTypeExpr | 1364 | /// / BlockLabel? LoopTypeExpr |
| 1356 | fn parseLabeledTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { | 1365 | fn parseLabeledTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 1357 | const label = parseBlockLabel(arena, it, tree); | 1366 | var colon: TokenIndex = undefined; |
| | 1367 | const label = parseBlockLabel(arena, it, tree, &colon); |
| 1358 | | 1368 | |
| 1359 | if (label) |token| { | 1369 | if (label) |token| { |
| 1360 | if (try parseBlock(arena, it, tree)) |node| { | 1370 | if (try parseBlock(arena, it, tree)) |node| { |
| ... | @@ -1372,12 +1382,9 @@ fn parseLabeledTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N | ... | @@ -1372,12 +1382,9 @@ fn parseLabeledTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N |
| 1372 | return node; | 1382 | return node; |
| 1373 | } | 1383 | } |
| 1374 | | 1384 | |
| 1375 | if (label != null) { | 1385 | if (label) |token| { |
| 1376 | // If we saw a label, there should have been a block next | 1386 | putBackToken(it, colon); |
| 1377 | try tree.errors.push(AstError{ | 1387 | putBackToken(it, token); |
| 1378 | .ExpectedLBrace = AstError.ExpectedLBrace{ .token = it.index }, | | |
| 1379 | }); | | |
| 1380 | return error.ParseError; | | |
| 1381 | } | 1388 | } |
| 1382 | return null; | 1389 | return null; |
| 1383 | } | 1390 | } |
| ... | @@ -1641,9 +1648,12 @@ fn parseBreakLabel(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { | ... | @@ -1641,9 +1648,12 @@ fn parseBreakLabel(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 1641 | } | 1648 | } |
| 1642 | | 1649 | |
| 1643 | /// BlockLabel <- IDENTIFIER COLON | 1650 | /// BlockLabel <- IDENTIFIER COLON |
| 1644 | fn parseBlockLabel(arena: *Allocator, it: *TokenIterator, tree: *Tree) ?TokenIndex { | 1651 | fn parseBlockLabel(arena: *Allocator, it: *TokenIterator, tree: *Tree, colon_token: *TokenIndex) ?TokenIndex { |
| 1645 | const identifier = eatToken(it, .Identifier) orelse return null; | 1652 | const identifier = eatToken(it, .Identifier) orelse return null; |
| 1646 | if (eatToken(it, .Colon) != null) return identifier; | 1653 | if (eatToken(it, .Colon)) |colon| { |
| | 1654 | colon_token.* = colon; |
| | 1655 | return identifier; |
| | 1656 | } |
| 1647 | putBackToken(it, identifier); | 1657 | putBackToken(it, identifier); |
| 1648 | return null; | 1658 | return null; |
| 1649 | } | 1659 | } |