Is there any way to seek through string ports? When I try to use input-port-byte-position I get this:
(call-with-input-string "asdf" (either (char/exactly #\c) (char/exactly #\s)))
*** ERROR IN #<procedure #10>, "tcv-gambit-parse.scm"@66.20 -- (Argument 1) Device INPUT PORT expected (input-port-byte-position '#<input-port #11 (string)>)
(I'm doubtful that input-port-byte-position would be what I want anyway if the string included characters that weren't encoded as single bytes, but that's a digression.)
I'm trying to write a parser combinator library, and part of that entails some rewinding of streams for ordered-choice operations (as illustrated above). A potential alternative would be to duplicate the port's contents and use a different port for each alternative, but I am not aware of any API to do this either. Any ideas on how to accomplish this objective? I need something that works for at least string ports and device ports.
My current code, for background:
(define char/exactly (lambda (c) (lambda (stream) (let ((char (read-char stream))) (cond ((eof-object? char) #f) ((not (char=? char c)) #f) (else char))))))
(define either (lambda combinators (lambda (stream) (let loop ((c combinators)) (cond ((null? c) #f) ((apply (car c) (list stream)) #t) (else (loop (cdr c))))))))
As defined here, the either function will not undo the changes done by char/exactly (in the example above), thus each choice will advance the stream by one character. We could work around it here by using peek-char rather than read-char but that wouldn't scale to when either is used on functions that read large chunks of data before failing.
Thanks for any ideas,