[gambit-list] Seekable String Ports

Taylor Venable taylor at metasyntax.net
Thu Jun 11 23:11:30 EDT 2009


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,

-- 
Taylor Christopher Venable
http://real.metasyntax.net:2357/



More information about the Gambit-list mailing list