authorchloe caruso <git@paperclover.net> 2024-09-16 03:32:36-04:00
committerchloe caruso <git@paperclover.net> 2024-09-16 03:32:36-04:00
loga1c102b80d39c733eec219da352304c4eff8ab8e
treec43a78270e72b95b5d2eb7bf627e392482a4966e
parent67e9829ce50923b93235b8afc60467dc22e9d548

feat: implement multiline string literals


4 files changed, 55 insertions(+), 0 deletions(-)

CHANGELOG.md+1
......@@ -12,6 +12,7 @@
1212- feat: rename `noreturn` to `never`
1313- feat: allow instantiating `@extern` at compile time
1414- feat: implement tuples
15- feat: implement multiline string literals
1516- fix: crash when printing unused struct declaration error
1617- fix: provide array result type to sema
1718- fix: crash when analyzing an empty array without a result type
src/core/Parse.zig+18
......@@ -819,6 +819,7 @@ fn isExpressionStart(p: *Parse) bool {
819819 .kw_fn,
820820 .kw_struct,
821821 .kw_tuple,
822 .multiline_string,
822823 => true,
823824 else => false,
824825 };
......@@ -877,6 +878,7 @@ fn parseExpressionPart(p: *Parse, mode: ParseExprMode) Error!NodeIndex {
877878 .number_int => try p.blankNode(.number_int),
878879 .number_float => try p.blankNode(.number_float),
879880 .string => try p.blankNode(.string),
881 .multiline_string => try p.parseMultilineString(),
880882
881883 .builtin_id => try p.parseBuiltinCall(),
882884 .dot => try p.parseAnonStructInit(),
......@@ -1320,6 +1322,22 @@ fn parseTupleType(p: *Parse) Error!NodeIndex {
13201322 });
13211323}
13221324
1325fn parseMultilineString(p: *Parse) !NodeIndex {
1326 const start = p.assertToken(.multiline_string);
1327
1328 while (p.eatToken(.multiline_string) != null) {}
1329
1330 const len = p.pos - start;
1331 return p.addNode(.{
1332 .tag = .multiline_string,
1333 .main_token = start,
1334 .data = .{ .list = .{
1335 .start = start,
1336 .len = len,
1337 } },
1338 });
1339}
1340
13231341// helpers
13241342
13251343/// Append a node and return its index.
src/core/Transform.zig+22
......@@ -1620,6 +1620,28 @@ fn transformExpression(
16201620 });
16211621 },
16221622
1623 .multiline_string => {
1624 const token_list = t.ast.nodeData(node).list;
1625
1626 assert(t.id_decode_buf.items.len == 0);
1627 defer t.id_decode_buf.clearRetainingCapacity();
1628
1629 try t.id_decode_buf.appendSlice(t.ast.tokenSlice(token_list.start)[2..]);
1630 for (token_list.start + 1..token_list.start + token_list.len) |i| {
1631 try t.id_decode_buf.append('\n');
1632 try t.id_decode_buf.appendSlice(t.ast.tokenSlice(@intCast(i))[2..]);
1633 }
1634
1635 return try t.addRef(.string, .{
1636 .src_node = ctx.nodeOffset(node),
1637 .extra_index = try t.extra.append(
1638 t.gpa,
1639 SlicedString,
1640 try t.addSlicedString(t.id_decode_buf.items),
1641 ),
1642 });
1643 },
1644
16231645 else => |tag| std.debug.panic("TODO: expr {s}", .{@tagName(tag)}),
16241646 }
16251647}
test/behavior/string created+14
......@@ -0,0 +1,14 @@
1let assertEqual = @extern("assertEqual");
2
3fn main {
4 assertEqual(
5 \\hello world
6 \\etc
7 \\
8 , "hello world\netc\n"
9 );
10 assertEqual(
11 \\language compiler
12 , "language compiler"
13 );
14}