A sign and an unknown escape are both the reader's business
Two mutations the reader survived: dropping '+' from the number dispatch, so +5 reads as a symbol nobody defined, and accepting an unknown string escape as the character after the backslash, so a typo silently reads a different string. Both now have a row, and the known escapes are asserted on the decoded bytes rather than through Form.to_string, which escapes them again and would compare the source with itself.
This commit is contained in:
parent
3afce2aeac
commit
9549d386a1
@ -47,6 +47,15 @@ let () =
|
|||||||
(* ── Atoms ─────────────────────────────────────────────────────── *)
|
(* ── Atoms ─────────────────────────────────────────────────────── *)
|
||||||
reads "integer" "42" "42";
|
reads "integer" "42" "42";
|
||||||
reads "negative" "-1" "-1";
|
reads "negative" "-1" "-1";
|
||||||
|
(* A sign is part of the number, both ways. [+5] is the one that reads as a
|
||||||
|
symbol the moment the '+' case is dropped from the dispatch, and a symbol
|
||||||
|
named "+5" is an unknown name much later and somewhere else. *)
|
||||||
|
reads "leading plus" "+5" "5";
|
||||||
|
reads "plus float" "+0.5" "0.5";
|
||||||
|
reads "plus in a call" "(f +5 -5)" "(f 5 -5)";
|
||||||
|
(* And the operator is still itself: [+] alone is the addition symbol, and
|
||||||
|
[(+ 1 2)] must not read its head as a number. *)
|
||||||
|
reads "bare plus" "+" "+";
|
||||||
reads "float" "0.05" "0.05";
|
reads "float" "0.05" "0.05";
|
||||||
reads "hex" "0xE6B800FF" "3870818559";
|
reads "hex" "0xE6B800FF" "3870818559";
|
||||||
reads "string" "\"SAND\"" "\"SAND\"";
|
reads "string" "\"SAND\"" "\"SAND\"";
|
||||||
@ -141,6 +150,18 @@ let () =
|
|||||||
rejects "unterminated str" "\"abc";
|
rejects "unterminated str" "\"abc";
|
||||||
rejects "empty keyword" ":";
|
rejects "empty keyword" ":";
|
||||||
rejects "unknown char" "\\bogus";
|
rejects "unknown char" "\\bogus";
|
||||||
|
(* An escape the reader does not know is a typo, not a character: accepting
|
||||||
|
\q as 'q' silently reads a different string than the one that was
|
||||||
|
written, and nothing downstream can tell. *)
|
||||||
|
rejects "unknown string escape" "\"a\\qb\"" ~needle:"unknown string escape";
|
||||||
|
(* The escapes it does know still decode, which is what says the rejection
|
||||||
|
above rejects the unknown one and not escaping itself. Asserted on the
|
||||||
|
string's bytes rather than through [Form.to_string], which escapes them
|
||||||
|
again and would compare the source with itself. *)
|
||||||
|
(match Reader.read_all ~file:"<test>" "\"a\\nb\\tc\\\\d\\\"e\\0f\"" with
|
||||||
|
| [ { Form.v = Form.Str s; _ } ] ->
|
||||||
|
check "known escapes" (s = "a\nb\tc\\d\"e\000f")
|
||||||
|
| _ -> check "known escapes: one string" false);
|
||||||
rejects "metadata" "^:async";
|
rejects "metadata" "^:async";
|
||||||
rejects "dangling quote" "'";
|
rejects "dangling quote" "'";
|
||||||
(* Each of these asserts the reason, not merely that something failed. *)
|
(* Each of these asserts the reason, not merely that something failed. *)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user