| ... | @@ -122,7 +122,7 @@ fn addExtra(p: *Parse, extra: anytype) Allocator.Error!ExtraIndex { | ... | @@ -122,7 +122,7 @@ fn addExtra(p: *Parse, extra: anytype) Allocator.Error!ExtraIndex { |
| 122 | return result; | 122 | return result; |
| 123 | } | 123 | } |
| 124 | | 124 | |
| 125 | fn warnExpected(p: *Parse, expected_token: Token.Tag) error{OutOfMemory}!void { | 125 | fn warnExpected(p: *Parse, expected_token: Token.Tag) Error!void { |
| 126 | @branchHint(.cold); | 126 | @branchHint(.cold); |
| 127 | try p.warnMsg(.{ | 127 | try p.warnMsg(.{ |
| 128 | .tag = .expected_token, | 128 | .tag = .expected_token, |
| ... | @@ -131,12 +131,12 @@ fn warnExpected(p: *Parse, expected_token: Token.Tag) error{OutOfMemory}!void { | ... | @@ -131,12 +131,12 @@ fn warnExpected(p: *Parse, expected_token: Token.Tag) error{OutOfMemory}!void { |
| 131 | }); | 131 | }); |
| 132 | } | 132 | } |
| 133 | | 133 | |
| 134 | fn warn(p: *Parse, error_tag: AstError.Tag) error{OutOfMemory}!void { | 134 | fn warn(p: *Parse, error_tag: AstError.Tag) Error!void { |
| 135 | @branchHint(.cold); | 135 | @branchHint(.cold); |
| 136 | try p.warnMsg(.{ .tag = error_tag, .token = p.tok_i }); | 136 | try p.warnMsg(.{ .tag = error_tag, .token = p.tok_i }); |
| 137 | } | 137 | } |
| 138 | | 138 | |
| 139 | fn warnMsg(p: *Parse, msg: Ast.Error) error{OutOfMemory}!void { | 139 | fn warnMsg(p: *Parse, msg: Ast.Error) Error!void { |
| 140 | @branchHint(.cold); | 140 | @branchHint(.cold); |
| 141 | switch (msg.tag) { | 141 | switch (msg.tag) { |
| 142 | .expected_semi_after_decl, | 142 | .expected_semi_after_decl, |
| ... | @@ -175,11 +175,13 @@ fn warnMsg(p: *Parse, msg: Ast.Error) error{OutOfMemory}!void { | ... | @@ -175,11 +175,13 @@ fn warnMsg(p: *Parse, msg: Ast.Error) error{OutOfMemory}!void { |
| 175 | var copy = msg; | 175 | var copy = msg; |
| 176 | copy.token_is_prev = true; | 176 | copy.token_is_prev = true; |
| 177 | copy.token -= 1; | 177 | copy.token -= 1; |
| 178 | return p.errors.append(p.gpa, copy); | 178 | try p.errors.append(p.gpa, copy); |
| | 179 | } else { |
| | 180 | try p.errors.append(p.gpa, msg); |
| 179 | }, | 181 | }, |
| 180 | else => {}, | 182 | else => try p.errors.append(p.gpa, msg), |
| 181 | } | 183 | } |
| 182 | try p.errors.append(p.gpa, msg); | 184 | if (!p.recover) return error.ParseError; |
| 183 | } | 185 | } |
| 184 | | 186 | |
| 185 | fn fail(p: *Parse, tag: Ast.Error.Tag) error{ ParseError, OutOfMemory } { | 187 | fn fail(p: *Parse, tag: Ast.Error.Tag) error{ ParseError, OutOfMemory } { |
| ... | @@ -203,17 +205,29 @@ fn failMsg(p: *Parse, msg: Ast.Error) error{ ParseError, OutOfMemory } { | ... | @@ -203,17 +205,29 @@ fn failMsg(p: *Parse, msg: Ast.Error) error{ ParseError, OutOfMemory } { |
| 203 | } | 205 | } |
| 204 | | 206 | |
| 205 | /// Root <- skip ContainerMembers eof | 207 | /// Root <- skip ContainerMembers eof |
| 206 | pub fn parseRoot(p: *Parse) !void { | 208 | pub fn parseRoot(p: *Parse) Allocator.Error!void { |
| 207 | // Root node must be index 0. | 209 | // Root node must be index 0. |
| 208 | p.nodes.appendAssumeCapacity(.{ | 210 | p.nodes.appendAssumeCapacity(.{ |
| 209 | .tag = .root, | 211 | .tag = .root, |
| 210 | .main_token = 0, | 212 | .main_token = 0, |
| 211 | .data = undefined, | 213 | .data = undefined, |
| 212 | }); | 214 | }); |
| 213 | const root_members = try p.parseContainerMembers(); | 215 | const root_members = p.parseContainerMembers() catch |err| switch (err) { |
| | 216 | error.OutOfMemory => |e| return e, |
| | 217 | error.ParseError => { |
| | 218 | assert(p.errors.items.len > 0); |
| | 219 | return; |
| | 220 | }, |
| | 221 | }; |
| 214 | const root_decls = try root_members.toSpan(p); | 222 | const root_decls = try root_members.toSpan(p); |
| 215 | if (p.tokenTag(p.tok_i) != .eof) { | 223 | if (p.tokenTag(p.tok_i) != .eof) { |
| 216 | try p.warnExpected(.eof); | 224 | p.warnExpected(.eof) catch |err| switch (err) { |
| | 225 | error.OutOfMemory => |e| return e, |
| | 226 | error.ParseError => { |
| | 227 | assert(p.errors.items.len > 0); |
| | 228 | return; |
| | 229 | }, |
| | 230 | }; |
| 217 | } | 231 | } |
| 218 | p.nodes.items(.data)[0] = .{ .extra_range = root_decls }; | 232 | p.nodes.items(.data)[0] = .{ .extra_range = root_decls }; |
| 219 | } | 233 | } |
| ... | @@ -221,7 +235,7 @@ pub fn parseRoot(p: *Parse) !void { | ... | @@ -221,7 +235,7 @@ pub fn parseRoot(p: *Parse) !void { |
| 221 | /// Parse in ZON mode. Subset of the language. | 235 | /// Parse in ZON mode. Subset of the language. |
| 222 | /// TODO: set a flag in Parse struct, and honor that flag | 236 | /// TODO: set a flag in Parse struct, and honor that flag |
| 223 | /// by emitting compilation errors when non-zon nodes are encountered. | 237 | /// by emitting compilation errors when non-zon nodes are encountered. |
| 224 | pub fn parseZon(p: *Parse) !void { | 238 | pub fn parseZon(p: *Parse) Allocator.Error!void { |
| 225 | // We must use index 0 so that 0 can be used as null elsewhere. | 239 | // We must use index 0 so that 0 can be used as null elsewhere. |
| 226 | p.nodes.appendAssumeCapacity(.{ | 240 | p.nodes.appendAssumeCapacity(.{ |
| 227 | .tag = .root, | 241 | .tag = .root, |
| ... | @@ -236,7 +250,13 @@ pub fn parseZon(p: *Parse) !void { | ... | @@ -236,7 +250,13 @@ pub fn parseZon(p: *Parse) !void { |
| 236 | else => |e| return e, | 250 | else => |e| return e, |
| 237 | }; | 251 | }; |
| 238 | if (p.tokenTag(p.tok_i) != .eof) { | 252 | if (p.tokenTag(p.tok_i) != .eof) { |
| 239 | try p.warnExpected(.eof); | 253 | p.warnExpected(.eof) catch |err| switch (err) { |
| | 254 | error.OutOfMemory => |e| return e, |
| | 255 | error.ParseError => { |
| | 256 | assert(p.errors.items.len > 0); |
| | 257 | return; |
| | 258 | }, |
| | 259 | }; |
| 240 | } | 260 | } |
| 241 | p.nodes.items(.data)[0] = .{ .node = node_index }; | 261 | p.nodes.items(.data)[0] = .{ .node = node_index }; |
| 242 | } | 262 | } |
| ... | @@ -246,7 +266,7 @@ pub fn parseZon(p: *Parse) !void { | ... | @@ -246,7 +266,7 @@ pub fn parseZon(p: *Parse) !void { |
| 246 | /// ContainerDeclaration <- TestDecl / ComptimeDecl / doc_comment? KEYWORD_pub? Decl | 266 | /// ContainerDeclaration <- TestDecl / ComptimeDecl / doc_comment? KEYWORD_pub? Decl |
| 247 | /// | 267 | /// |
| 248 | /// ComptimeDecl <- KEYWORD_comptime Block | 268 | /// ComptimeDecl <- KEYWORD_comptime Block |
| 249 | fn parseContainerMembers(p: *Parse) Allocator.Error!Members { | 269 | fn parseContainerMembers(p: *Parse) Error!Members { |
| 250 | const scratch_top = p.scratch.items.len; | 270 | const scratch_top = p.scratch.items.len; |
| 251 | defer p.scratch.shrinkRetainingCapacity(scratch_top); | 271 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 252 | | 272 | |
| ... | @@ -3582,7 +3602,7 @@ fn expectFor(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) ! | ... | @@ -3582,7 +3602,7 @@ fn expectFor(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) ! |
| 3582 | } | 3602 | } |
| 3583 | | 3603 | |
| 3584 | /// Skips over doc comment tokens. Returns the first one, if any. | 3604 | /// Skips over doc comment tokens. Returns the first one, if any. |
| 3585 | fn eatDocComments(p: *Parse) Allocator.Error!?TokenIndex { | 3605 | fn eatDocComments(p: *Parse) Error!?TokenIndex { |
| 3586 | if (p.eatToken(.doc_comment)) |tok| { | 3606 | if (p.eatToken(.doc_comment)) |tok| { |
| 3587 | var first_line = tok; | 3607 | var first_line = tok; |
| 3588 | if (tok > 0 and tokensOnSameLine(p, tok - 1, tok)) { | 3608 | if (tok > 0 and tokensOnSameLine(p, tok - 1, tok)) { |