From 581369c0836591a07b9b84b54042368db4d00cd5 Mon Sep 17 00:00:00 2001 From: dave caruso Date: Mon, 16 Sep 2024 03:32:36 -0400 Subject: [PATCH] feat: implement multiline string literals --- CHANGELOG.md | 1 + src/core/Parse.zig | 18 ++++++++++++++++++ src/core/Transform.zig | 22 ++++++++++++++++++++++ test/behavior/string | 14 ++++++++++++++ 4 files changed, 55 insertions(+) create mode 100644 test/behavior/string diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fd3a46010f6e891a8b671348cce1db15e4084c6..40108791e1dda71a087b2605b09cf94cdebcfafe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - feat: rename `noreturn` to `never` - feat: allow instantiating `@extern` at compile time - feat: implement tuples +- feat: implement multiline string literals - fix: crash when printing unused struct declaration error - fix: provide array result type to sema - fix: crash when analyzing an empty array without a result type diff --git a/src/core/Parse.zig b/src/core/Parse.zig index 120626eac16464a5bea13eff869cf72a4757c3d0..64e69aea245518ba9812947cd904e9e7882af9f3 100644 --- a/src/core/Parse.zig +++ b/src/core/Parse.zig @@ -819,6 +819,7 @@ fn isExpressionStart(p: *Parse) bool { .kw_fn, .kw_struct, .kw_tuple, + .multiline_string, => true, else => false, }; @@ -877,6 +878,7 @@ fn parseExpressionPart(p: *Parse, mode: ParseExprMode) Error!NodeIndex { .number_int => try p.blankNode(.number_int), .number_float => try p.blankNode(.number_float), .string => try p.blankNode(.string), + .multiline_string => try p.parseMultilineString(), .builtin_id => try p.parseBuiltinCall(), .dot => try p.parseAnonStructInit(), @@ -1320,6 +1322,22 @@ fn parseTupleType(p: *Parse) Error!NodeIndex { }); } +fn parseMultilineString(p: *Parse) !NodeIndex { + const start = p.assertToken(.multiline_string); + + while (p.eatToken(.multiline_string) != null) {} + + const len = p.pos - start; + return p.addNode(.{ + .tag = .multiline_string, + .main_token = start, + .data = .{ .list = .{ + .start = start, + .len = len, + } }, + }); +} + // helpers /// Append a node and return its index. diff --git a/src/core/Transform.zig b/src/core/Transform.zig index 4db0d59b9feab0f6da84f31d2a72b20038ada801..cbd8e9b1bae291405216f520e8c9b12e990fbb45 100644 --- a/src/core/Transform.zig +++ b/src/core/Transform.zig @@ -1620,6 +1620,28 @@ fn transformExpression( }); }, + .multiline_string => { + const token_list = t.ast.nodeData(node).list; + + assert(t.id_decode_buf.items.len == 0); + defer t.id_decode_buf.clearRetainingCapacity(); + + try t.id_decode_buf.appendSlice(t.ast.tokenSlice(token_list.start)[2..]); + for (token_list.start + 1..token_list.start + token_list.len) |i| { + try t.id_decode_buf.append('\n'); + try t.id_decode_buf.appendSlice(t.ast.tokenSlice(@intCast(i))[2..]); + } + + return try t.addRef(.string, .{ + .src_node = ctx.nodeOffset(node), + .extra_index = try t.extra.append( + t.gpa, + SlicedString, + try t.addSlicedString(t.id_decode_buf.items), + ), + }); + }, + else => |tag| std.debug.panic("TODO: expr {s}", .{@tagName(tag)}), } } diff --git a/test/behavior/string b/test/behavior/string new file mode 100644 index 0000000000000000000000000000000000000000..47fd2cea504cddc346094e766e0256c585f9fd79 --- /dev/null +++ b/test/behavior/string @@ -0,0 +1,14 @@ +let assertEqual = @extern("assertEqual"); + +fn main { + assertEqual( + \\hello world + \\etc + \\ + , "hello world\netc\n" + ); + assertEqual( + \\language compiler + , "language compiler" + ); +} -- 2.54.0