authorgravatar for fncontroloption@noreply.codeberg.orgFnControlOption <fncontroloption@noreply.codeberg.org> 2021-10-04 15:46:55-07:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-01-17 17:16:48+02:00
logd46973ee4fc2a2eff5b5e0ef78368419546ee6f9
tree86a3354a3fb9dbeae945cea375972dcc9b1f3c85
parent4a92f42ed755a1c30ef2aa3842b7efe7e5725e17

translate-c: improve error messages when expecting specific tokens

Old: unable to translate C expr: expected ')' New: unable to translate C expr: expected ')' instead got '...'

2 files changed, 41 insertions(+), 71 deletions(-)

src/translate_c.zig+40-70
......@@ -5281,6 +5281,18 @@ const MacroCtx = struct {
52815281 return self.list[self.i].id;
52825282 }
52835283
5284 fn skip(self: *MacroCtx, c: *Context, expected_id: std.meta.Tag(CToken.Id)) ParseError!void {
5285 const next_id = self.next().?;
5286 if (next_id != expected_id) {
5287 try self.fail(
5288 c,
5289 "unable to translate C expr: expected '{s}' instead got '{s}'",
5290 .{ CToken.Id.symbol(expected_id), next_id.symbol() },
5291 );
5292 return error.ParseError;
5293 }
5294 }
5295
52845296 fn slice(self: *MacroCtx) []const u8 {
52855297 const tok = self.list[self.i];
52865298 return self.source[tok.start..tok.end];
......@@ -5418,7 +5430,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void {
54185430 const init_node = try parseCExpr(c, m, scope);
54195431 const last = m.next().?;
54205432 if (last != .Eof and last != .Nl)
5421 return m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(last)});
5433 return m.fail(c, "unable to translate C expr: unexpected token '{s}'", .{last.symbol()});
54225434
54235435 const var_decl = try Tag.pub_var_simple.create(c.arena, .{ .name = m.name, .init = init_node });
54245436 try c.global_scope.macro_table.put(m.name, var_decl);
......@@ -5439,9 +5451,7 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
54395451 defer block_scope.deinit();
54405452 const scope = &block_scope.base;
54415453
5442 if (m.next().? != .LParen) {
5443 return m.fail(c, "unable to translate C expr: expected '('", .{});
5444 }
5454 try m.skip(c, .LParen);
54455455
54465456 var fn_params = std.ArrayList(ast.Payload.Param).init(c.gpa);
54475457 defer fn_params.deinit();
......@@ -5461,9 +5471,7 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
54615471 _ = m.next();
54625472 }
54635473
5464 if (m.next().? != .RParen) {
5465 return m.fail(c, "unable to translate C expr: expected ')'", .{});
5466 }
5474 try m.skip(c, .RParen);
54675475
54685476 if (m.containsUndefinedIdentifier(scope, fn_params.items)) |ident|
54695477 return m.fail(c, "unable to translate macro: undefined identifier `{s}`", .{ident});
......@@ -5471,7 +5479,7 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
54715479 const expr = try parseCExpr(c, m, scope);
54725480 const last = m.next().?;
54735481 if (last != .Eof and last != .Nl)
5474 return m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(last)});
5482 return m.fail(c, "unable to translate C expr: unexpected token '{s}'", .{last.symbol()});
54755483
54765484 const typeof_arg = if (expr.castTag(.block)) |some| blk: {
54775485 const stmts = some.data.stmts;
......@@ -5837,11 +5845,7 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N
58375845 .LParen => {
58385846 const inner_node = try parseCExpr(c, m, scope);
58395847
5840 const next_id = m.next().?;
5841 if (next_id != .RParen) {
5842 try m.fail(c, "unable to translate C expr: expected ')' instead got: {s}", .{@tagName(next_id)});
5843 return error.ParseError;
5844 }
5848 try m.skip(c, .RParen);
58455849 return inner_node;
58465850 },
58475851 else => {
......@@ -5851,7 +5855,7 @@ fn parseCPrimaryExprInner(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!N
58515855 if (try parseCTypeName(c, m, scope, true)) |type_name| {
58525856 return type_name;
58535857 }
5854 try m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(tok)});
5858 try m.fail(c, "unable to translate C expr: unexpected token '{s}'", .{tok.symbol()});
58555859 return error.ParseError;
58565860 },
58575861 }
......@@ -5896,10 +5900,7 @@ fn parseCCondExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
58965900 _ = m.next();
58975901
58985902 const then_body = try parseCOrExpr(c, m, scope);
5899 if (m.next().? != .Colon) {
5900 try m.fail(c, "unable to translate C expr: expected ':'", .{});
5901 return error.ParseError;
5902 }
5903 try m.skip(c, .Colon);
59035904 const else_body = try parseCCondExpr(c, m, scope);
59045905 return Tag.@"if".create(c.arena, .{ .cond = node, .then = then_body, .@"else" = else_body });
59055906}
......@@ -6086,10 +6087,7 @@ fn parseCCastExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
60866087 switch (m.next().?) {
60876088 .LParen => {
60886089 if (try parseCTypeName(c, m, scope, true)) |type_name| {
6089 if (m.next().? != .RParen) {
6090 try m.fail(c, "unable to translate C expr: expected ')'", .{});
6091 return error.ParseError;
6092 }
6090 try m.skip(c, .RParen);
60936091 if (m.peek().? == .LBrace) {
60946092 // initializer list
60956093 return parseCPostfixExpr(c, m, scope, type_name);
......@@ -6141,11 +6139,7 @@ fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope, allow_
61416139 .Keyword_enum, .Keyword_struct, .Keyword_union => {
61426140 // struct Foo will be declared as struct_Foo by transRecordDecl
61436141 const slice = m.slice();
6144 const next_id = m.next().?;
6145 if (next_id != .Identifier) {
6146 try m.fail(c, "unable to translate C expr: expected Identifier instead got: {s}", .{@tagName(next_id)});
6147 return error.ParseError;
6148 }
6142 try m.skip(c, .Identifier);
61496143
61506144 const name = try std.fmt.allocPrint(c.arena, "{s}_{s}", .{ slice, m.slice() });
61516145 return try Tag.identifier.create(c.arena, name);
......@@ -6157,7 +6151,7 @@ fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope, allow_
61576151 m.i -= 1;
61586152 return null;
61596153 } else {
6160 try m.fail(c, "unable to translate C expr: unexpected token .{s}", .{@tagName(tok)});
6154 try m.fail(c, "unable to translate C expr: unexpected token '{s}'", .{tok.symbol()});
61616155 return error.ParseError;
61626156 }
61636157}
......@@ -6298,18 +6292,12 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node)
62986292 while (true) {
62996293 switch (m.next().?) {
63006294 .Period => {
6301 if (m.next().? != .Identifier) {
6302 try m.fail(c, "unable to translate C expr: expected identifier", .{});
6303 return error.ParseError;
6304 }
6295 try m.skip(c, .Identifier);
63056296
63066297 node = try Tag.field_access.create(c.arena, .{ .lhs = node, .field_name = m.slice() });
63076298 },
63086299 .Arrow => {
6309 if (m.next().? != .Identifier) {
6310 try m.fail(c, "unable to translate C expr: expected identifier", .{});
6311 return error.ParseError;
6312 }
6300 try m.skip(c, .Identifier);
63136301
63146302 const deref = try Tag.deref.create(c.arena, node);
63156303 node = try Tag.field_access.create(c.arena, .{ .lhs = deref, .field_name = m.slice() });
......@@ -6317,10 +6305,7 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node)
63176305 .LBracket => {
63186306 const index = try macroBoolToInt(c, try parseCExpr(c, m, scope));
63196307 node = try Tag.array_access.create(c.arena, .{ .lhs = node, .rhs = index });
6320 if (m.next().? != .RBracket) {
6321 try m.fail(c, "unable to translate C expr: expected ']'", .{});
6322 return error.ParseError;
6323 }
6308 try m.skip(c, .RBracket);
63246309 },
63256310 .LParen => {
63266311 if (m.peek().? == .RParen) {
......@@ -6332,11 +6317,12 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node)
63326317 while (true) {
63336318 const arg = try parseCCondExpr(c, m, scope);
63346319 try args.append(arg);
6335 switch (m.next().?) {
6320 const next_id = m.next().?;
6321 switch (next_id) {
63366322 .Comma => {},
63376323 .RParen => break,
63386324 else => {
6339 try m.fail(c, "unable to translate C expr: expected ',' or ')'", .{});
6325 try m.fail(c, "unable to translate C expr: expected ',' or ')' instead got '{s}'", .{next_id.symbol()});
63406326 return error.ParseError;
63416327 },
63426328 }
......@@ -6351,27 +6337,19 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node)
63516337 defer init_vals.deinit();
63526338
63536339 while (true) {
6354 if (m.next().? != .Period) {
6355 try m.fail(c, "unable to translate C expr: expected '.'", .{});
6356 return error.ParseError;
6357 }
6358 if (m.next().? != .Identifier) {
6359 try m.fail(c, "unable to translate C expr: expected identifier", .{});
6360 return error.ParseError;
6361 }
6340 try m.skip(c, .Period);
6341 try m.skip(c, .Identifier);
63626342 const name = m.slice();
6363 if (m.next().? != .Equal) {
6364 try m.fail(c, "unable to translate C expr: expected '='", .{});
6365 return error.ParseError;
6366 }
6343 try m.skip(c, .Equal);
63676344
63686345 const val = try parseCCondExpr(c, m, scope);
63696346 try init_vals.append(.{ .name = name, .value = val });
6370 switch (m.next().?) {
6347 const next_id = m.next().?;
6348 switch (next_id) {
63716349 .Comma => {},
63726350 .RBrace => break,
63736351 else => {
6374 try m.fail(c, "unable to translate C expr: expected ',' or '}}'", .{});
6352 try m.fail(c, "unable to translate C expr: expected ',' or '}}' instead got '{s}'", .{next_id.symbol()});
63756353 return error.ParseError;
63766354 },
63776355 }
......@@ -6387,11 +6365,12 @@ fn parseCPostfixExpr(c: *Context, m: *MacroCtx, scope: *Scope, type_name: ?Node)
63876365 while (true) {
63886366 const val = try parseCCondExpr(c, m, scope);
63896367 try init_vals.append(val);
6390 switch (m.next().?) {
6368 const next_id = m.next().?;
6369 switch (next_id) {
63916370 .Comma => {},
63926371 .RBrace => break,
63936372 else => {
6394 try m.fail(c, "unable to translate C expr: expected ',' or '}}'", .{});
6373 try m.fail(c, "unable to translate C expr: expected ',' or '}}' instead got '{s}'", .{next_id.symbol()});
63956374 return error.ParseError;
63966375 },
63976376 }
......@@ -6438,10 +6417,7 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
64386417 const operand = if (m.peek().? == .LParen) blk: {
64396418 _ = m.next();
64406419 const inner = (try parseCTypeName(c, m, scope, false)).?;
6441 if (m.next().? != .RParen) {
6442 try m.fail(c, "unable to translate C expr: expected ')'", .{});
6443 return error.ParseError;
6444 }
6420 try m.skip(c, .RParen);
64456421 break :blk inner;
64466422 } else try parseCUnaryExpr(c, m, scope);
64476423
......@@ -6450,15 +6426,9 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
64506426 .Keyword_alignof => {
64516427 // TODO this won't work if using <stdalign.h>'s
64526428 // #define alignof _Alignof
6453 if (m.next().? != .LParen) {
6454 try m.fail(c, "unable to translate C expr: expected '('", .{});
6455 return error.ParseError;
6456 }
6429 try m.skip(c, .LParen);
64576430 const operand = (try parseCTypeName(c, m, scope, false)).?;
6458 if (m.next().? != .RParen) {
6459 try m.fail(c, "unable to translate C expr: expected ')'", .{});
6460 return error.ParseError;
6461 }
6431 try m.skip(c, .RParen);
64626432
64636433 return Tag.alignof.create(c.arena, operand);
64646434 },
test/translate_c.zig+1-1
......@@ -2076,7 +2076,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
20762076 , &[_][]const u8{
20772077 \\pub export var @"anyerror": c_uint = 2;
20782078 ,
2079 \\pub const @"noreturn" = @compileError("unable to translate C expr: unexpected token .Keyword_noreturn");
2079 \\pub const @"noreturn" = @compileError("unable to translate C expr: unexpected token '_Noreturn'");
20802080 ,
20812081 \\pub const @"f32": c_int = 0;
20822082 \\pub const @"u32": c_int = 1;