Explorar o código

Clean up a few details of lex yaml printing (#4845)

- Escape dumped token strings (what got me here)
- Change the quoting from backticks to quotes
- Also add a `FormatEscaped` helper function for this, updating other
`.write_escaped` uses
Jon Ross-Perkins hai 1 ano
pai
achega
b06fcc97f6

+ 20 - 0
common/ostream.h

@@ -53,6 +53,26 @@ class Printable {
   }
 };
 
+// Helper class for printing strings with escapes.
+//
+// For example:
+//   stream << FormatEscaped(str);
+// Is equivalent to:
+//   stream.write_escaped(str);
+class FormatEscaped : public Printable<FormatEscaped> {
+ public:
+  explicit FormatEscaped(llvm::StringRef str, bool use_hex_escapes = false)
+      : str_(str), use_hex_escapes_(use_hex_escapes) {}
+
+  auto Print(llvm::raw_ostream& out) const -> void {
+    out.write_escaped(str_, use_hex_escapes_);
+  }
+
+ private:
+  llvm::StringRef str_;
+  bool use_hex_escapes_;
+};
+
 // Returns the result of printing the value.
 template <typename T>
   requires std::derived_from<T, Printable<T>>

+ 2 - 3
testing/file_test/file_test_base.h

@@ -29,9 +29,8 @@ class FileTestBase : public testing::Test {
     friend void PrintTo(const TestFile& f, std::ostream* os) {
       // Print content escaped.
       llvm::raw_os_ostream os_wrap(*os);
-      os_wrap << "TestFile(" << f.filename << ", \"";
-      os_wrap.write_escaped(f.content);
-      os_wrap << "\")";
+      os_wrap << "TestFile(" << f.filename << ", \"" << FormatEscaped(f.content)
+              << "\")";
     }
 
     std::string filename;

+ 4 - 6
toolchain/check/dump.cpp

@@ -40,9 +40,8 @@ static auto DumpNoNewline(const Context& context, SemIR::LocId loc_id) -> void {
     auto line = context.tokens().GetLineNumber(token);
     auto col = context.tokens().GetColumnNumber(token);
     const char* implicit = loc_id.is_implicit() ? " implicit" : "";
-    llvm::errs() << "LocId(";
-    llvm::errs().write_escaped(context.sem_ir().filename());
-    llvm::errs() << ":" << line << ":" << col << implicit << ")";
+    llvm::errs() << "LocId(" << FormatEscaped(context.sem_ir().filename())
+                 << ":" << line << ":" << col << implicit << ")";
   } else {
     CARBON_CHECK(loc_id.is_import_ir_inst_id());
 
@@ -52,9 +51,8 @@ static auto DumpNoNewline(const Context& context, SemIR::LocId loc_id) -> void {
                             .ir_id;
     const auto* import_file =
         context.sem_ir().import_irs().Get(import_ir_id).sem_ir;
-    llvm::errs() << "LocId(import from \"";
-    llvm::errs().write_escaped(import_file->filename());
-    llvm::errs() << "\")";
+    llvm::errs() << "LocId(import from \""
+                 << FormatEscaped(import_file->filename()) << "\")";
   }
 }
 

+ 1 - 3
toolchain/check/import_cpp.cpp

@@ -27,9 +27,7 @@ static auto GenerateCppIncludesHeaderCode(
   std::string code;
   llvm::raw_string_ostream code_stream(code);
   for (const auto& [path, _] : imports) {
-    code_stream << "#include \"";
-    code_stream.write_escaped(path);
-    code_stream << "\"\n";
+    code_stream << "#include \"" << FormatEscaped(path) << "\"\n";
   }
   return code;
 }

+ 13 - 13
toolchain/lex/testdata/basic_syntax.carbon

@@ -12,21 +12,21 @@
 // TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/lex/testdata/basic_syntax.carbon
 // CHECK:STDOUT: - filename: basic_syntax.carbon
 // CHECK:STDOUT:   tokens:
-// CHECK:STDOUT:   - { index:  0, kind:         'FileStart', line: {{ *\d+}}, column:   1, indent: 1, spelling: '' }
+// CHECK:STDOUT:   - { index:  0, kind:         "FileStart", line: {{ *\d+}}, column:   1, indent: 1, spelling: "" }
 
 fn run(String program) {
-// CHECK:STDOUT:   - { index:  1, kind:                'Fn', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: 'fn', has_leading_space: true }
-// CHECK:STDOUT:   - { index:  2, kind:        'Identifier', line: {{ *}}[[@LINE-2]], column:   4, indent: 1, spelling: 'run', identifier: 0, has_leading_space: true }
-// CHECK:STDOUT:   - { index:  3, kind:         'OpenParen', line: {{ *}}[[@LINE-3]], column:   7, indent: 1, spelling: '(', closing_token: 6 }
-// CHECK:STDOUT:   - { index:  4, kind: 'StringTypeLiteral', line: {{ *}}[[@LINE-4]], column:   8, indent: 1, spelling: 'String' }
-// CHECK:STDOUT:   - { index:  5, kind:        'Identifier', line: {{ *}}[[@LINE-5]], column:  15, indent: 1, spelling: 'program', identifier: 1, has_leading_space: true }
-// CHECK:STDOUT:   - { index:  6, kind:        'CloseParen', line: {{ *}}[[@LINE-6]], column:  22, indent: 1, spelling: ')', opening_token: 3 }
-// CHECK:STDOUT:   - { index:  7, kind:    'OpenCurlyBrace', line: {{ *}}[[@LINE-7]], column:  24, indent: 1, spelling: '{', closing_token: 11, has_leading_space: true }
+// CHECK:STDOUT:   - { index:  1, kind:                "Fn", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "fn", has_leading_space: true }
+// CHECK:STDOUT:   - { index:  2, kind:        "Identifier", line: {{ *}}[[@LINE-2]], column:   4, indent: 1, spelling: "run", identifier: 0, has_leading_space: true }
+// CHECK:STDOUT:   - { index:  3, kind:         "OpenParen", line: {{ *}}[[@LINE-3]], column:   7, indent: 1, spelling: "(", closing_token: 6 }
+// CHECK:STDOUT:   - { index:  4, kind: "StringTypeLiteral", line: {{ *}}[[@LINE-4]], column:   8, indent: 1, spelling: "String" }
+// CHECK:STDOUT:   - { index:  5, kind:        "Identifier", line: {{ *}}[[@LINE-5]], column:  15, indent: 1, spelling: "program", identifier: 1, has_leading_space: true }
+// CHECK:STDOUT:   - { index:  6, kind:        "CloseParen", line: {{ *}}[[@LINE-6]], column:  22, indent: 1, spelling: ")", opening_token: 3 }
+// CHECK:STDOUT:   - { index:  7, kind:    "OpenCurlyBrace", line: {{ *}}[[@LINE-7]], column:  24, indent: 1, spelling: "{", closing_token: 11, has_leading_space: true }
   return True;
-  // CHECK:STDOUT:   - { index:  8, kind:            'Return', line: {{ *}}[[@LINE-1]], column:   3, indent: 3, spelling: 'return', has_leading_space: true }
-  // CHECK:STDOUT:   - { index:  9, kind:        'Identifier', line: {{ *}}[[@LINE-2]], column:  10, indent: 3, spelling: 'True', identifier: 2, has_leading_space: true }
-  // CHECK:STDOUT:   - { index: 10, kind:              'Semi', line: {{ *}}[[@LINE-3]], column:  14, indent: 3, spelling: ';' }
+  // CHECK:STDOUT:   - { index:  8, kind:            "Return", line: {{ *}}[[@LINE-1]], column:   3, indent: 3, spelling: "return", has_leading_space: true }
+  // CHECK:STDOUT:   - { index:  9, kind:        "Identifier", line: {{ *}}[[@LINE-2]], column:  10, indent: 3, spelling: "True", identifier: 2, has_leading_space: true }
+  // CHECK:STDOUT:   - { index: 10, kind:              "Semi", line: {{ *}}[[@LINE-3]], column:  14, indent: 3, spelling: ";" }
 }
-// CHECK:STDOUT:   - { index: 11, kind:   'CloseCurlyBrace', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: '}', opening_token: 7, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 11, kind:   "CloseCurlyBrace", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "}", opening_token: 7, has_leading_space: true }
 
-// CHECK:STDOUT:   - { index: 12, kind:           'FileEnd', line: {{ *}}[[@LINE+0]], column: {{ *\d+}}, indent: 1, spelling: '', has_leading_space: true }
+// CHECK:STDOUT:   - { index: 12, kind:           "FileEnd", line: {{ *}}[[@LINE+0]], column: {{ *\d+}}, indent: 1, spelling: "", has_leading_space: true }

+ 23 - 23
toolchain/lex/testdata/fail_bad_raw_identifier.carbon

@@ -19,8 +19,8 @@
 // CHECK:STDERR:  ^
 // CHECK:STDERR:
 r#
-// CHECK:STDOUT:   - { index:  1, kind:    'Identifier', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'r', identifier: 0, has_leading_space: true }
-// CHECK:STDOUT:   - { index:  2, kind:         'Error', line: {{ *}}[[@LINE-2]], column: 2, indent: 1, spelling: '#' }
+// CHECK:STDOUT:   - { index:  1, kind:    "Identifier", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "r", identifier: 0, has_leading_space: true }
+// CHECK:STDOUT:   - { index:  2, kind:         "Error", line: {{ *}}[[@LINE-2]], column: 2, indent: 1, spelling: "#" }
 
 // Not a valid identifier.
 // CHECK:STDERR: fail_bad_raw_identifier.carbon:[[@LINE+4]]:2: error: encountered unrecognized characters while parsing [UnrecognizedCharacters]
@@ -28,9 +28,9 @@ r#
 // CHECK:STDERR:  ^
 // CHECK:STDERR:
 r#3
-// CHECK:STDOUT:   - { index:  3, kind:    'Identifier', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'r', identifier: 0, has_leading_space: true }
-// CHECK:STDOUT:   - { index:  4, kind:         'Error', line: {{ *}}[[@LINE-2]], column: 2, indent: 1, spelling: '#' }
-// CHECK:STDOUT:   - { index:  5, kind:    'IntLiteral', line: {{ *}}[[@LINE-3]], column: 3, indent: 1, spelling: '3', value: `3` }
+// CHECK:STDOUT:   - { index:  3, kind:    "Identifier", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "r", identifier: 0, has_leading_space: true }
+// CHECK:STDOUT:   - { index:  4, kind:         "Error", line: {{ *}}[[@LINE-2]], column: 2, indent: 1, spelling: "#" }
+// CHECK:STDOUT:   - { index:  5, kind:    "IntLiteral", line: {{ *}}[[@LINE-3]], column: 3, indent: 1, spelling: "3", value: "3" }
 
 // Non ascii start to identifier.
 // CHECK:STDERR: fail_bad_raw_identifier.carbon:[[@LINE+4]]:2: error: encountered unrecognized characters while parsing [UnrecognizedCharacters]
@@ -38,8 +38,8 @@ r#3
 // CHECK:STDERR:  ^
 // CHECK:STDERR:
 r#á
-// CHECK:STDOUT:   - { index:  6, kind:    'Identifier', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'r', identifier: 0, has_leading_space: true }
-// CHECK:STDOUT:   - { index:  7, kind:         'Error', line: {{ *}}[[@LINE-2]], column: 2, indent: 1, spelling: '#á' }
+// CHECK:STDOUT:   - { index:  6, kind:    "Identifier", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "r", identifier: 0, has_leading_space: true }
+// CHECK:STDOUT:   - { index:  7, kind:         "Error", line: {{ *}}[[@LINE-2]], column: 2, indent: 1, spelling: "#\xC3\xA1" }
 
 // Raw `r` identifier doesn't start a second raw identifier.
 // CHECK:STDERR: fail_bad_raw_identifier.carbon:[[@LINE+4]]:4: error: encountered unrecognized characters while parsing [UnrecognizedCharacters]
@@ -47,9 +47,9 @@ r#á
 // CHECK:STDERR:    ^
 // CHECK:STDERR:
 r#r#foo
-// CHECK:STDOUT:   - { index:  8, kind:    'Identifier', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'r', identifier: 0, has_leading_space: true }
-// CHECK:STDOUT:   - { index:  9, kind:         'Error', line: {{ *}}[[@LINE-2]], column: 4, indent: 1, spelling: '#' }
-// CHECK:STDOUT:   - { index: 10, kind:    'Identifier', line: {{ *}}[[@LINE-3]], column: 5, indent: 1, spelling: 'foo', identifier: 1 }
+// CHECK:STDOUT:   - { index:  8, kind:    "Identifier", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "r", identifier: 0, has_leading_space: true }
+// CHECK:STDOUT:   - { index:  9, kind:         "Error", line: {{ *}}[[@LINE-2]], column: 4, indent: 1, spelling: "#" }
+// CHECK:STDOUT:   - { index: 10, kind:    "Identifier", line: {{ *}}[[@LINE-3]], column: 5, indent: 1, spelling: "foo", identifier: 1 }
 
 // Other identifier characters don't start a raw identifier.
 // CHECK:STDERR: fail_bad_raw_identifier.carbon:[[@LINE+4]]:2: error: encountered unrecognized characters while parsing [UnrecognizedCharacters]
@@ -57,9 +57,9 @@ r#r#foo
 // CHECK:STDERR:  ^
 // CHECK:STDERR:
 s#foo
-// CHECK:STDOUT:   - { index: 11, kind:    'Identifier', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 's', identifier: 2, has_leading_space: true }
-// CHECK:STDOUT:   - { index: 12, kind:         'Error', line: {{ *}}[[@LINE-2]], column: 2, indent: 1, spelling: '#' }
-// CHECK:STDOUT:   - { index: 13, kind:    'Identifier', line: {{ *}}[[@LINE-3]], column: 3, indent: 1, spelling: 'foo', identifier: 1 }
+// CHECK:STDOUT:   - { index: 11, kind:    "Identifier", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "s", identifier: 2, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 12, kind:         "Error", line: {{ *}}[[@LINE-2]], column: 2, indent: 1, spelling: "#" }
+// CHECK:STDOUT:   - { index: 13, kind:    "Identifier", line: {{ *}}[[@LINE-3]], column: 3, indent: 1, spelling: "foo", identifier: 1 }
 
 // Identifier ending in `r` doesn't start a raw identifier.
 // CHECK:STDERR: fail_bad_raw_identifier.carbon:[[@LINE+4]]:4: error: encountered unrecognized characters while parsing [UnrecognizedCharacters]
@@ -67,9 +67,9 @@ s#foo
 // CHECK:STDERR:    ^
 // CHECK:STDERR:
 arr#foo
-// CHECK:STDOUT:   - { index: 14, kind:    'Identifier', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'arr', identifier: 3, has_leading_space: true }
-// CHECK:STDOUT:   - { index: 15, kind:         'Error', line: {{ *}}[[@LINE-2]], column: 4, indent: 1, spelling: '#' }
-// CHECK:STDOUT:   - { index: 16, kind:    'Identifier', line: {{ *}}[[@LINE-3]], column: 5, indent: 1, spelling: 'foo', identifier: 1 }
+// CHECK:STDOUT:   - { index: 14, kind:    "Identifier", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "arr", identifier: 3, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 15, kind:         "Error", line: {{ *}}[[@LINE-2]], column: 4, indent: 1, spelling: "#" }
+// CHECK:STDOUT:   - { index: 16, kind:    "Identifier", line: {{ *}}[[@LINE-3]], column: 5, indent: 1, spelling: "foo", identifier: 1 }
 
 // Whitespace between `r` and `#` isn't allowed.
 // CHECK:STDERR: fail_bad_raw_identifier.carbon:[[@LINE+4]]:3: error: encountered unrecognized characters while parsing [UnrecognizedCharacters]
@@ -77,14 +77,14 @@ arr#foo
 // CHECK:STDERR:   ^
 // CHECK:STDERR:
 r #foo
-// CHECK:STDOUT:   - { index: 17, kind:    'Identifier', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'r', identifier: 0, has_leading_space: true }
-// CHECK:STDOUT:   - { index: 18, kind:         'Error', line: {{ *}}[[@LINE-2]], column: 3, indent: 1, spelling: '#', has_leading_space: true }
-// CHECK:STDOUT:   - { index: 19, kind:    'Identifier', line: {{ *}}[[@LINE-3]], column: 4, indent: 1, spelling: 'foo', identifier: 1 }
+// CHECK:STDOUT:   - { index: 17, kind:    "Identifier", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "r", identifier: 0, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 18, kind:         "Error", line: {{ *}}[[@LINE-2]], column: 3, indent: 1, spelling: "#", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 19, kind:    "Identifier", line: {{ *}}[[@LINE-3]], column: 4, indent: 1, spelling: "foo", identifier: 1 }
 
 // This is an `r` identifier followed by a string literal.
 r#"hello"#
-// CHECK:STDOUT:   - { index: 20, kind:    'Identifier', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'r', identifier: 0, has_leading_space: true }
-// CHECK:STDOUT:   - { index: 21, kind: 'StringLiteral', line: {{ *}}[[@LINE-2]], column: 2, indent: 1, spelling: '#"hello"#', value: `hello` }
+// CHECK:STDOUT:   - { index: 20, kind:    "Identifier", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "r", identifier: 0, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 21, kind: "StringLiteral", line: {{ *}}[[@LINE-2]], column: 2, indent: 1, spelling: "#\"hello\"#", value: "hello" }
 
 // --- fail_hash_at_start_of_file.carbon
 // CHECK:STDOUT: - filename: fail_hash_at_start_of_file.carbon
@@ -96,5 +96,5 @@ r#"hello"#
 // CHECK:STDERR: ^
 // CHECK:STDERR:
 #foo
-// CHECK:STDOUT:   - { index: 1, kind:      'Error', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: '#', has_leading_space: true }
-// CHECK:STDOUT:   - { index: 2, kind: 'Identifier', line: {{ *}}[[@LINE-2]], column:   2, indent: 1, spelling: 'foo', identifier: 0 }
+// CHECK:STDOUT:   - { index: 1, kind:      "Error", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "#", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 2, kind: "Identifier", line: {{ *}}[[@LINE-2]], column:   2, indent: 1, spelling: "foo", identifier: 0 }

+ 6 - 7
toolchain/lex/testdata/fail_block_string_second_line.carbon

@@ -19,10 +19,9 @@ var s: String = '''
 // CHECK:STDERR:
 // CHECK:STDOUT: - filename: fail_block_string_second_line.carbon
 // CHECK:STDOUT:   tokens:
-// CHECK:STDOUT:   - { index: 1, kind:               'Var', line: {{ *}}[[@LINE-17]], column:  1, indent: 1, spelling: 'var', has_leading_space: true }
-// CHECK:STDOUT:   - { index: 2, kind:        'Identifier', line: {{ *}}[[@LINE-18]], column:  5, indent: 1, spelling: 's', identifier: 0, has_leading_space: true }
-// CHECK:STDOUT:   - { index: 3, kind:             'Colon', line: {{ *}}[[@LINE-19]], column:  6, indent: 1, spelling: ':' }
-// CHECK:STDOUT:   - { index: 4, kind: 'StringTypeLiteral', line: {{ *}}[[@LINE-20]], column:  8, indent: 1, spelling: 'String', has_leading_space: true }
-// CHECK:STDOUT:   - { index: 5, kind:             'Equal', line: {{ *}}[[@LINE-21]], column: 15, indent: 1, spelling: '=', has_leading_space: true }
-// CHECK:STDOUT:   - { index: 6, kind:     'StringLiteral', line: {{ *}}[[@LINE-22]], column: 17, indent: 1, spelling: ''''
-// CHECK:STDOUT:   error here: '''', value: `error here: `, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 1, kind:               "Var", line: {{ *}}[[@LINE-17]], column:   1, indent: 1, spelling: "var", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 2, kind:        "Identifier", line: {{ *}}[[@LINE-18]], column:   5, indent: 1, spelling: "s", identifier: 0, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 3, kind:             "Colon", line: {{ *}}[[@LINE-19]], column:   6, indent: 1, spelling: ":" }
+// CHECK:STDOUT:   - { index: 4, kind: "StringTypeLiteral", line: {{ *}}[[@LINE-20]], column:   8, indent: 1, spelling: "String", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 5, kind:             "Equal", line: {{ *}}[[@LINE-21]], column:  15, indent: 1, spelling: "=", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 6, kind:     "StringLiteral", line: {{ *}}[[@LINE-22]], column:  17, indent: 1, spelling: "'''\n  error here: '''", value: "error here: ", has_leading_space: true }

+ 5 - 5
toolchain/lex/testdata/fail_mismatched_brackets.carbon

@@ -15,20 +15,20 @@
 // CHECK:STDERR: ^
 // CHECK:STDERR:
 }
-// CHECK:STDOUT:   - { index: 1, kind:      'Error', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: '}', has_leading_space: true }
+// CHECK:STDOUT:   - { index: 1, kind:      "Error", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "}", has_leading_space: true }
 
 // CHECK:STDERR: fail_mismatched_brackets.carbon:[[@LINE+4]]:3: error: closing symbol without a corresponding opening symbol [UnmatchedClosing]
 // CHECK:STDERR: ( } )
 // CHECK:STDERR:   ^
 // CHECK:STDERR:
 ( } )
-// CHECK:STDOUT:   - { index: 2, kind:  'OpenParen', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: '(', closing_token: 4, has_leading_space: true }
-// CHECK:STDOUT:   - { index: 3, kind:      'Error', line: {{ *}}[[@LINE-2]], column:   3, indent: 1, spelling: '}', has_leading_space: true }
-// CHECK:STDOUT:   - { index: 4, kind: 'CloseParen', line: {{ *}}[[@LINE-3]], column:   5, indent: 1, spelling: ')', opening_token: 2, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 2, kind:  "OpenParen", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "(", closing_token: 4, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 3, kind:      "Error", line: {{ *}}[[@LINE-2]], column:   3, indent: 1, spelling: "}", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 4, kind: "CloseParen", line: {{ *}}[[@LINE-3]], column:   5, indent: 1, spelling: ")", opening_token: 2, has_leading_space: true }
 
 // CHECK:STDERR: fail_mismatched_brackets.carbon:[[@LINE+4]]:1: error: opening symbol without a corresponding closing symbol [UnmatchedOpening]
 // CHECK:STDERR: [
 // CHECK:STDERR: ^
 // CHECK:STDERR:
 [
-// CHECK:STDOUT:   - { index: 5, kind:      'Error', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: '[', has_leading_space: true }
+// CHECK:STDOUT:   - { index: 5, kind:      "Error", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "[", has_leading_space: true }

+ 13 - 13
toolchain/lex/testdata/fail_mismatched_brackets_2.carbon

@@ -24,16 +24,16 @@ fn F() {
 // CHECK:STDERR:
 // CHECK:STDOUT: - filename: fail_mismatched_brackets_2.carbon
 // CHECK:STDOUT:   tokens:
-// CHECK:STDOUT:   - { index:  1, kind:              'Fn', line: {{ *}}[[@LINE-19]], column:   1, indent: 1, spelling: 'fn', has_leading_space: true }
-// CHECK:STDOUT:   - { index:  2, kind:      'Identifier', line: {{ *}}[[@LINE-20]], column:   4, indent: 1, spelling: 'F', identifier: 0, has_leading_space: true }
-// CHECK:STDOUT:   - { index:  3, kind:       'OpenParen', line: {{ *}}[[@LINE-21]], column:   5, indent: 1, spelling: '(', closing_token: 4 }
-// CHECK:STDOUT:   - { index:  4, kind:      'CloseParen', line: {{ *}}[[@LINE-22]], column:   6, indent: 1, spelling: ')', opening_token: 3 }
-// CHECK:STDOUT:   - { index:  5, kind:  'OpenCurlyBrace', line: {{ *}}[[@LINE-23]], column:   8, indent: 1, spelling: '{', closing_token: 12, has_leading_space: true }
-// CHECK:STDOUT:   - { index:  6, kind:              'If', line: {{ *}}[[@LINE-23]], column:   3, indent: 3, spelling: 'if', has_leading_space: true }
-// CHECK:STDOUT:   - { index:  7, kind:       'OpenParen', line: {{ *}}[[@LINE-24]], column:   6, indent: 3, spelling: '(', closing_token: 9, has_leading_space: true }
-// CHECK:STDOUT:   - { index:  8, kind:      'Identifier', line: {{ *}}[[@LINE-25]], column:   7, indent: 3, spelling: 'thing1', identifier: 1 }
-// CHECK:STDOUT:   - { index:  9, kind:      'CloseParen', line: {{ *}}[[@LINE-26]], column:  13, indent: 3, spelling: ')', opening_token: 7 }
-// CHECK:STDOUT:   - { index: 10, kind:      'Identifier', line: {{ *}}[[@LINE-26]], column:   5, indent: 5, spelling: 'thing2', identifier: 2, has_leading_space: true }
-// CHECK:STDOUT:   - { index: 11, kind:            'Semi', line: {{ *}}[[@LINE-27]], column:  11, indent: 5, spelling: ';' }
-// CHECK:STDOUT:   - { index: 12, kind: 'CloseCurlyBrace', line: {{ *}}[[@LINE-27]], column:   3, indent: 3, spelling: '}', opening_token: 5, has_leading_space: true }
-// CHECK:STDOUT:   - { index: 13, kind:           'Error', line: {{ *}}[[@LINE-27]], column:   1, indent: 1, spelling: '}', has_leading_space: true }
+// CHECK:STDOUT:   - { index:  1, kind:              "Fn", line: {{ *}}[[@LINE-19]], column:   1, indent: 1, spelling: "fn", has_leading_space: true }
+// CHECK:STDOUT:   - { index:  2, kind:      "Identifier", line: {{ *}}[[@LINE-20]], column:   4, indent: 1, spelling: "F", identifier: 0, has_leading_space: true }
+// CHECK:STDOUT:   - { index:  3, kind:       "OpenParen", line: {{ *}}[[@LINE-21]], column:   5, indent: 1, spelling: "(", closing_token: 4 }
+// CHECK:STDOUT:   - { index:  4, kind:      "CloseParen", line: {{ *}}[[@LINE-22]], column:   6, indent: 1, spelling: ")", opening_token: 3 }
+// CHECK:STDOUT:   - { index:  5, kind:  "OpenCurlyBrace", line: {{ *}}[[@LINE-23]], column:   8, indent: 1, spelling: "{", closing_token: 12, has_leading_space: true }
+// CHECK:STDOUT:   - { index:  6, kind:              "If", line: {{ *}}[[@LINE-23]], column:   3, indent: 3, spelling: "if", has_leading_space: true }
+// CHECK:STDOUT:   - { index:  7, kind:       "OpenParen", line: {{ *}}[[@LINE-24]], column:   6, indent: 3, spelling: "(", closing_token: 9, has_leading_space: true }
+// CHECK:STDOUT:   - { index:  8, kind:      "Identifier", line: {{ *}}[[@LINE-25]], column:   7, indent: 3, spelling: "thing1", identifier: 1 }
+// CHECK:STDOUT:   - { index:  9, kind:      "CloseParen", line: {{ *}}[[@LINE-26]], column:  13, indent: 3, spelling: ")", opening_token: 7 }
+// CHECK:STDOUT:   - { index: 10, kind:      "Identifier", line: {{ *}}[[@LINE-26]], column:   5, indent: 5, spelling: "thing2", identifier: 2, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 11, kind:            "Semi", line: {{ *}}[[@LINE-27]], column:  11, indent: 5, spelling: ";" }
+// CHECK:STDOUT:   - { index: 12, kind: "CloseCurlyBrace", line: {{ *}}[[@LINE-27]], column:   3, indent: 3, spelling: "}", opening_token: 5, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 13, kind:           "Error", line: {{ *}}[[@LINE-27]], column:   1, indent: 1, spelling: "}", has_leading_space: true }

+ 2 - 2
toolchain/lex/testdata/fail_multifile.carbon

@@ -16,7 +16,7 @@
 // CHECK:STDERR:   ^
 // CHECK:STDERR:
 1.a
-// CHECK:STDOUT:   - { index: 1, kind:     'Error', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: '1.a', has_leading_space: true }
+// CHECK:STDOUT:   - { index: 1, kind:     "Error", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "1.a", has_leading_space: true }
 
 // --- fail_b.carbon
 // CHECK:STDOUT: - filename: fail_b.carbon
@@ -26,4 +26,4 @@
 // CHECK:STDERR:   ^
 // CHECK:STDERR:
 2.b
-// CHECK:STDOUT:   - { index: 1, kind:     'Error', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: '2.b', has_leading_space: true }
+// CHECK:STDOUT:   - { index: 1, kind:     "Error", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "2.b", has_leading_space: true }

+ 21 - 21
toolchain/lex/testdata/fail_trailing_comments.carbon

@@ -30,24 +30,24 @@ var c: i32 = 0.4; // still more trailing comment
 // CHECK:STDERR:
 // CHECK:STDOUT: - filename: fail_trailing_comments.carbon
 // CHECK:STDOUT:   tokens:
-// CHECK:STDOUT:   - { index:  1, kind:            'Var', line: {{ *}}[[@LINE-25]], column:   1, indent: 1, spelling: 'var', has_leading_space: true }
-// CHECK:STDOUT:   - { index:  2, kind:     'Identifier', line: {{ *}}[[@LINE-26]], column:   5, indent: 1, spelling: 'a', identifier: 0, has_leading_space: true }
-// CHECK:STDOUT:   - { index:  3, kind:          'Colon', line: {{ *}}[[@LINE-27]], column:   6, indent: 1, spelling: ':' }
-// CHECK:STDOUT:   - { index:  4, kind: 'IntTypeLiteral', line: {{ *}}[[@LINE-28]], column:   8, indent: 1, spelling: 'i32', has_leading_space: true }
-// CHECK:STDOUT:   - { index:  5, kind:          'Equal', line: {{ *}}[[@LINE-29]], column:  12, indent: 1, spelling: '=', has_leading_space: true }
-// CHECK:STDOUT:   - { index:  6, kind:     'IntLiteral', line: {{ *}}[[@LINE-30]], column:  14, indent: 1, spelling: '1', value: `1`, has_leading_space: true }
-// CHECK:STDOUT:   - { index:  7, kind:           'Semi', line: {{ *}}[[@LINE-31]], column:  15, indent: 1, spelling: ';' }
-// CHECK:STDOUT:   - { index:  8, kind:            'Var', line: {{ *}}[[@LINE-31]], column:   1, indent: 1, spelling: 'var', has_leading_space: true }
-// CHECK:STDOUT:   - { index:  9, kind:     'Identifier', line: {{ *}}[[@LINE-32]], column:   5, indent: 1, spelling: 'b', identifier: 1, has_leading_space: true }
-// CHECK:STDOUT:   - { index: 10, kind:          'Colon', line: {{ *}}[[@LINE-33]], column:   6, indent: 1, spelling: ':' }
-// CHECK:STDOUT:   - { index: 11, kind:     'IntLiteral', line: {{ *}}[[@LINE-34]], column:   8, indent: 1, spelling: '32', value: `32`, has_leading_space: true }
-// CHECK:STDOUT:   - { index: 12, kind:          'Equal', line: {{ *}}[[@LINE-35]], column:  11, indent: 1, spelling: '=', has_leading_space: true }
-// CHECK:STDOUT:   - { index: 13, kind:     'IntLiteral', line: {{ *}}[[@LINE-36]], column:  13, indent: 1, spelling: '13', value: `13`, has_leading_space: true }
-// CHECK:STDOUT:   - { index: 14, kind:           'Semi', line: {{ *}}[[@LINE-37]], column:  15, indent: 1, spelling: ';' }
-// CHECK:STDOUT:   - { index: 15, kind:            'Var', line: {{ *}}[[@LINE-37]], column:   1, indent: 1, spelling: 'var', has_leading_space: true }
-// CHECK:STDOUT:   - { index: 16, kind:     'Identifier', line: {{ *}}[[@LINE-38]], column:   5, indent: 1, spelling: 'c', identifier: 2, has_leading_space: true }
-// CHECK:STDOUT:   - { index: 17, kind:          'Colon', line: {{ *}}[[@LINE-39]], column:   6, indent: 1, spelling: ':' }
-// CHECK:STDOUT:   - { index: 18, kind: 'IntTypeLiteral', line: {{ *}}[[@LINE-40]], column:   8, indent: 1, spelling: 'i32', has_leading_space: true }
-// CHECK:STDOUT:   - { index: 19, kind:          'Equal', line: {{ *}}[[@LINE-41]], column:  12, indent: 1, spelling: '=', has_leading_space: true }
-// CHECK:STDOUT:   - { index: 20, kind:    'RealLiteral', line: {{ *}}[[@LINE-42]], column:  14, indent: 1, spelling: '0.4', value: `4*10^-1`, has_leading_space: true }
-// CHECK:STDOUT:   - { index: 21, kind:           'Semi', line: {{ *}}[[@LINE-43]], column:  17, indent: 1, spelling: ';' }
+// CHECK:STDOUT:   - { index:  1, kind:            "Var", line: {{ *}}[[@LINE-25]], column:   1, indent: 1, spelling: "var", has_leading_space: true }
+// CHECK:STDOUT:   - { index:  2, kind:     "Identifier", line: {{ *}}[[@LINE-26]], column:   5, indent: 1, spelling: "a", identifier: 0, has_leading_space: true }
+// CHECK:STDOUT:   - { index:  3, kind:          "Colon", line: {{ *}}[[@LINE-27]], column:   6, indent: 1, spelling: ":" }
+// CHECK:STDOUT:   - { index:  4, kind: "IntTypeLiteral", line: {{ *}}[[@LINE-28]], column:   8, indent: 1, spelling: "i32", has_leading_space: true }
+// CHECK:STDOUT:   - { index:  5, kind:          "Equal", line: {{ *}}[[@LINE-29]], column:  12, indent: 1, spelling: "=", has_leading_space: true }
+// CHECK:STDOUT:   - { index:  6, kind:     "IntLiteral", line: {{ *}}[[@LINE-30]], column:  14, indent: 1, spelling: "1", value: "1", has_leading_space: true }
+// CHECK:STDOUT:   - { index:  7, kind:           "Semi", line: {{ *}}[[@LINE-31]], column:  15, indent: 1, spelling: ";" }
+// CHECK:STDOUT:   - { index:  8, kind:            "Var", line: {{ *}}[[@LINE-31]], column:   1, indent: 1, spelling: "var", has_leading_space: true }
+// CHECK:STDOUT:   - { index:  9, kind:     "Identifier", line: {{ *}}[[@LINE-32]], column:   5, indent: 1, spelling: "b", identifier: 1, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 10, kind:          "Colon", line: {{ *}}[[@LINE-33]], column:   6, indent: 1, spelling: ":" }
+// CHECK:STDOUT:   - { index: 11, kind:     "IntLiteral", line: {{ *}}[[@LINE-34]], column:   8, indent: 1, spelling: "32", value: "32", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 12, kind:          "Equal", line: {{ *}}[[@LINE-35]], column:  11, indent: 1, spelling: "=", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 13, kind:     "IntLiteral", line: {{ *}}[[@LINE-36]], column:  13, indent: 1, spelling: "13", value: "13", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 14, kind:           "Semi", line: {{ *}}[[@LINE-37]], column:  15, indent: 1, spelling: ";" }
+// CHECK:STDOUT:   - { index: 15, kind:            "Var", line: {{ *}}[[@LINE-37]], column:   1, indent: 1, spelling: "var", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 16, kind:     "Identifier", line: {{ *}}[[@LINE-38]], column:   5, indent: 1, spelling: "c", identifier: 2, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 17, kind:          "Colon", line: {{ *}}[[@LINE-39]], column:   6, indent: 1, spelling: ":" }
+// CHECK:STDOUT:   - { index: 18, kind: "IntTypeLiteral", line: {{ *}}[[@LINE-40]], column:   8, indent: 1, spelling: "i32", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 19, kind:          "Equal", line: {{ *}}[[@LINE-41]], column:  12, indent: 1, spelling: "=", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 20, kind:    "RealLiteral", line: {{ *}}[[@LINE-42]], column:  14, indent: 1, spelling: "0.4", value: "4*10^-1", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 21, kind:           "Semi", line: {{ *}}[[@LINE-43]], column:  17, indent: 1, spelling: ";" }

+ 13 - 13
toolchain/lex/testdata/keywords.carbon

@@ -13,28 +13,28 @@
 // CHECK:STDOUT:   tokens:
 
    fn
-   // CHECK:STDOUT:   - { index: 1, kind:        'Fn', line: {{ *}}[[@LINE-1]], column: 4, indent: 4, spelling: 'fn', has_leading_space: true }
+   // CHECK:STDOUT:   - { index: 1, kind:        "Fn", line: {{ *}}[[@LINE-1]], column: 4, indent: 4, spelling: "fn", has_leading_space: true }
 
 // --- chain.carbon
 // CHECK:STDOUT: - filename: chain.carbon
 // CHECK:STDOUT:   tokens:
 
 and or not if else for return var break continue _
-// CHECK:STDOUT:   - { index:  1, kind:        'And', line: {{ *}}[[@LINE-1]], column:  1, indent: 1, spelling: 'and', has_leading_space: true }
-// CHECK:STDOUT:   - { index:  2, kind:         'Or', line: {{ *}}[[@LINE-2]], column:  5, indent: 1, spelling: 'or', has_leading_space: true }
-// CHECK:STDOUT:   - { index:  3, kind:        'Not', line: {{ *}}[[@LINE-3]], column:  8, indent: 1, spelling: 'not', has_leading_space: true }
-// CHECK:STDOUT:   - { index:  4, kind:         'If', line: {{ *}}[[@LINE-4]], column: 12, indent: 1, spelling: 'if', has_leading_space: true }
-// CHECK:STDOUT:   - { index:  5, kind:       'Else', line: {{ *}}[[@LINE-5]], column: 15, indent: 1, spelling: 'else', has_leading_space: true }
-// CHECK:STDOUT:   - { index:  6, kind:        'For', line: {{ *}}[[@LINE-6]], column: 20, indent: 1, spelling: 'for', has_leading_space: true }
-// CHECK:STDOUT:   - { index:  7, kind:     'Return', line: {{ *}}[[@LINE-7]], column: 24, indent: 1, spelling: 'return', has_leading_space: true }
-// CHECK:STDOUT:   - { index:  8, kind:        'Var', line: {{ *}}[[@LINE-8]], column: 31, indent: 1, spelling: 'var', has_leading_space: true }
-// CHECK:STDOUT:   - { index:  9, kind:      'Break', line: {{ *}}[[@LINE-9]], column: 35, indent: 1, spelling: 'break', has_leading_space: true }
-// CHECK:STDOUT:   - { index: 10, kind:   'Continue', line: {{ *}}[[@LINE-10]], column: 41, indent: 1, spelling: 'continue', has_leading_space: true }
-// CHECK:STDOUT:   - { index: 11, kind: 'Underscore', line: {{ *}}[[@LINE-11]], column: 50, indent: 1, spelling: '_', has_leading_space: true }
+// CHECK:STDOUT:   - { index:  1, kind:        "And", line: {{ *}}[[@LINE-1]], column:  1, indent: 1, spelling: "and", has_leading_space: true }
+// CHECK:STDOUT:   - { index:  2, kind:         "Or", line: {{ *}}[[@LINE-2]], column:  5, indent: 1, spelling: "or", has_leading_space: true }
+// CHECK:STDOUT:   - { index:  3, kind:        "Not", line: {{ *}}[[@LINE-3]], column:  8, indent: 1, spelling: "not", has_leading_space: true }
+// CHECK:STDOUT:   - { index:  4, kind:         "If", line: {{ *}}[[@LINE-4]], column: 12, indent: 1, spelling: "if", has_leading_space: true }
+// CHECK:STDOUT:   - { index:  5, kind:       "Else", line: {{ *}}[[@LINE-5]], column: 15, indent: 1, spelling: "else", has_leading_space: true }
+// CHECK:STDOUT:   - { index:  6, kind:        "For", line: {{ *}}[[@LINE-6]], column: 20, indent: 1, spelling: "for", has_leading_space: true }
+// CHECK:STDOUT:   - { index:  7, kind:     "Return", line: {{ *}}[[@LINE-7]], column: 24, indent: 1, spelling: "return", has_leading_space: true }
+// CHECK:STDOUT:   - { index:  8, kind:        "Var", line: {{ *}}[[@LINE-8]], column: 31, indent: 1, spelling: "var", has_leading_space: true }
+// CHECK:STDOUT:   - { index:  9, kind:      "Break", line: {{ *}}[[@LINE-9]], column: 35, indent: 1, spelling: "break", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 10, kind:   "Continue", line: {{ *}}[[@LINE-10]], column: 41, indent: 1, spelling: "continue", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 11, kind: "Underscore", line: {{ *}}[[@LINE-11]], column: 50, indent: 1, spelling: "_", has_leading_space: true }
 
 // --- notakeyword.carbon
 // CHECK:STDOUT: - filename: notakeyword.carbon
 // CHECK:STDOUT:   tokens:
 
 notakeyword
-// CHECK:STDOUT:   - { index: 1, kind: 'Identifier', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: 'notakeyword', identifier: 0, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 1, kind: "Identifier", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "notakeyword", identifier: 0, has_leading_space: true }

+ 6 - 6
toolchain/lex/testdata/multifile.carbon

@@ -12,15 +12,15 @@
 // CHECK:STDOUT: - filename: a.carbon
 // CHECK:STDOUT:   tokens:
 a;
-// CHECK:STDOUT:   - { index: 1, kind: 'Identifier', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: 'a', identifier: 0, has_leading_space: true }
-// CHECK:STDOUT:   - { index: 2, kind:       'Semi', line: {{ *}}[[@LINE-2]], column: 2, indent: 1, spelling: ';' }
+// CHECK:STDOUT:   - { index: 1, kind: "Identifier", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "a", identifier: 0, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 2, kind:       "Semi", line: {{ *}}[[@LINE-2]], column: 2, indent: 1, spelling: ";" }
 
 // --- b.carbon
 // CHECK:STDOUT: - filename: b.carbon
 // CHECK:STDOUT:   tokens:
 b;
-// CHECK:STDOUT:   - { index: 1, kind: 'Identifier', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: 'b', identifier: 0, has_leading_space: true }
-// CHECK:STDOUT:   - { index: 2, kind:       'Semi', line: {{ *}}[[@LINE-2]], column:   2, indent: 1, spelling: ';' }
+// CHECK:STDOUT:   - { index: 1, kind: "Identifier", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "b", identifier: 0, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 2, kind:       "Semi", line: {{ *}}[[@LINE-2]], column:   2, indent: 1, spelling: ";" }
 a;
-// CHECK:STDOUT:   - { index: 3, kind: 'Identifier', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: 'a', identifier: 1, has_leading_space: true }
-// CHECK:STDOUT:   - { index: 4, kind:       'Semi', line: {{ *}}[[@LINE-2]], column:   2, indent: 1, spelling: ';' }
+// CHECK:STDOUT:   - { index: 3, kind: "Identifier", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "a", identifier: 1, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 4, kind:       "Semi", line: {{ *}}[[@LINE-2]], column:   2, indent: 1, spelling: ";" }

+ 2 - 8
toolchain/lex/testdata/multiline_string_literals.carbon

@@ -35,13 +35,7 @@ a
 // CHECK:STDERR:
 // CHECK:STDOUT: - filename: fail_indent_mismatch.carbon
 // CHECK:STDOUT:   tokens:
-// CHECK:STDOUT:   - { index: 1, kind: 'StringLiteral', line: {{ *}}2, column: 3, indent: 3, spelling: ''''
-// CHECK:STDOUT: a
-// CHECK:STDOUT:   '''', value: `a
-// CHECK:STDOUT: `, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 1, kind: "StringLiteral", line: {{ *}}2, column: 3, indent: 3, spelling: "'''\na\n  '''", value: "a\n", has_leading_space: true }
 // CHECK:STDOUT: - filename: fail_quotes.carbon
 // CHECK:STDOUT:   tokens:
-// CHECK:STDOUT:   - { index: 1, kind: 'StringLiteral', line: {{ *}}2, column: 1, indent: 1, spelling: '"""
-// CHECK:STDOUT: a
-// CHECK:STDOUT: """', value: `a
-// CHECK:STDOUT: `, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 1, kind: "StringLiteral", line: {{ *}}2, column: 1, indent: 1, spelling: "\"\"\"\na\n\"\"\"", value: "a\n", has_leading_space: true }

+ 59 - 59
toolchain/lex/testdata/numeric_literals.carbon

@@ -14,79 +14,79 @@
 
 
 fn F() {
-// CHECK:STDOUT:   - { index:  1, kind:                 'Fn', line: {{ *}}[[@LINE-1]], column:  1, indent: 1, spelling: 'fn', has_leading_space: true }
-// CHECK:STDOUT:   - { index:  2, kind:         'Identifier', line: {{ *}}[[@LINE-2]], column:  4, indent: 1, spelling: 'F', identifier: 0, has_leading_space: true }
-// CHECK:STDOUT:   - { index:  3, kind:          'OpenParen', line: {{ *}}[[@LINE-3]], column:  5, indent: 1, spelling: '(', closing_token: 4 }
-// CHECK:STDOUT:   - { index:  4, kind:         'CloseParen', line: {{ *}}[[@LINE-4]], column:  6, indent: 1, spelling: ')', opening_token: 3 }
-// CHECK:STDOUT:   - { index:  5, kind:     'OpenCurlyBrace', line: {{ *}}[[@LINE-5]], column:  8, indent: 1, spelling: '{', closing_token: 54, has_leading_space: true }
+// CHECK:STDOUT:   - { index:  1, kind:                 "Fn", line: {{ *}}[[@LINE-1]], column:  1, indent: 1, spelling: "fn", has_leading_space: true }
+// CHECK:STDOUT:   - { index:  2, kind:         "Identifier", line: {{ *}}[[@LINE-2]], column:  4, indent: 1, spelling: "F", identifier: 0, has_leading_space: true }
+// CHECK:STDOUT:   - { index:  3, kind:          "OpenParen", line: {{ *}}[[@LINE-3]], column:  5, indent: 1, spelling: "(", closing_token: 4 }
+// CHECK:STDOUT:   - { index:  4, kind:         "CloseParen", line: {{ *}}[[@LINE-4]], column:  6, indent: 1, spelling: ")", opening_token: 3 }
+// CHECK:STDOUT:   - { index:  5, kind:     "OpenCurlyBrace", line: {{ *}}[[@LINE-5]], column:  8, indent: 1, spelling: "{", closing_token: 54, has_leading_space: true }
   // 8 and 9 trigger special behavior in APInt when mishandling signed versus
   // unsigned, so we pay extra attention to those.
   var ints: [i32; 5] = (
-  // CHECK:STDOUT:   - { index:  6, kind:                'Var', line: {{ *}}[[@LINE-1]], column:  3, indent: 3, spelling: 'var', has_leading_space: true }
-  // CHECK:STDOUT:   - { index:  7, kind:         'Identifier', line: {{ *}}[[@LINE-2]], column:  7, indent: 3, spelling: 'ints', identifier: 1, has_leading_space: true }
-  // CHECK:STDOUT:   - { index:  8, kind:              'Colon', line: {{ *}}[[@LINE-3]], column: 11, indent: 3, spelling: ':' }
-  // CHECK:STDOUT:   - { index:  9, kind:  'OpenSquareBracket', line: {{ *}}[[@LINE-4]], column: 13, indent: 3, spelling: '[', closing_token: 13, has_leading_space: true }
-  // CHECK:STDOUT:   - { index: 10, kind:     'IntTypeLiteral', line: {{ *}}[[@LINE-5]], column: 14, indent: 3, spelling: 'i32' }
-  // CHECK:STDOUT:   - { index: 11, kind:               'Semi', line: {{ *}}[[@LINE-6]], column: 17, indent: 3, spelling: ';' }
-  // CHECK:STDOUT:   - { index: 12, kind:         'IntLiteral', line: {{ *}}[[@LINE-7]], column: 19, indent: 3, spelling: '5', value: `5`, has_leading_space: true }
-  // CHECK:STDOUT:   - { index: 13, kind: 'CloseSquareBracket', line: {{ *}}[[@LINE-8]], column: 20, indent: 3, spelling: ']', opening_token: 9 }
-  // CHECK:STDOUT:   - { index: 14, kind:              'Equal', line: {{ *}}[[@LINE-9]], column: 22, indent: 3, spelling: '=', has_leading_space: true }
-  // CHECK:STDOUT:   - { index: 15, kind:          'OpenParen', line: {{ *}}[[@LINE-10]], column: 24, indent: 3, spelling: '(', closing_token: 26, has_leading_space: true }
+  // CHECK:STDOUT:   - { index:  6, kind:                "Var", line: {{ *}}[[@LINE-1]], column:  3, indent: 3, spelling: "var", has_leading_space: true }
+  // CHECK:STDOUT:   - { index:  7, kind:         "Identifier", line: {{ *}}[[@LINE-2]], column:  7, indent: 3, spelling: "ints", identifier: 1, has_leading_space: true }
+  // CHECK:STDOUT:   - { index:  8, kind:              "Colon", line: {{ *}}[[@LINE-3]], column: 11, indent: 3, spelling: ":" }
+  // CHECK:STDOUT:   - { index:  9, kind:  "OpenSquareBracket", line: {{ *}}[[@LINE-4]], column: 13, indent: 3, spelling: "[", closing_token: 13, has_leading_space: true }
+  // CHECK:STDOUT:   - { index: 10, kind:     "IntTypeLiteral", line: {{ *}}[[@LINE-5]], column: 14, indent: 3, spelling: "i32" }
+  // CHECK:STDOUT:   - { index: 11, kind:               "Semi", line: {{ *}}[[@LINE-6]], column: 17, indent: 3, spelling: ";" }
+  // CHECK:STDOUT:   - { index: 12, kind:         "IntLiteral", line: {{ *}}[[@LINE-7]], column: 19, indent: 3, spelling: "5", value: "5", has_leading_space: true }
+  // CHECK:STDOUT:   - { index: 13, kind: "CloseSquareBracket", line: {{ *}}[[@LINE-8]], column: 20, indent: 3, spelling: "]", opening_token: 9 }
+  // CHECK:STDOUT:   - { index: 14, kind:              "Equal", line: {{ *}}[[@LINE-9]], column: 22, indent: 3, spelling: "=", has_leading_space: true }
+  // CHECK:STDOUT:   - { index: 15, kind:          "OpenParen", line: {{ *}}[[@LINE-10]], column: 24, indent: 3, spelling: "(", closing_token: 26, has_leading_space: true }
     8,
-    // CHECK:STDOUT:   - { index: 16, kind:         'IntLiteral', line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: '8', value: `8`, has_leading_space: true }
-    // CHECK:STDOUT:   - { index: 17, kind:              'Comma', line: {{ *}}[[@LINE-2]], column:  6, indent: 5, spelling: ',' }
+    // CHECK:STDOUT:   - { index: 16, kind:         "IntLiteral", line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: "8", value: "8", has_leading_space: true }
+    // CHECK:STDOUT:   - { index: 17, kind:              "Comma", line: {{ *}}[[@LINE-2]], column:  6, indent: 5, spelling: "," }
     9,
-    // CHECK:STDOUT:   - { index: 18, kind:         'IntLiteral', line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: '9', value: `9`, has_leading_space: true }
-    // CHECK:STDOUT:   - { index: 19, kind:              'Comma', line: {{ *}}[[@LINE-2]], column:  6, indent: 5, spelling: ',' }
+    // CHECK:STDOUT:   - { index: 18, kind:         "IntLiteral", line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: "9", value: "9", has_leading_space: true }
+    // CHECK:STDOUT:   - { index: 19, kind:              "Comma", line: {{ *}}[[@LINE-2]], column:  6, indent: 5, spelling: "," }
     0x8,
-    // CHECK:STDOUT:   - { index: 20, kind:         'IntLiteral', line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: '0x8', value: `8`, has_leading_space: true }
-    // CHECK:STDOUT:   - { index: 21, kind:              'Comma', line: {{ *}}[[@LINE-2]], column:  8, indent: 5, spelling: ',' }
+    // CHECK:STDOUT:   - { index: 20, kind:         "IntLiteral", line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: "0x8", value: "8", has_leading_space: true }
+    // CHECK:STDOUT:   - { index: 21, kind:              "Comma", line: {{ *}}[[@LINE-2]], column:  8, indent: 5, spelling: "," }
     0b1000,
-    // CHECK:STDOUT:   - { index: 22, kind:         'IntLiteral', line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: '0b1000', value: `8`, has_leading_space: true }
-    // CHECK:STDOUT:   - { index: 23, kind:              'Comma', line: {{ *}}[[@LINE-2]], column: 11, indent: 5, spelling: ',' }
+    // CHECK:STDOUT:   - { index: 22, kind:         "IntLiteral", line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: "0b1000", value: "8", has_leading_space: true }
+    // CHECK:STDOUT:   - { index: 23, kind:              "Comma", line: {{ *}}[[@LINE-2]], column: 11, indent: 5, spelling: "," }
     39999999999999999993,
-    // CHECK:STDOUT:   - { index: 24, kind:         'IntLiteral', line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: '39999999999999999993', value: `39999999999999999993`, has_leading_space: true }
-    // CHECK:STDOUT:   - { index: 25, kind:              'Comma', line: {{ *}}[[@LINE-2]], column: 25, indent: 5, spelling: ',' }
+    // CHECK:STDOUT:   - { index: 24, kind:         "IntLiteral", line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: "39999999999999999993", value: "39999999999999999993", has_leading_space: true }
+    // CHECK:STDOUT:   - { index: 25, kind:              "Comma", line: {{ *}}[[@LINE-2]], column: 25, indent: 5, spelling: "," }
   );
-  // CHECK:STDOUT:   - { index: 26, kind:         'CloseParen', line: {{ *}}[[@LINE-1]], column:  3, indent: 3, spelling: ')', opening_token: 15, has_leading_space: true }
-  // CHECK:STDOUT:   - { index: 27, kind:               'Semi', line: {{ *}}[[@LINE-2]], column:  4, indent: 3, spelling: ';' }
+  // CHECK:STDOUT:   - { index: 26, kind:         "CloseParen", line: {{ *}}[[@LINE-1]], column:  3, indent: 3, spelling: ")", opening_token: 15, has_leading_space: true }
+  // CHECK:STDOUT:   - { index: 27, kind:               "Semi", line: {{ *}}[[@LINE-2]], column:  4, indent: 3, spelling: ";" }
   var floats: [f64; 7] = (
-  // CHECK:STDOUT:   - { index: 28, kind:                'Var', line: {{ *}}[[@LINE-1]], column:  3, indent: 3, spelling: 'var', has_leading_space: true }
-  // CHECK:STDOUT:   - { index: 29, kind:         'Identifier', line: {{ *}}[[@LINE-2]], column:  7, indent: 3, spelling: 'floats', identifier: 2, has_leading_space: true }
-  // CHECK:STDOUT:   - { index: 30, kind:              'Colon', line: {{ *}}[[@LINE-3]], column: 13, indent: 3, spelling: ':' }
-  // CHECK:STDOUT:   - { index: 31, kind:  'OpenSquareBracket', line: {{ *}}[[@LINE-4]], column: 15, indent: 3, spelling: '[', closing_token: 35, has_leading_space: true }
-  // CHECK:STDOUT:   - { index: 32, kind:   'FloatTypeLiteral', line: {{ *}}[[@LINE-5]], column: 16, indent: 3, spelling: 'f64' }
-  // CHECK:STDOUT:   - { index: 33, kind:               'Semi', line: {{ *}}[[@LINE-6]], column: 19, indent: 3, spelling: ';' }
-  // CHECK:STDOUT:   - { index: 34, kind:         'IntLiteral', line: {{ *}}[[@LINE-7]], column: 21, indent: 3, spelling: '7', value: `7`, has_leading_space: true }
-  // CHECK:STDOUT:   - { index: 35, kind: 'CloseSquareBracket', line: {{ *}}[[@LINE-8]], column: 22, indent: 3, spelling: ']', opening_token: 31 }
-  // CHECK:STDOUT:   - { index: 36, kind:              'Equal', line: {{ *}}[[@LINE-9]], column: 24, indent: 3, spelling: '=', has_leading_space: true }
-  // CHECK:STDOUT:   - { index: 37, kind:          'OpenParen', line: {{ *}}[[@LINE-10]], column: 26, indent: 3, spelling: '(', closing_token: 52, has_leading_space: true }
+  // CHECK:STDOUT:   - { index: 28, kind:                "Var", line: {{ *}}[[@LINE-1]], column:  3, indent: 3, spelling: "var", has_leading_space: true }
+  // CHECK:STDOUT:   - { index: 29, kind:         "Identifier", line: {{ *}}[[@LINE-2]], column:  7, indent: 3, spelling: "floats", identifier: 2, has_leading_space: true }
+  // CHECK:STDOUT:   - { index: 30, kind:              "Colon", line: {{ *}}[[@LINE-3]], column: 13, indent: 3, spelling: ":" }
+  // CHECK:STDOUT:   - { index: 31, kind:  "OpenSquareBracket", line: {{ *}}[[@LINE-4]], column: 15, indent: 3, spelling: "[", closing_token: 35, has_leading_space: true }
+  // CHECK:STDOUT:   - { index: 32, kind:   "FloatTypeLiteral", line: {{ *}}[[@LINE-5]], column: 16, indent: 3, spelling: "f64" }
+  // CHECK:STDOUT:   - { index: 33, kind:               "Semi", line: {{ *}}[[@LINE-6]], column: 19, indent: 3, spelling: ";" }
+  // CHECK:STDOUT:   - { index: 34, kind:         "IntLiteral", line: {{ *}}[[@LINE-7]], column: 21, indent: 3, spelling: "7", value: "7", has_leading_space: true }
+  // CHECK:STDOUT:   - { index: 35, kind: "CloseSquareBracket", line: {{ *}}[[@LINE-8]], column: 22, indent: 3, spelling: "]", opening_token: 31 }
+  // CHECK:STDOUT:   - { index: 36, kind:              "Equal", line: {{ *}}[[@LINE-9]], column: 24, indent: 3, spelling: "=", has_leading_space: true }
+  // CHECK:STDOUT:   - { index: 37, kind:          "OpenParen", line: {{ *}}[[@LINE-10]], column: 26, indent: 3, spelling: "(", closing_token: 52, has_leading_space: true }
     0.9,
-    // CHECK:STDOUT:   - { index: 38, kind:        'RealLiteral', line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: '0.9', value: `9*10^-1`, has_leading_space: true }
-    // CHECK:STDOUT:   - { index: 39, kind:              'Comma', line: {{ *}}[[@LINE-2]], column:  8, indent: 5, spelling: ',' }
+    // CHECK:STDOUT:   - { index: 38, kind:        "RealLiteral", line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: "0.9", value: "9*10^-1", has_leading_space: true }
+    // CHECK:STDOUT:   - { index: 39, kind:              "Comma", line: {{ *}}[[@LINE-2]], column:  8, indent: 5, spelling: "," }
     8.0,
-    // CHECK:STDOUT:   - { index: 40, kind:        'RealLiteral', line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: '8.0', value: `80*10^-1`, has_leading_space: true }
-    // CHECK:STDOUT:   - { index: 41, kind:              'Comma', line: {{ *}}[[@LINE-2]], column:  8, indent: 5, spelling: ',' }
+    // CHECK:STDOUT:   - { index: 40, kind:        "RealLiteral", line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: "8.0", value: "80*10^-1", has_leading_space: true }
+    // CHECK:STDOUT:   - { index: 41, kind:              "Comma", line: {{ *}}[[@LINE-2]], column:  8, indent: 5, spelling: "," }
     80.0,
-    // CHECK:STDOUT:   - { index: 42, kind:        'RealLiteral', line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: '80.0', value: `800*10^-1`, has_leading_space: true }
-    // CHECK:STDOUT:   - { index: 43, kind:              'Comma', line: {{ *}}[[@LINE-2]], column:  9, indent: 5, spelling: ',' }
+    // CHECK:STDOUT:   - { index: 42, kind:        "RealLiteral", line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: "80.0", value: "800*10^-1", has_leading_space: true }
+    // CHECK:STDOUT:   - { index: 43, kind:              "Comma", line: {{ *}}[[@LINE-2]], column:  9, indent: 5, spelling: "," }
     1.0e7,
-    // CHECK:STDOUT:   - { index: 44, kind:        'RealLiteral', line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: '1.0e7', value: `10*10^6`, has_leading_space: true }
-    // CHECK:STDOUT:   - { index: 45, kind:              'Comma', line: {{ *}}[[@LINE-2]], column: 10, indent: 5, spelling: ',' }
+    // CHECK:STDOUT:   - { index: 44, kind:        "RealLiteral", line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: "1.0e7", value: "10*10^6", has_leading_space: true }
+    // CHECK:STDOUT:   - { index: 45, kind:              "Comma", line: {{ *}}[[@LINE-2]], column: 10, indent: 5, spelling: "," }
     1.0e8,
-    // CHECK:STDOUT:   - { index: 46, kind:        'RealLiteral', line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: '1.0e8', value: `10*10^7`, has_leading_space: true }
-    // CHECK:STDOUT:   - { index: 47, kind:              'Comma', line: {{ *}}[[@LINE-2]], column: 10, indent: 5, spelling: ',' }
+    // CHECK:STDOUT:   - { index: 46, kind:        "RealLiteral", line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: "1.0e8", value: "10*10^7", has_leading_space: true }
+    // CHECK:STDOUT:   - { index: 47, kind:              "Comma", line: {{ *}}[[@LINE-2]], column: 10, indent: 5, spelling: "," }
     1.0e-8,
-    // CHECK:STDOUT:   - { index: 48, kind:        'RealLiteral', line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: '1.0e-8', value: `10*10^-9`, has_leading_space: true }
-    // CHECK:STDOUT:   - { index: 49, kind:              'Comma', line: {{ *}}[[@LINE-2]], column: 11, indent: 5, spelling: ',' }
+    // CHECK:STDOUT:   - { index: 48, kind:        "RealLiteral", line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: "1.0e-8", value: "10*10^-9", has_leading_space: true }
+    // CHECK:STDOUT:   - { index: 49, kind:              "Comma", line: {{ *}}[[@LINE-2]], column: 11, indent: 5, spelling: "," }
     39999999999999999993.0e39999999999999999993,
-    // CHECK:STDOUT:   - { index: 50, kind:        'RealLiteral', line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: '39999999999999999993.0e39999999999999999993', value: `399999999999999999930*10^39999999999999999992`, has_leading_space: true }
-    // CHECK:STDOUT:   - { index: 51, kind:              'Comma', line: {{ *}}[[@LINE-2]], column: 48, indent: 5, spelling: ',' }
+    // CHECK:STDOUT:   - { index: 50, kind:        "RealLiteral", line: {{ *}}[[@LINE-1]], column:  5, indent: 5, spelling: "39999999999999999993.0e39999999999999999993", value: "399999999999999999930*10^39999999999999999992", has_leading_space: true }
+    // CHECK:STDOUT:   - { index: 51, kind:              "Comma", line: {{ *}}[[@LINE-2]], column: 48, indent: 5, spelling: "," }
   );
-  // CHECK:STDOUT:   - { index: 52, kind:         'CloseParen', line: {{ *}}[[@LINE-1]], column:  3, indent: 3, spelling: ')', opening_token: 37, has_leading_space: true }
-  // CHECK:STDOUT:   - { index: 53, kind:               'Semi', line: {{ *}}[[@LINE-2]], column:  4, indent: 3, spelling: ';' }
+  // CHECK:STDOUT:   - { index: 52, kind:         "CloseParen", line: {{ *}}[[@LINE-1]], column:  3, indent: 3, spelling: ")", opening_token: 37, has_leading_space: true }
+  // CHECK:STDOUT:   - { index: 53, kind:               "Semi", line: {{ *}}[[@LINE-2]], column:  4, indent: 3, spelling: ";" }
 }
-// CHECK:STDOUT:   - { index: 54, kind:    'CloseCurlyBrace', line: {{ *}}[[@LINE-1]], column:  1, indent: 1, spelling: '}', opening_token: 5, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 54, kind:    "CloseCurlyBrace", line: {{ *}}[[@LINE-1]], column:  1, indent: 1, spelling: "}", opening_token: 5, has_leading_space: true }
 
 
 // --- fail_binary_real.carbon
@@ -98,7 +98,7 @@ fn F() {
 // CHECK:STDERR:    ^
 // CHECK:STDERR:
 0b1.0
-// CHECK:STDOUT:   - { index: 1, kind: 'RealLiteral', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: '0b1.0', value: `2*2^-1`, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 1, kind: "RealLiteral", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "0b1.0", value: "2*2^-1", has_leading_space: true }
 
 // --- fail_wrong_real_exponent.carbon
 // CHECK:STDOUT: - filename: fail_wrong_real_exponent.carbon
@@ -109,7 +109,7 @@ fn F() {
 // CHECK:STDERR:    ^
 // CHECK:STDERR:
 1.0r3
-// CHECK:STDOUT:   - { index: 1, kind:     'Error', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: '1.0r3', has_leading_space: true }
+// CHECK:STDOUT:   - { index: 1, kind:     "Error", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "1.0r3", has_leading_space: true }
 
 // --- fail_invalid_digit.carbon
 // CHECK:STDOUT: - filename: fail_invalid_digit.carbon
@@ -120,7 +120,7 @@ fn F() {
 // CHECK:STDERR:    ^
 // CHECK:STDERR:
 0x1a
-// CHECK:STDOUT:   - { index: 1, kind:     'Error', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: '0x1a', has_leading_space: true }
+// CHECK:STDOUT:   - { index: 1, kind:     "Error", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "0x1a", has_leading_space: true }
 
 // --- fail_invalid_separator.carbon
 // CHECK:STDOUT: - filename: fail_invalid_separator.carbon
@@ -131,7 +131,7 @@ fn F() {
 // CHECK:STDERR:  ^
 // CHECK:STDERR:
 1__2
-// CHECK:STDOUT:   - { index: 1, kind: 'IntLiteral', line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: '1__2', value: `12`, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 1, kind: "IntLiteral", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "1__2", value: "12", has_leading_space: true }
 
 // --- fail_unknown_base.carbon
 // CHECK:STDOUT: - filename: fail_unknown_base.carbon
@@ -142,4 +142,4 @@ fn F() {
 // CHECK:STDERR: ^
 // CHECK:STDERR:
 05
-// CHECK:STDOUT:   - { index: 1, kind:     'Error', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: '05', has_leading_space: true }
+// CHECK:STDOUT:   - { index: 1, kind:     "Error", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "05", has_leading_space: true }

+ 4 - 4
toolchain/lex/testdata/printing_digit_padding.carbon

@@ -11,10 +11,10 @@
 // CHECK:STDOUT:   tokens:
 
 ;
-// CHECK:STDOUT:   - { index: 1, kind:      'Semi', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: ';', has_leading_space: true }
+// CHECK:STDOUT:   - { index: 1, kind:      "Semi", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: ";", has_leading_space: true }
 
 // Test digit padding with values of 9, 10, and 11.
         ;;;
-        // CHECK:STDOUT:   - { index: 2, kind:      'Semi', line: {{ *}}[[@LINE-1]], column:   9, indent: 9, spelling: ';', has_leading_space: true }
-        // CHECK:STDOUT:   - { index: 3, kind:      'Semi', line: {{ *}}[[@LINE-2]], column:  10, indent: 9, spelling: ';' }
-        // CHECK:STDOUT:   - { index: 4, kind:      'Semi', line: {{ *}}[[@LINE-3]], column:  11, indent: 9, spelling: ';' }
+        // CHECK:STDOUT:   - { index: 2, kind:      "Semi", line: {{ *}}[[@LINE-1]], column:   9, indent: 9, spelling: ";", has_leading_space: true }
+        // CHECK:STDOUT:   - { index: 3, kind:      "Semi", line: {{ *}}[[@LINE-2]], column:  10, indent: 9, spelling: ";" }
+        // CHECK:STDOUT:   - { index: 4, kind:      "Semi", line: {{ *}}[[@LINE-3]], column:  11, indent: 9, spelling: ";" }

+ 1 - 1
toolchain/lex/testdata/printing_integer_literal.carbon

@@ -11,4 +11,4 @@
 // CHECK:STDOUT:   tokens:
 
 123
-// CHECK:STDOUT:   - { index: 1, kind: 'IntLiteral', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: '123', value: `123`, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 1, kind: "IntLiteral", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "123", value: "123", has_leading_space: true }

+ 1 - 1
toolchain/lex/testdata/printing_real_literal.carbon

@@ -11,4 +11,4 @@
 // CHECK:STDOUT:   tokens:
 
 2.5
-// CHECK:STDOUT:   - { index: 1, kind: 'RealLiteral', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: '2.5', value: `25*10^-1`, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 1, kind: "RealLiteral", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "2.5", value: "25*10^-1", has_leading_space: true }

+ 1 - 1
toolchain/lex/testdata/printing_token.carbon

@@ -11,4 +11,4 @@
 // CHECK:STDOUT:   tokens:
 
 0x9
-// CHECK:STDOUT:   - { index: 1, kind: 'IntLiteral', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: '0x9', value: `9`, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 1, kind: "IntLiteral", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "0x9", value: "9", has_leading_space: true }

+ 6 - 6
toolchain/lex/testdata/raw_identifier.carbon

@@ -12,24 +12,24 @@
 
 // A non-keyword identifier.
 r#foo
-// CHECK:STDOUT:   - { index: 1, kind:          'Identifier', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: 'foo', identifier: 1, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 1, kind:          "Identifier", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "foo", identifier: 1, has_leading_space: true }
 
 // The same non-keyword identifier, for comparison.
 foo
-// CHECK:STDOUT:   - { index: 2, kind:          'Identifier', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: 'foo', identifier: 1, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 2, kind:          "Identifier", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "foo", identifier: 1, has_leading_space: true }
 
 // A keyword as a raw identifier.
 r#self
-// CHECK:STDOUT:   - { index: 3, kind:          'Identifier', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: 'self', identifier: 2, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 3, kind:          "Identifier", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "self", identifier: 2, has_leading_space: true }
 
 // The same keyword, for comparison.
 self
-// CHECK:STDOUT:   - { index: 4, kind: 'SelfValueIdentifier', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: 'self', has_leading_space: true }
+// CHECK:STDOUT:   - { index: 4, kind: "SelfValueIdentifier", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "self", has_leading_space: true }
 
 // A type literal as a raw identifier.
 r#i32
-// CHECK:STDOUT:   - { index: 5, kind:          'Identifier', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: 'i32', identifier: 3, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 5, kind:          "Identifier", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "i32", identifier: 3, has_leading_space: true }
 
 // The same type literal, for comparison.
 i32
-// CHECK:STDOUT:   - { index: 6, kind:      'IntTypeLiteral', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: 'i32', has_leading_space: true }
+// CHECK:STDOUT:   - { index: 6, kind:      "IntTypeLiteral", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "i32", has_leading_space: true }

+ 30 - 30
toolchain/lex/testdata/repeated_tuple_index.carbon

@@ -11,41 +11,41 @@
 // CHECK:STDOUT:   tokens:
 
 x.0.1.2.3.foo.4.5
-// CHECK:STDOUT:   - { index:  1, kind:    'Identifier', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: 'x', identifier: 0, has_leading_space: true }
-// CHECK:STDOUT:   - { index:  2, kind:        'Period', line: {{ *}}[[@LINE-2]], column:   2, indent: 1, spelling: '.' }
-// CHECK:STDOUT:   - { index:  3, kind:    'IntLiteral', line: {{ *}}[[@LINE-3]], column:   3, indent: 1, spelling: '0', value: `0` }
-// CHECK:STDOUT:   - { index:  4, kind:        'Period', line: {{ *}}[[@LINE-4]], column:   4, indent: 1, spelling: '.' }
-// CHECK:STDOUT:   - { index:  5, kind:    'IntLiteral', line: {{ *}}[[@LINE-5]], column:   5, indent: 1, spelling: '1', value: `1` }
-// CHECK:STDOUT:   - { index:  6, kind:        'Period', line: {{ *}}[[@LINE-6]], column:   6, indent: 1, spelling: '.' }
-// CHECK:STDOUT:   - { index:  7, kind:    'IntLiteral', line: {{ *}}[[@LINE-7]], column:   7, indent: 1, spelling: '2', value: `2` }
-// CHECK:STDOUT:   - { index:  8, kind:        'Period', line: {{ *}}[[@LINE-8]], column:   8, indent: 1, spelling: '.' }
-// CHECK:STDOUT:   - { index:  9, kind:    'IntLiteral', line: {{ *}}[[@LINE-9]], column:   9, indent: 1, spelling: '3', value: `3` }
-// CHECK:STDOUT:   - { index: 10, kind:        'Period', line: {{ *}}[[@LINE-10]], column:  10, indent: 1, spelling: '.' }
-// CHECK:STDOUT:   - { index: 11, kind:    'Identifier', line: {{ *}}[[@LINE-11]], column:  11, indent: 1, spelling: 'foo', identifier: 1 }
-// CHECK:STDOUT:   - { index: 12, kind:        'Period', line: {{ *}}[[@LINE-12]], column:  14, indent: 1, spelling: '.' }
-// CHECK:STDOUT:   - { index: 13, kind:    'IntLiteral', line: {{ *}}[[@LINE-13]], column:  15, indent: 1, spelling: '4', value: `4` }
-// CHECK:STDOUT:   - { index: 14, kind:        'Period', line: {{ *}}[[@LINE-14]], column:  16, indent: 1, spelling: '.' }
-// CHECK:STDOUT:   - { index: 15, kind:    'IntLiteral', line: {{ *}}[[@LINE-15]], column:  17, indent: 1, spelling: '5', value: `5` }
+// CHECK:STDOUT:   - { index:  1, kind:    "Identifier", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "x", identifier: 0, has_leading_space: true }
+// CHECK:STDOUT:   - { index:  2, kind:        "Period", line: {{ *}}[[@LINE-2]], column:   2, indent: 1, spelling: "." }
+// CHECK:STDOUT:   - { index:  3, kind:    "IntLiteral", line: {{ *}}[[@LINE-3]], column:   3, indent: 1, spelling: "0", value: "0" }
+// CHECK:STDOUT:   - { index:  4, kind:        "Period", line: {{ *}}[[@LINE-4]], column:   4, indent: 1, spelling: "." }
+// CHECK:STDOUT:   - { index:  5, kind:    "IntLiteral", line: {{ *}}[[@LINE-5]], column:   5, indent: 1, spelling: "1", value: "1" }
+// CHECK:STDOUT:   - { index:  6, kind:        "Period", line: {{ *}}[[@LINE-6]], column:   6, indent: 1, spelling: "." }
+// CHECK:STDOUT:   - { index:  7, kind:    "IntLiteral", line: {{ *}}[[@LINE-7]], column:   7, indent: 1, spelling: "2", value: "2" }
+// CHECK:STDOUT:   - { index:  8, kind:        "Period", line: {{ *}}[[@LINE-8]], column:   8, indent: 1, spelling: "." }
+// CHECK:STDOUT:   - { index:  9, kind:    "IntLiteral", line: {{ *}}[[@LINE-9]], column:   9, indent: 1, spelling: "3", value: "3" }
+// CHECK:STDOUT:   - { index: 10, kind:        "Period", line: {{ *}}[[@LINE-10]], column:  10, indent: 1, spelling: "." }
+// CHECK:STDOUT:   - { index: 11, kind:    "Identifier", line: {{ *}}[[@LINE-11]], column:  11, indent: 1, spelling: "foo", identifier: 1 }
+// CHECK:STDOUT:   - { index: 12, kind:        "Period", line: {{ *}}[[@LINE-12]], column:  14, indent: 1, spelling: "." }
+// CHECK:STDOUT:   - { index: 13, kind:    "IntLiteral", line: {{ *}}[[@LINE-13]], column:  15, indent: 1, spelling: "4", value: "4" }
+// CHECK:STDOUT:   - { index: 14, kind:        "Period", line: {{ *}}[[@LINE-14]], column:  16, indent: 1, spelling: "." }
+// CHECK:STDOUT:   - { index: 15, kind:    "IntLiteral", line: {{ *}}[[@LINE-15]], column:  17, indent: 1, spelling: "5", value: "5" }
 
 1.2.3.4
-// CHECK:STDOUT:   - { index: 16, kind:   'RealLiteral', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: '1.2', value: `12*10^-1`, has_leading_space: true }
-// CHECK:STDOUT:   - { index: 17, kind:        'Period', line: {{ *}}[[@LINE-2]], column:   4, indent: 1, spelling: '.' }
-// CHECK:STDOUT:   - { index: 18, kind:    'IntLiteral', line: {{ *}}[[@LINE-3]], column:   5, indent: 1, spelling: '3', value: `3` }
-// CHECK:STDOUT:   - { index: 19, kind:        'Period', line: {{ *}}[[@LINE-4]], column:   6, indent: 1, spelling: '.' }
-// CHECK:STDOUT:   - { index: 20, kind:    'IntLiteral', line: {{ *}}[[@LINE-5]], column:   7, indent: 1, spelling: '4', value: `4` }
+// CHECK:STDOUT:   - { index: 16, kind:   "RealLiteral", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "1.2", value: "12*10^-1", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 17, kind:        "Period", line: {{ *}}[[@LINE-2]], column:   4, indent: 1, spelling: "." }
+// CHECK:STDOUT:   - { index: 18, kind:    "IntLiteral", line: {{ *}}[[@LINE-3]], column:   5, indent: 1, spelling: "3", value: "3" }
+// CHECK:STDOUT:   - { index: 19, kind:        "Period", line: {{ *}}[[@LINE-4]], column:   6, indent: 1, spelling: "." }
+// CHECK:STDOUT:   - { index: 20, kind:    "IntLiteral", line: {{ *}}[[@LINE-5]], column:   7, indent: 1, spelling: "4", value: "4" }
 
 tuple.1.2
-// CHECK:STDOUT:   - { index: 21, kind:    'Identifier', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: 'tuple', identifier: 2, has_leading_space: true }
-// CHECK:STDOUT:   - { index: 22, kind:        'Period', line: {{ *}}[[@LINE-2]], column:   6, indent: 1, spelling: '.' }
-// CHECK:STDOUT:   - { index: 23, kind:    'IntLiteral', line: {{ *}}[[@LINE-3]], column:   7, indent: 1, spelling: '1', value: `1` }
-// CHECK:STDOUT:   - { index: 24, kind:        'Period', line: {{ *}}[[@LINE-4]], column:   8, indent: 1, spelling: '.' }
-// CHECK:STDOUT:   - { index: 25, kind:    'IntLiteral', line: {{ *}}[[@LINE-5]], column:   9, indent: 1, spelling: '2', value: `2` }
+// CHECK:STDOUT:   - { index: 21, kind:    "Identifier", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "tuple", identifier: 2, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 22, kind:        "Period", line: {{ *}}[[@LINE-2]], column:   6, indent: 1, spelling: "." }
+// CHECK:STDOUT:   - { index: 23, kind:    "IntLiteral", line: {{ *}}[[@LINE-3]], column:   7, indent: 1, spelling: "1", value: "1" }
+// CHECK:STDOUT:   - { index: 24, kind:        "Period", line: {{ *}}[[@LINE-4]], column:   8, indent: 1, spelling: "." }
+// CHECK:STDOUT:   - { index: 25, kind:    "IntLiteral", line: {{ *}}[[@LINE-5]], column:   9, indent: 1, spelling: "2", value: "2" }
 
 tuple . 1.2
-// CHECK:STDOUT:   - { index: 26, kind:    'Identifier', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: 'tuple', identifier: 2, has_leading_space: true }
-// CHECK:STDOUT:   - { index: 27, kind:        'Period', line: {{ *}}[[@LINE-2]], column:   7, indent: 1, spelling: '.', has_leading_space: true }
-// CHECK:STDOUT:   - { index: 28, kind:   'RealLiteral', line: {{ *}}[[@LINE-3]], column:   9, indent: 1, spelling: '1.2', value: `12*10^-1`, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 26, kind:    "Identifier", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "tuple", identifier: 2, has_leading_space: true }
+// CHECK:STDOUT:   - { index: 27, kind:        "Period", line: {{ *}}[[@LINE-2]], column:   7, indent: 1, spelling: ".", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 28, kind:   "RealLiteral", line: {{ *}}[[@LINE-3]], column:   9, indent: 1, spelling: "1.2", value: "12*10^-1", has_leading_space: true }
 
 "hello"1.2
-// CHECK:STDOUT:   - { index: 29, kind: 'StringLiteral', line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: '"hello"', value: `hello`, has_leading_space: true }
-// CHECK:STDOUT:   - { index: 30, kind:   'RealLiteral', line: {{ *}}[[@LINE-2]], column:   8, indent: 1, spelling: '1.2', value: `12*10^-1` }
+// CHECK:STDOUT:   - { index: 29, kind: "StringLiteral", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "\"hello\"", value: "hello", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 30, kind:   "RealLiteral", line: {{ *}}[[@LINE-2]], column:   8, indent: 1, spelling: "1.2", value: "12*10^-1" }

BIN=BIN
toolchain/lex/testdata/string_literals.carbon


+ 13 - 11
toolchain/lex/tokenized_buffer.cpp

@@ -254,36 +254,38 @@ auto TokenizedBuffer::PrintToken(llvm::raw_ostream& output_stream,
   // and get the quotes included.
   output_stream << llvm::formatv(
       "  - { index: {0}, kind: {1}, line: {2}, column: {3}, indent: {4}, "
-      "spelling: '{5}'",
+      "spelling: \"{5}\"",
       llvm::format_decimal(token_index, widths.index),
       llvm::right_justify(
-          llvm::formatv("'{0}'", token_info.kind().name()).str(),
+          llvm::formatv("\"{0}\"", token_info.kind().name()).str(),
           widths.kind + 2),
       llvm::format_decimal(GetLineNumber(token), widths.line),
       llvm::format_decimal(GetColumnNumber(token), widths.column),
       llvm::format_decimal(GetIndentColumnNumber(line_index), widths.indent),
-      token_text);
+      FormatEscaped(token_text, /*use_hex_escapes=*/true));
 
   switch (token_info.kind()) {
     case TokenKind::Identifier:
       output_stream << ", identifier: " << GetIdentifier(token).index;
       break;
     case TokenKind::IntLiteral:
-      output_stream << ", value: `";
+      output_stream << ", value: \"";
       value_stores_->ints()
           .Get(GetIntLiteral(token))
           .print(output_stream, /*isSigned=*/false);
-      output_stream << "`";
+      output_stream << "\"";
       break;
     case TokenKind::RealLiteral:
-      output_stream << ", value: `"
-                    << value_stores_->reals().Get(GetRealLiteral(token)) << "`";
+      output_stream << ", value: \""
+                    << value_stores_->reals().Get(GetRealLiteral(token))
+                    << "\"";
       break;
     case TokenKind::StringLiteral:
-      output_stream << ", value: `"
-                    << value_stores_->string_literal_values().Get(
-                           GetStringLiteralValue(token))
-                    << "`";
+      output_stream << ", value: \""
+                    << FormatEscaped(value_stores_->string_literal_values().Get(
+                                         GetStringLiteralValue(token)),
+                                     /*use_hex_escapes=*/true)
+                    << "\"";
       break;
     default:
       if (token_info.kind().is_opening_symbol()) {

+ 9 - 11
toolchain/sem_ir/formatter.cpp

@@ -414,10 +414,10 @@ class FormatterImpl {
     }
 
     if (fn.builtin_function_kind != BuiltinFunctionKind::None) {
-      out_ << " = \"";
-      out_.write_escaped(fn.builtin_function_kind.name(),
-                         /*UseHexEscapes=*/true);
-      out_ << "\"";
+      out_ << " = \""
+           << FormatEscaped(fn.builtin_function_kind.name(),
+                            /*use_hex_escapes=*/true)
+           << "\"";
     }
 
     if (!fn.body_block_ids.empty()) {
@@ -740,9 +740,7 @@ class FormatterImpl {
     if (space_where == AddSpace::Before) {
       out_ << ' ';
     }
-    out_ << "[from \"";
-    out_.write_escaped(pending_imported_from_);
-    out_ << "\"]";
+    out_ << "[from \"" << FormatEscaped(pending_imported_from_) << "\"]";
     if (space_where == AddSpace::After) {
       out_ << ' ';
     }
@@ -1216,10 +1214,10 @@ class FormatterImpl {
   }
 
   auto FormatArg(StringLiteralValueId id) -> void {
-    out_ << '"';
-    out_.write_escaped(sem_ir_->string_literal_values().Get(id),
-                       /*UseHexEscapes=*/true);
-    out_ << '"';
+    out_ << '"'
+         << FormatEscaped(sem_ir_->string_literal_values().Get(id),
+                          /*use_hex_escapes=*/true)
+         << '"';
   }
 
   auto FormatArg(TypeId id) -> void { FormatType(id); }