| author | |
| committer | |
| log | 4d8f9e2295bb672f70550b3bb5a4cb667f68bb70 |
| tree | 434ac90b56af673e28fb1b42effb8351c595a7f2 |
| parent | 4793c3397e17169317d2feded9ca6901ff0e99e8 |
3 files changed, 108 insertions(+), 5 deletions(-)
std/zig/ast.zig+21| ... | ... | @@ -20,6 +20,7 @@ pub const Node = struct { |
| 20 | 20 | IntegerLiteral, |
| 21 | 21 | FloatLiteral, |
| 22 | 22 | StringLiteral, |
| 23 | MultilineStringLiteral, | |
| 23 | 24 | UndefinedLiteral, |
| 24 | 25 | BuiltinCall, |
| 25 | 26 | Call, |
| ... | ... | @@ -40,6 +41,7 @@ pub const Node = struct { |
| 40 | 41 | Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).iterate(index), |
| 41 | 42 | Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).iterate(index), |
| 42 | 43 | Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).iterate(index), |
| 44 | Id.MultilineStringLiteral => @fieldParentPtr(NodeMultilineStringLiteral, "base", base).iterate(index), | |
| 43 | 45 | Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).iterate(index), |
| 44 | 46 | Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index), |
| 45 | 47 | Id.Call => @fieldParentPtr(NodeCall, "base", base).iterate(index), |
| ... | ... | @@ -61,6 +63,7 @@ pub const Node = struct { |
| 61 | 63 | Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).firstToken(), |
| 62 | 64 | Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).firstToken(), |
| 63 | 65 | Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).firstToken(), |
| 66 | Id.MultilineStringLiteral => @fieldParentPtr(NodeMultilineStringLiteral, "base", base).firstToken(), | |
| 64 | 67 | Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).firstToken(), |
| 65 | 68 | Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).firstToken(), |
| 66 | 69 | Id.Call => @fieldParentPtr(NodeCall, "base", base).firstToken(), |
| ... | ... | @@ -82,6 +85,7 @@ pub const Node = struct { |
| 82 | 85 | Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).lastToken(), |
| 83 | 86 | Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).lastToken(), |
| 84 | 87 | Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).lastToken(), |
| 88 | Id.MultilineStringLiteral => @fieldParentPtr(NodeMultilineStringLiteral, "base", base).lastToken(), | |
| 85 | 89 | Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).lastToken(), |
| 86 | 90 | Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).lastToken(), |
| 87 | 91 | Id.Call => @fieldParentPtr(NodeCall, "base", base).lastToken(), |
| ... | ... | @@ -587,6 +591,23 @@ pub const NodeStringLiteral = struct { |
| 587 | 591 | } |
| 588 | 592 | }; |
| 589 | 593 | |
| 594 | pub const NodeMultilineStringLiteral = struct { | |
| 595 | base: Node, | |
| 596 | tokens: ArrayList(Token), | |
| 597 | ||
| 598 | pub fn iterate(self: &NodeMultilineStringLiteral, index: usize) ?&Node { | |
| 599 | return null; | |
| 600 | } | |
| 601 | ||
| 602 | pub fn firstToken(self: &NodeMultilineStringLiteral) Token { | |
| 603 | return self.tokens.at(0); | |
| 604 | } | |
| 605 | ||
| 606 | pub fn lastToken(self: &NodeMultilineStringLiteral) Token { | |
| 607 | return self.tokens.at(self.tokens.len - 1); | |
| 608 | } | |
| 609 | }; | |
| 610 | ||
| 590 | 611 | pub const NodeUndefinedLiteral = struct { |
| 591 | 612 | base: Node, |
| 592 | 613 | token: Token, |
std/zig/parser.zig+48-4| ... | ... | @@ -456,6 +456,30 @@ pub const Parser = struct { |
| 456 | 456 | try stack.append(State.AfterOperand); |
| 457 | 457 | continue; |
| 458 | 458 | }, |
| 459 | Token.Id.MultilineStringLiteralLine => { | |
| 460 | const node = try arena.create(ast.NodeMultilineStringLiteral); | |
| 461 | *node = ast.NodeMultilineStringLiteral { | |
| 462 | .base = self.initNode(ast.Node.Id.MultilineStringLiteral), | |
| 463 | .tokens = ArrayList(Token).init(arena), | |
| 464 | }; | |
| 465 | try node.tokens.append(token); | |
| 466 | ||
| 467 | while (true) { | |
| 468 | const multiline_str = self.getNextToken(); | |
| 469 | if (multiline_str.id != Token.Id.MultilineStringLiteralLine) { | |
| 470 | self.putBackToken(multiline_str); | |
| 471 | break; | |
| 472 | } | |
| 473 | ||
| 474 | try node.tokens.append(multiline_str); | |
| 475 | } | |
| 476 | ||
| 477 | try stack.append(State { | |
| 478 | .Operand = &node.base | |
| 479 | }); | |
| 480 | try stack.append(State.AfterOperand); | |
| 481 | continue; | |
| 482 | }, | |
| 459 | 483 | |
| 460 | 484 | else => return self.parseError(token, "expected primary expression, found {}", @tagName(token.id)), |
| 461 | 485 | } |
| ... | ... | @@ -1427,6 +1451,20 @@ pub const Parser = struct { |
| 1427 | 1451 | const string_literal = @fieldParentPtr(ast.NodeStringLiteral, "base", base); |
| 1428 | 1452 | try stream.print("{}", self.tokenizer.getTokenSlice(string_literal.token)); |
| 1429 | 1453 | }, |
| 1454 | ast.Node.Id.MultilineStringLiteral => { | |
| 1455 | const multiline_str_literal = @fieldParentPtr(ast.NodeMultilineStringLiteral, "base", base); | |
| 1456 | try stream.print("\n"); | |
| 1457 | ||
| 1458 | var i : usize = 0; | |
| 1459 | indent += 4; | |
| 1460 | while (i < multiline_str_literal.tokens.len) : (i += 1) { | |
| 1461 | const t = multiline_str_literal.tokens.at(i); | |
| 1462 | try stream.writeByteNTimes(' ', indent); | |
| 1463 | try stream.print("{}", self.tokenizer.getTokenSlice(t)); | |
| 1464 | } | |
| 1465 | try stream.writeByteNTimes(' ', indent); | |
| 1466 | indent -= 4; | |
| 1467 | }, | |
| 1430 | 1468 | ast.Node.Id.UndefinedLiteral => { |
| 1431 | 1469 | const undefined_literal = @fieldParentPtr(ast.NodeUndefinedLiteral, "base", base); |
| 1432 | 1470 | try stream.print("{}", self.tokenizer.getTokenSlice(undefined_literal.token)); |
| ... | ... | @@ -1806,6 +1844,16 @@ test "zig fmt: extern function" { |
| 1806 | 1844 | ); |
| 1807 | 1845 | } |
| 1808 | 1846 | |
| 1847 | test "zig fmt: multiline string" { | |
| 1848 | try testCanonical( | |
| 1849 | \\const s = | |
| 1850 | \\ \\ something | |
| 1851 | \\ \\ something else | |
| 1852 | \\ ; | |
| 1853 | \\ | |
| 1854 | ); | |
| 1855 | } | |
| 1856 | ||
| 1809 | 1857 | test "zig fmt: values" { |
| 1810 | 1858 | try testCanonical( |
| 1811 | 1859 | \\test "values" { |
| ... | ... | @@ -1813,10 +1861,6 @@ test "zig fmt: values" { |
| 1813 | 1861 | \\ 1.0; |
| 1814 | 1862 | \\ "string"; |
| 1815 | 1863 | \\ c"cstring"; |
| 1816 | \\ \\ Multi | |
| 1817 | \\ \\ line | |
| 1818 | \\ \\ string | |
| 1819 | \\ ; | |
| 1820 | 1864 | \\ 'c'; |
| 1821 | 1865 | \\ true; |
| 1822 | 1866 | \\ false; |
std/zig/tokenizer.zig+39-1| ... | ... | @@ -72,6 +72,7 @@ pub const Token = struct { |
| 72 | 72 | Invalid, |
| 73 | 73 | Identifier, |
| 74 | 74 | StringLiteral: StrLitKind, |
| 75 | MultilineStringLiteralLine: StrLitKind, | |
| 75 | 76 | StringIdentifier, |
| 76 | 77 | Eof, |
| 77 | 78 | Builtin, |
| ... | ... | @@ -225,6 +226,9 @@ pub const Tokenizer = struct { |
| 225 | 226 | C, |
| 226 | 227 | StringLiteral, |
| 227 | 228 | StringLiteralBackslash, |
| 229 | MultilineStringLiteralLine, | |
| 230 | MultilineStringLiteralLineBackslash, | |
| 231 | Backslash, | |
| 228 | 232 | Equal, |
| 229 | 233 | Bang, |
| 230 | 234 | Pipe, |
| ... | ... | @@ -352,6 +356,10 @@ pub const Tokenizer = struct { |
| 352 | 356 | '^' => { |
| 353 | 357 | state = State.Caret; |
| 354 | 358 | }, |
| 359 | '\\' => { | |
| 360 | state = State.Backslash; | |
| 361 | result.id = Token.Id { .MultilineStringLiteralLine = Token.StrLitKind.Normal }; | |
| 362 | }, | |
| 355 | 363 | '{' => { |
| 356 | 364 | result.id = Token.Id.LBrace; |
| 357 | 365 | self.index += 1; |
| ... | ... | @@ -532,8 +540,17 @@ pub const Tokenizer = struct { |
| 532 | 540 | 'a'...'z', 'A'...'Z', '_', '0'...'9' => {}, |
| 533 | 541 | else => break, |
| 534 | 542 | }, |
| 543 | State.Backslash => switch (c) { | |
| 544 | '\\' => { | |
| 545 | state = State.MultilineStringLiteralLine; | |
| 546 | }, | |
| 547 | else => break, | |
| 548 | }, | |
| 535 | 549 | State.C => switch (c) { |
| 536 | '\\' => @panic("TODO"), | |
| 550 | '\\' => { | |
| 551 | state = State.Backslash; | |
| 552 | result.id = Token.Id { .MultilineStringLiteralLine = Token.StrLitKind.C }; | |
| 553 | }, | |
| 537 | 554 | '"' => { |
| 538 | 555 | state = State.StringLiteral; |
| 539 | 556 | result.id = Token.Id { .StringLiteral = Token.StrLitKind.C }; |
| ... | ... | @@ -562,6 +579,24 @@ pub const Tokenizer = struct { |
| 562 | 579 | }, |
| 563 | 580 | }, |
| 564 | 581 | |
| 582 | State.MultilineStringLiteralLine => switch (c) { | |
| 583 | '\\' => { | |
| 584 | state = State.MultilineStringLiteralLineBackslash; | |
| 585 | }, | |
| 586 | '\n' => { | |
| 587 | self.index += 1; | |
| 588 | break; | |
| 589 | }, | |
| 590 | else => self.checkLiteralCharacter(), | |
| 591 | }, | |
| 592 | ||
| 593 | State.MultilineStringLiteralLineBackslash => switch (c) { | |
| 594 | '\n' => break, // Look for this error later. | |
| 595 | else => { | |
| 596 | state = State.MultilineStringLiteralLine; | |
| 597 | }, | |
| 598 | }, | |
| 599 | ||
| 565 | 600 | State.Bang => switch (c) { |
| 566 | 601 | '=' => { |
| 567 | 602 | result.id = Token.Id.BangEqual; |
| ... | ... | @@ -811,6 +846,7 @@ pub const Tokenizer = struct { |
| 811 | 846 | State.FloatFraction, |
| 812 | 847 | State.FloatExponentNumber, |
| 813 | 848 | State.StringLiteral, // find this error later |
| 849 | State.MultilineStringLiteralLine, | |
| 814 | 850 | State.Builtin => {}, |
| 815 | 851 | |
| 816 | 852 | State.Identifier => { |
| ... | ... | @@ -825,6 +861,8 @@ pub const Tokenizer = struct { |
| 825 | 861 | State.NumberDot, |
| 826 | 862 | State.FloatExponentUnsigned, |
| 827 | 863 | State.SawAtSign, |
| 864 | State.Backslash, | |
| 865 | State.MultilineStringLiteralLineBackslash, | |
| 828 | 866 | State.StringLiteralBackslash => { |
| 829 | 867 | result.id = Token.Id.Invalid; |
| 830 | 868 | }, |