jeremyschlatter/chime

Leading-colon terms don't parse in the REPL

Opened this issue · 0 comments

masak commented

Using the Windows executable of the 0.4.0 release:

> (read '(":foo"))
(compose foo)

> ':foo
input:1:2:
  |
1 | ':foo
  |  ^^
unexpected ":f"
expecting ",@", '!', '"', '#', ''', '(', '+', ',', '-', '.', '[', '\', '`', '~', '|', integer, or regular character

I expected these to give the same output, ultimately because there should be no observable difference between the reader used by the REPL and read.

Words with colons in them are handled by parsecom:

(def parsecom (cs base)
  (if (mem \: cs)
      (cons 'compose (map [parseno _ base] (tokens cs \:)))
      (parseno cs base)))

The tokens function is untroubled by a leading colon (ultimately because it's defined in terms of runs, which defines its fon parameter default to be true iff the list begins with the separator):

> (tokens ":foo" \:)
("foo")

My Haskell is weak (but enough to appreciate how beautiful parser combinators are!), anyway, this looks relevant:

  s3 :: Parser m (Object (Ref m))
  s3 = sepBy1 s2 (char ':') >>= compose

As shown above by the call to tokens and to read, : can occur not just as a separator, but also at the start.

Just as I wrote this, it also occurred to me to test whether it can also occur at the end. It can, and with the same outcome:

> (read '("foo:\lf"))
(compose foo)

> 'foo:
|

Here the REPL is doing a different thing — it's showing a continuation prompt after I hit Return, because it's thinking of the : as a separator and so there must be something after it. But we've already hit a breakc (\lf), and so the Bel reader knows that the word can't continue.

Both :foo and foo: have untapped potential as syntax-up-for-grabs in some macro-powered DSL or other. 😄