| ... | ... | @@ -75,9 +75,12 @@ pub fn parse(allocator: *Allocator, source: []const u8, options: Options) !*Tree |
| 75 | 75 | } |
| 76 | 76 | } |
| 77 | 77 | |
| 78 | var parse_arena = std.heap.ArenaAllocator.init(allocator); |
| 79 | defer parse_arena.deinit(); |
| 80 | |
| 78 | 81 | var parser = Parser{ |
| 79 | | .symbols = Parser.SymbolList.init(allocator), |
| 80 | | .arena = arena, |
| 82 | .scopes = Parser.SymbolList.init(allocator), |
| 83 | .arena = &parse_arena.allocator, |
| 81 | 84 | .it = &it, |
| 82 | 85 | .tree = tree, |
| 83 | 86 | .options = options, |
| ... | ... | @@ -93,11 +96,17 @@ const Parser = struct { |
| 93 | 96 | it: *TokenIterator, |
| 94 | 97 | tree: *Tree, |
| 95 | 98 | |
| 96 | | /// only used for scopes |
| 97 | | symbols: SymbolList, |
| 99 | arena: *Allocator, |
| 100 | scopes: ScopeList, |
| 98 | 101 | options: Options, |
| 99 | 102 | |
| 100 | | const SymbolList = std.ArrayList(Symbol); |
| 103 | const ScopeList = std.SegmentedLists(Scope); |
| 104 | const SymbolList = std.SegmentedLists(Symbol); |
| 105 | |
| 106 | const Scope = struct { |
| 107 | kind: ScopeKind, |
| 108 | syms: SymbolList, |
| 109 | }; |
| 101 | 110 | |
| 102 | 111 | const Symbol = struct { |
| 103 | 112 | name: []const u8, |
| ... | ... | @@ -111,21 +120,27 @@ const Parser = struct { |
| 111 | 120 | Switch, |
| 112 | 121 | }; |
| 113 | 122 | |
| 114 | | fn pushScope(parser: *Parser, kind: ScopeKind) usize { |
| 115 | | return parser.symbols.len; |
| 123 | fn pushScope(parser: *Parser, kind: ScopeKind) !void { |
| 124 | const new = try parser.scopes.addOne(); |
| 125 | new.* = .{ |
| 126 | .kind = kind, |
| 127 | .syms = SymbolList.init(parser.arena), |
| 128 | }; |
| 116 | 129 | } |
| 117 | 130 | |
| 118 | 131 | fn popScope(parser: *Parser, len: usize) void { |
| 119 | | parser.symbols.resize(len) catch unreachable; |
| 132 | _ = parser.scopes.pop(); |
| 120 | 133 | } |
| 121 | 134 | |
| 122 | | fn getSymbol(parser: *Parser, tok: TokenIndex) ?*Type { |
| 135 | fn getSymbol(parser: *Parser, tok: TokenIndex) ?*Symbol { |
| 123 | 136 | const name = parser.tree.tokenSlice(tok); |
| 124 | | const syms = parser.symbols.toSliceConst(); |
| 125 | | var i = syms.len; |
| 126 | | while (i > 0) : (i -= 1) { |
| 127 | | if (mem.eql(u8, name, syms[i].name)) { |
| 128 | | return syms[i].ty; |
| 137 | var scope_it = parser.scopes.iterator(parser.scopes.len); |
| 138 | while (scope_it.prev()) |scope| { |
| 139 | var sym_it = scope.syms.iterator(scope.syms.len); |
| 140 | while (sym_it.prev()) |sym| { |
| 141 | if (mem.eql(u8, sym.name, name)) { |
| 142 | return sym; |
| 143 | } |
| 129 | 144 | } |
| 130 | 145 | } |
| 131 | 146 | return null; |
| ... | ... | @@ -137,8 +152,8 @@ const Parser = struct { |
| 137 | 152 | |
| 138 | 153 | /// Root <- ExternalDeclaration* eof |
| 139 | 154 | fn root(parser: *Parser) Allocator.Error!*Node.Root { |
| 140 | | const scope = parser.pushScope(.Root); |
| 141 | | defer parser.popScope(scope); |
| 155 | try parser.pushScope(.Root); |
| 156 | defer parser.popScope(); |
| 142 | 157 | const node = try parser.arena.create(Node.Root); |
| 143 | 158 | node.* = .{ |
| 144 | 159 | .decls = Node.Root.DeclList.init(parser.arena), |
| ... | ... | @@ -782,8 +797,8 @@ const Parser = struct { |
| 782 | 797 | .ty = ty, |
| 783 | 798 | }); |
| 784 | 799 | if (parser.eatToken(.LBrace)) |lbrace| { |
| 785 | | const scope = parser.pushScope(.Block); |
| 786 | | defer parser.popScope(scope); |
| 800 | try parser.pushScope(.Block); |
| 801 | defer parser.popScope(); |
| 787 | 802 | var fields = Node.RecordType.FieldList.init(parser.arena); |
| 788 | 803 | while (true) { |
| 789 | 804 | if (parser.eatToken(.RBrace)) |rbrace| { |
| ... | ... | @@ -996,15 +1011,14 @@ const Parser = struct { |
| 996 | 1011 | fn assignmentExpr(parser: *Parser) !*Node {} |
| 997 | 1012 | |
| 998 | 1013 | /// ConstExpr <- ConditionalExpr |
| 999 | | fn constExpr(parser: *Parser) Error!*Node { |
| 1014 | fn constExpr(parser: *Parser) Error!?*Expr { |
| 1000 | 1015 | const start = parser.it.index; |
| 1001 | 1016 | const expression = try parser.conditionalExpr(); |
| 1002 | | // TODO |
| 1003 | | // if (expression == nullor expression.?.value == null) |
| 1004 | | // return parser.err(.{ |
| 1005 | | // .ConsExpr = start, |
| 1006 | | // }); |
| 1007 | | return expression.?; |
| 1017 | if (expression != null and expression.?.value == .None) |
| 1018 | return parser.err(.{ |
| 1019 | .ConsExpr = start, |
| 1020 | }); |
| 1021 | return expression; |
| 1008 | 1022 | } |
| 1009 | 1023 | |
| 1010 | 1024 | /// ConditionalExpr <- LogicalOrExpr (QUESTIONMARK Expr COLON ConditionalExpr)? |
| ... | ... | @@ -1085,8 +1099,8 @@ const Parser = struct { |
| 1085 | 1099 | /// CompoundStmt <- LBRACE (Declaration / Stmt)* RBRACE |
| 1086 | 1100 | fn compoundStmt(parser: *Parser) Error!?*Node { |
| 1087 | 1101 | const lbrace = parser.eatToken(.LBrace) orelse return null; |
| 1088 | | const scope = parser.pushScope(.Block); |
| 1089 | | defer parser.popScope(scope); |
| 1102 | try parser.pushScope(.Block); |
| 1103 | defer parser.popScope(); |
| 1090 | 1104 | const body_node = try parser.arena.create(Node.CompoundStmt); |
| 1091 | 1105 | body_node.* = .{ |
| 1092 | 1106 | .lbrace = lbrace, |
| ... | ... | @@ -1142,8 +1156,8 @@ const Parser = struct { |
| 1142 | 1156 | return &node.base; |
| 1143 | 1157 | } |
| 1144 | 1158 | if (parser.eatToken(.Keyword_while)) |tok| { |
| 1145 | | const scope = parser.pushScope(.Loop); |
| 1146 | | defer parser.popScope(scope); |
| 1159 | try parser.pushScope(.Loop); |
| 1160 | defer parser.popScope(); |
| 1147 | 1161 | _ = try parser.expectToken(.LParen); |
| 1148 | 1162 | const cond = (try parser.expr()) orelse return parser.err(.{ |
| 1149 | 1163 | .ExpectedExpr = .{ .token = parser.it.index }, |
| ... | ... | @@ -1160,8 +1174,8 @@ const Parser = struct { |
| 1160 | 1174 | return &node.base; |
| 1161 | 1175 | } |
| 1162 | 1176 | if (parser.eatToken(.Keyword_do)) |tok| { |
| 1163 | | const scope = parser.pushScope(.Loop); |
| 1164 | | defer parser.popScope(scope); |
| 1177 | try parser.pushScope(.Loop); |
| 1178 | defer parser.popScope(); |
| 1165 | 1179 | const body = try parser.stmt(); |
| 1166 | 1180 | _ = try parser.expectToken(.LParen); |
| 1167 | 1181 | const cond = (try parser.expr()) orelse return parser.err(.{ |
| ... | ... | @@ -1179,8 +1193,8 @@ const Parser = struct { |
| 1179 | 1193 | return &node.base; |
| 1180 | 1194 | } |
| 1181 | 1195 | if (parser.eatToken(.Keyword_for)) |tok| { |
| 1182 | | const scope = parser.pushScope(.Loop); |
| 1183 | | defer parser.popScope(scope); |
| 1196 | try parser.pushScope(.Loop); |
| 1197 | defer parser.popScope(); |
| 1184 | 1198 | _ = try parser.expectToken(.LParen); |
| 1185 | 1199 | const init = if (try parser.declaration()) |decl| blk:{ |
| 1186 | 1200 | // TODO disallow storage class other than auto and register |
| ... | ... | @@ -1203,8 +1217,8 @@ const Parser = struct { |
| 1203 | 1217 | return &node.base; |
| 1204 | 1218 | } |
| 1205 | 1219 | if (parser.eatToken(.Keyword_switch)) |tok| { |
| 1206 | | const scope = parser.pushScope(.Switch); |
| 1207 | | defer parser.popScope(scope); |
| 1220 | try parser.pushScope(.Switch); |
| 1221 | defer parser.popScope(); |
| 1208 | 1222 | _ = try parser.expectToken(.LParen); |
| 1209 | 1223 | const switch_expr = try parser.exprStmt(); |
| 1210 | 1224 | const rparen = try parser.expectToken(.RParen); |