Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions src/Lex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,12 @@ std::optional<Tok> Lex::maybeLexByteString(SourceStream &S) {
}

bool isCharacterName(SourceStream &S, std::string &Found) {
static const std::array Names = {"space", "newline", "alarm",
"backspace", "delete", "escape",
"null", "return", "tab"};
// Accepts both the reader's traditional names and the print names emitted by
// charReprFromCodePoint (nul/vtab/page/rubout) so printed control characters
// round-trip. "null" must precede "nul" so #\null is not truncated to #\nul.
static const std::array Names = {
"space", "newline", "alarm", "backspace", "delete", "escape", "null",
"return", "tab", "nul", "vtab", "page", "rubout"};

for (const auto *Name : Names) {
if (S.isPrefix(Name)) {
Expand Down Expand Up @@ -317,9 +320,11 @@ std::optional<Tok> Lex::maybeLexSchemeChar(SourceStream &S) {
(UTF8::isUTF8ReplacementCharacter(StartPtr, EndPtr) ||
UTF8::isGraphUTF8(StartPtr, EndPtr)) &&

// followup character
(isDelimiter(S, 1) || S.peekChar(1) == EOF ||
std::isspace(S.peekChar(1)))) {
// followup character: the byte right after the glyph, at offset Bytes.
// Using offset 1 would land inside a multi-byte glyph (e.g. #\λ), so its
// printed form failed to lex back as a character.
(isDelimiter(S, Bytes) || S.peekChar(Bytes) == EOF ||
std::isspace(static_cast<unsigned char>(S.peekChar(Bytes))))) {
auto Subview = S.getSubviewAndSkip(Bytes);
// End is the index of the last consumed char, so that Tok::size() equals
// the number of bytes consumed (#\ plus the character). Using getPosition()
Expand Down
5 changes: 5 additions & 0 deletions test/integration/char-glyph-list-read.rkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
;; RUN: norac %s | FileCheck %s
;; A multi-byte glyph char followed by whitespace (inside a list) must lex too;
;; the closing-delimiter case is covered by char-glyph-read.rkt.
;; CHECK: '(#\λ #\a)
(linklet () () '(#\λ #\a))
4 changes: 4 additions & 0 deletions test/integration/char-glyph-read.rkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
;; RUN: norac %s | FileCheck %s
;; Reading a printed multi-byte glyph char literal back must yield the same char.
;; CHECK: #\λ
(linklet () () '#\λ)
3 changes: 3 additions & 0 deletions test/integration/char-nul-read.rkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
;; RUN: norac %s | FileCheck %s
;; CHECK: #\nul
(linklet () () '#\nul)
4 changes: 4 additions & 0 deletions test/integration/char-null-read.rkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
;; RUN: norac %s | FileCheck %s
;; The traditional #\null name must still lex (not be truncated to #\nul).
;; CHECK: #\null
(linklet () () '#\null)
3 changes: 3 additions & 0 deletions test/integration/char-page-read.rkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
;; RUN: norac %s | FileCheck %s
;; CHECK: #\page
(linklet () () '#\page)
3 changes: 3 additions & 0 deletions test/integration/char-rubout-read.rkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
;; RUN: norac %s | FileCheck %s
;; CHECK: #\rubout
(linklet () () '#\rubout)
3 changes: 3 additions & 0 deletions test/integration/char-vtab-read.rkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
;; RUN: norac %s | FileCheck %s
;; CHECK: #\vtab
(linklet () () '#\vtab)
Loading