| 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,6 +20,7 @@ pub const Node = struct { |
| 20 | IntegerLiteral, | 20 | IntegerLiteral, |
| 21 | FloatLiteral, | 21 | FloatLiteral, |
| 22 | StringLiteral, | 22 | StringLiteral, |
| 23 | MultilineStringLiteral, | ||
| 23 | UndefinedLiteral, | 24 | UndefinedLiteral, |
| 24 | BuiltinCall, | 25 | BuiltinCall, |
| 25 | Call, | 26 | Call, |
| ... | @@ -40,6 +41,7 @@ pub const Node = struct { | ... | @@ -40,6 +41,7 @@ pub const Node = struct { |
| 40 | Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).iterate(index), | 41 | Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).iterate(index), |
| 41 | Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).iterate(index), | 42 | Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).iterate(index), |
| 42 | Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).iterate(index), | 43 | Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).iterate(index), |
| 44 | Id.MultilineStringLiteral => @fieldParentPtr(NodeMultilineStringLiteral, "base", base).iterate(index), | ||
| 43 | Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).iterate(index), | 45 | Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).iterate(index), |
| 44 | Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index), | 46 | Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index), |
| 45 | Id.Call => @fieldParentPtr(NodeCall, "base", base).iterate(index), | 47 | Id.Call => @fieldParentPtr(NodeCall, "base", base).iterate(index), |
| ... | @@ -61,6 +63,7 @@ pub const Node = struct { | ... | @@ -61,6 +63,7 @@ pub const Node = struct { |
| 61 | Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).firstToken(), | 63 | Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).firstToken(), |
| 62 | Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).firstToken(), | 64 | Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).firstToken(), |
| 63 | Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).firstToken(), | 65 | Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).firstToken(), |
| 66 | Id.MultilineStringLiteral => @fieldParentPtr(NodeMultilineStringLiteral, "base", base).firstToken(), | ||
| 64 | Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).firstToken(), | 67 | Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).firstToken(), |
| 65 | Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).firstToken(), | 68 | Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).firstToken(), |
| 66 | Id.Call => @fieldParentPtr(NodeCall, "base", base).firstToken(), | 69 | Id.Call => @fieldParentPtr(NodeCall, "base", base).firstToken(), |
| ... | @@ -82,6 +85,7 @@ pub const Node = struct { | ... | @@ -82,6 +85,7 @@ pub const Node = struct { |
| 82 | Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).lastToken(), | 85 | Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).lastToken(), |
| 83 | Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).lastToken(), | 86 | Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).lastToken(), |
| 84 | Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).lastToken(), | 87 | Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).lastToken(), |
| 88 | Id.MultilineStringLiteral => @fieldParentPtr(NodeMultilineStringLiteral, "base", base).lastToken(), | ||
| 85 | Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).lastToken(), | 89 | Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).lastToken(), |
| 86 | Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).lastToken(), | 90 | Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).lastToken(), |
| 87 | Id.Call => @fieldParentPtr(NodeCall, "base", base).lastToken(), | 91 | Id.Call => @fieldParentPtr(NodeCall, "base", base).lastToken(), |
| ... | @@ -587,6 +591,23 @@ pub const NodeStringLiteral = struct { | ... | @@ -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 | pub const NodeUndefinedLiteral = struct { | 611 | pub const NodeUndefinedLiteral = struct { |
| 591 | base: Node, | 612 | base: Node, |
| 592 | token: Token, | 613 | token: Token, |
std/zig/parser.zig+48-4| ... | @@ -456,6 +456,30 @@ pub const Parser = struct { | ... | @@ -456,6 +456,30 @@ pub const Parser = struct { |
| 456 | try stack.append(State.AfterOperand); | 456 | try stack.append(State.AfterOperand); |
| 457 | continue; | 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 | else => return self.parseError(token, "expected primary expression, found {}", @tagName(token.id)), | 484 | else => return self.parseError(token, "expected primary expression, found {}", @tagName(token.id)), |
| 461 | } | 485 | } |
| ... | @@ -1427,6 +1451,20 @@ pub const Parser = struct { | ... | @@ -1427,6 +1451,20 @@ pub const Parser = struct { |
| 1427 | const string_literal = @fieldParentPtr(ast.NodeStringLiteral, "base", base); | 1451 | const string_literal = @fieldParentPtr(ast.NodeStringLiteral, "base", base); |
| 1428 | try stream.print("{}", self.tokenizer.getTokenSlice(string_literal.token)); | 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 | ast.Node.Id.UndefinedLiteral => { | 1468 | ast.Node.Id.UndefinedLiteral => { |
| 1431 | const undefined_literal = @fieldParentPtr(ast.NodeUndefinedLiteral, "base", base); | 1469 | const undefined_literal = @fieldParentPtr(ast.NodeUndefinedLiteral, "base", base); |
| 1432 | try stream.print("{}", self.tokenizer.getTokenSlice(undefined_literal.token)); | 1470 | try stream.print("{}", self.tokenizer.getTokenSlice(undefined_literal.token)); |
| ... | @@ -1806,6 +1844,16 @@ test "zig fmt: extern function" { | ... | @@ -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 | test "zig fmt: values" { | 1857 | test "zig fmt: values" { |
| 1810 | try testCanonical( | 1858 | try testCanonical( |
| 1811 | \\test "values" { | 1859 | \\test "values" { |
| ... | @@ -1813,10 +1861,6 @@ test "zig fmt: values" { | ... | @@ -1813,10 +1861,6 @@ test "zig fmt: values" { |
| 1813 | \\ 1.0; | 1861 | \\ 1.0; |
| 1814 | \\ "string"; | 1862 | \\ "string"; |
| 1815 | \\ c"cstring"; | 1863 | \\ c"cstring"; |
| 1816 | \\ \\ Multi | ||
| 1817 | \\ \\ line | ||
| 1818 | \\ \\ string | ||
| 1819 | \\ ; | ||
| 1820 | \\ 'c'; | 1864 | \\ 'c'; |
| 1821 | \\ true; | 1865 | \\ true; |
| 1822 | \\ false; | 1866 | \\ false; |
std/zig/tokenizer.zig+39-1| ... | @@ -72,6 +72,7 @@ pub const Token = struct { | ... | @@ -72,6 +72,7 @@ pub const Token = struct { |
| 72 | Invalid, | 72 | Invalid, |
| 73 | Identifier, | 73 | Identifier, |
| 74 | StringLiteral: StrLitKind, | 74 | StringLiteral: StrLitKind, |
| 75 | MultilineStringLiteralLine: StrLitKind, | ||
| 75 | StringIdentifier, | 76 | StringIdentifier, |
| 76 | Eof, | 77 | Eof, |
| 77 | Builtin, | 78 | Builtin, |
| ... | @@ -225,6 +226,9 @@ pub const Tokenizer = struct { | ... | @@ -225,6 +226,9 @@ pub const Tokenizer = struct { |
| 225 | C, | 226 | C, |
| 226 | StringLiteral, | 227 | StringLiteral, |
| 227 | StringLiteralBackslash, | 228 | StringLiteralBackslash, |
| 229 | MultilineStringLiteralLine, | ||
| 230 | MultilineStringLiteralLineBackslash, | ||
| 231 | Backslash, | ||
| 228 | Equal, | 232 | Equal, |
| 229 | Bang, | 233 | Bang, |
| 230 | Pipe, | 234 | Pipe, |
| ... | @@ -352,6 +356,10 @@ pub const Tokenizer = struct { | ... | @@ -352,6 +356,10 @@ pub const Tokenizer = struct { |
| 352 | '^' => { | 356 | '^' => { |
| 353 | state = State.Caret; | 357 | state = State.Caret; |
| 354 | }, | 358 | }, |
| 359 | '\\' => { | ||
| 360 | state = State.Backslash; | ||
| 361 | result.id = Token.Id { .MultilineStringLiteralLine = Token.StrLitKind.Normal }; | ||
| 362 | }, | ||
| 355 | '{' => { | 363 | '{' => { |
| 356 | result.id = Token.Id.LBrace; | 364 | result.id = Token.Id.LBrace; |
| 357 | self.index += 1; | 365 | self.index += 1; |
| ... | @@ -532,8 +540,17 @@ pub const Tokenizer = struct { | ... | @@ -532,8 +540,17 @@ pub const Tokenizer = struct { |
| 532 | 'a'...'z', 'A'...'Z', '_', '0'...'9' => {}, | 540 | 'a'...'z', 'A'...'Z', '_', '0'...'9' => {}, |
| 533 | else => break, | 541 | else => break, |
| 534 | }, | 542 | }, |
| 543 | State.Backslash => switch (c) { | ||
| 544 | '\\' => { | ||
| 545 | state = State.MultilineStringLiteralLine; | ||
| 546 | }, | ||
| 547 | else => break, | ||
| 548 | }, | ||
| 535 | State.C => switch (c) { | 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 | state = State.StringLiteral; | 555 | state = State.StringLiteral; |
| 539 | result.id = Token.Id { .StringLiteral = Token.StrLitKind.C }; | 556 | result.id = Token.Id { .StringLiteral = Token.StrLitKind.C }; |
| ... | @@ -562,6 +579,24 @@ pub const Tokenizer = struct { | ... | @@ -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 | State.Bang => switch (c) { | 600 | State.Bang => switch (c) { |
| 566 | '=' => { | 601 | '=' => { |
| 567 | result.id = Token.Id.BangEqual; | 602 | result.id = Token.Id.BangEqual; |
| ... | @@ -811,6 +846,7 @@ pub const Tokenizer = struct { | ... | @@ -811,6 +846,7 @@ pub const Tokenizer = struct { |
| 811 | State.FloatFraction, | 846 | State.FloatFraction, |
| 812 | State.FloatExponentNumber, | 847 | State.FloatExponentNumber, |
| 813 | State.StringLiteral, // find this error later | 848 | State.StringLiteral, // find this error later |
| 849 | State.MultilineStringLiteralLine, | ||
| 814 | State.Builtin => {}, | 850 | State.Builtin => {}, |
| 815 | 851 | ||
| 816 | State.Identifier => { | 852 | State.Identifier => { |
| ... | @@ -825,6 +861,8 @@ pub const Tokenizer = struct { | ... | @@ -825,6 +861,8 @@ pub const Tokenizer = struct { |
| 825 | State.NumberDot, | 861 | State.NumberDot, |
| 826 | State.FloatExponentUnsigned, | 862 | State.FloatExponentUnsigned, |
| 827 | State.SawAtSign, | 863 | State.SawAtSign, |
| 864 | State.Backslash, | ||
| 865 | State.MultilineStringLiteralLineBackslash, | ||
| 828 | State.StringLiteralBackslash => { | 866 | State.StringLiteralBackslash => { |
| 829 | result.id = Token.Id.Invalid; | 867 | result.id = Token.Id.Invalid; |
| 830 | }, | 868 | }, |