parsecomb.arc has not been maintained. The current parser combinator library that is maintained is raymyers's lib/treeparse.arc , but you have to coerce strings to parse into 'cons cells.
For that matter the fix in lib/parsecomb.arc should probably be to mapdelay:
Yeah, that was the first thing I was going to try, then I got sidetracked :)
Can you elaborate on how I can use treeparse for more generalized parsing? Like if I just have a file with flat text and want to generate a list of strings separated by empty lines?
treeparse is very generalized, so expect to write a lot of code.
As for files: the lib/scanner.arc library allows you to treat input streams (e.g. input files) as if they were a list of characters, which is what treeparse accepts (treeparse can work with "real" lists and scanners).
Treeparse usually returns a list of characters, but this behavior can be modified by using a 'filt parser.
Just off the top of my head (untested!):
(require "lib/scanner.arc")
(require "lib/treeparse.arc") ; could use cps_treeparse.arc
(let (list-str newline line oneline lastline allparse) nil
; converts a list of chars to a string
(= list-str
[string _])
; support \r\n, \n\r, \n, and \r
(= newline
; alt & seq's semantics should be obvious
(alt
(seq #\return #\newline)
(seq #\newline #\return)
#\newline
#\return))
(= line
; lots of characters that could be anything...
; but *not* newlines!
(many (anything-but newline)))
(= oneline
(seq line
newline)))
; in case the last line doesn't end in newline
(= lastline
line)
(= allparse
(seq
; many is greedy, but will still pass
; if there are none
(many
; the filter function has to return a list
(filt [list (list-str _)]
oneline))
; might not exist; will still pass whether
; it exists or not
(maybe
(filt [list (list-str _)]
lastline))))
(def lines-from-scanner (s)
(parse allparse s)))
(def lines-from-file (f)
(w/infile s f
(lines-from-scanner (scanner-input s))))
p.s. performance may be slow. cps_treeparse.arc is a more optimized version (maybe 25% faster on average, which most of the speedup in many and seq IIRC, which could be twice the speed), but does not support the "semantics" feature.
Achtung! The CPS variant is written in, of all things, continuation passing style, which is hard on the eyes. It is thus expected to be much harder to read than the straightforward treeparse.
Achtung! In a single Arc session, it is safe to use only treeparse or cps_treeparse. Never load both in the same session.
Achtung! Some of treeparse's features are not supported by cps_treeparse.
doesn't work when s is a scanner -- s remains unchanged. I looked at the code and convinced myself that macros like zap that call setforms won't work for new types. Does that make sense?