A doubled backslash in a string literal produces the single backslash it
should, but complains on the way there.
$ cat esc.arch
null main
methods
'START' : write "back\\slash"
end
$ archetype --source=esc.arch
At esc.arch, line 3, column 27:
'START' : write "back\\slash"
^
Unknown escape character \\
back\slash
The output is right; the diagnostic is noise. Exit status is 0, so this is
cosmetic — but it appears on every correct use of an escaped backslash, and
\\ is documented behaviour going back to the 1995 manual.
Cause
The escape switch at TokenStream.cc:212-224 has cases for t, b, e, n,
and ", and no case for \:
switch (next_ch) {
case 't' : next_ch = '\t'; break;
case 'b' : next_ch = '\b'; break;
case 'e' : next_ch = '\033'; break;
case 'n' : next_ch = '\n'; break;
case '"' : next_ch = '"'; break;
default: {
errorMessage(format("Unknown escape character \\{}", next_ch));
break;
}
}
s += next_ch;
A backslash falls to default, which complains and then falls through to
s += next_ch — appending the backslash, which is why the text comes out
correct anyway.
Fix
case '\\' : break; // next_ch is already the backslash
A question to settle with it
The 1995 manual promised more than the strict set:
Any other character preceded by a backslash becomes simply that character
without the backslash. \m becomes m, for example.
That is no longer true — \m yields m and an error message. Two coherent
readings:
- Strict (what the code does today, minus this bug): only
\\, \",
\b, \e, \n, \t are legal and anything else is a typo worth
reporting. This catches real mistakes, which is presumably why the default
arm was written.
- Permissive (what the manual says): unknown escapes pass the character
through silently.
The revised manual in docs/manual.md documents the strict reading and drops
the \m sentence, on the assumption that the error arm was deliberate and the
missing \\ case was not. Worth confirming that is the intent; if the
permissive rule is preferred instead, the fix is to delete the default arm's
errorMessage rather than to add a case.
Either way a test in TestTokenStream.cc should pin "a\\b" scanning to the
three characters a, \, b with no diagnostic.
A doubled backslash in a string literal produces the single backslash it
should, but complains on the way there.
The output is right; the diagnostic is noise. Exit status is 0, so this is
cosmetic — but it appears on every correct use of an escaped backslash, and
\\is documented behaviour going back to the 1995 manual.Cause
The escape switch at
TokenStream.cc:212-224has cases fort,b,e,n,and
", and no case for\:A backslash falls to
default, which complains and then falls through tos += next_ch— appending the backslash, which is why the text comes outcorrect anyway.
Fix
A question to settle with it
The 1995 manual promised more than the strict set:
That is no longer true —
\myieldsmand an error message. Two coherentreadings:
\\,\",\b,\e,\n,\tare legal and anything else is a typo worthreporting. This catches real mistakes, which is presumably why the
defaultarm was written.
through silently.
The revised manual in
docs/manual.mddocuments the strict reading and dropsthe
\msentence, on the assumption that the error arm was deliberate and themissing
\\case was not. Worth confirming that is the intent; if thepermissive rule is preferred instead, the fix is to delete the
defaultarm'serrorMessagerather than to add a case.Either way a test in
TestTokenStream.ccshould pin"a\\b"scanning to thethree characters
a,\,bwith no diagnostic.