diff --git a/test/test_flan.ml b/test/test_flan.ml index ff84835..9768a6e 100644 --- a/test/test_flan.ml +++ b/test/test_flan.ml @@ -47,6 +47,15 @@ let () = (* ── Atoms ─────────────────────────────────────────────────────── *) reads "integer" "42" "42"; 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 "hex" "0xE6B800FF" "3870818559"; reads "string" "\"SAND\"" "\"SAND\""; @@ -141,6 +150,18 @@ let () = rejects "unterminated str" "\"abc"; rejects "empty keyword" ":"; 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:"" "\"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 "dangling quote" "'"; (* Each of these asserts the reason, not merely that something failed. *)