guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: RFC: major change to argument processing.


From: Rob Browning
Subject: Re: RFC: major change to argument processing.
Date: 01 Jun 2001 23:52:12 -0500
User-agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7

Marius Vollmer <address@hidden> writes:

> Here is some code for the parser I have in mind, to make things
> clearer.

Well I had a state based parser like that to start with, but ended up
with one much longer after rewriting it a couple of times to better
match the behaviors you wanted.

I think the code should be pretty easy to follow, though.  I did have
to add more code to handle unexpected eof's *everywhere*, and I tried
to avoid any "reversing" (though there was no really good reason for
that since performance doesn't really matter here).

In any case, I'd be happy to use code more like yours if you'd prefer
that, but here's what I currently have:

    (define (read-meta-arg port)
      ;; Returns either a string argument, or throws bad-meta-arg.
      ;; Will concatenate any strings not separated by whitespace.
      ;; i.e. "foo bar"baz -> <foo barbaz>
      
      ;; Note: we don't need the count anymore, so skip-whitespace
      ;; can be simplified.

      (define (skip-whitespace port . count)
        ;; returns num chars skipped
        (set! count (if (null? count) 0 (car count)))
        (cond
         ((eof-object? (peek-char port)) count)
         ((not (char-whitespace? (peek-char port))) count)
         (else
          (read-char port)
          (skip-whitespace port (+ count 1)))))
      
      ;; Both get-single-quote-arg and get-double-quote-arg return a
      ;; string representing the contents of the quoted region and
      ;; throw bad-meta-arg on error.  They both presume that the
      ;; first char available on port is the open quote without
      ;; checking.  They do not concatenate adjacent strings, but do
      ;; consume the final single quote from the port.

      (define (get-single-quote-arg port)
        (read-char port)                  ; throw away opening quote.
        (list->string
         (let loop ((next-char (peek-char port)))
           (if (eof-object? next-char)
               (throw bad-meta-arg)
               (if (char=? #\' next-char)
                   (begin (read-char port) '())
                   (cons (read-char port) (loop (peek-char port))))))))
      
      (define (get-double-quote-arg port)
        ;; Returns a string representing the contents of the quoted
        ;; region.  Throws bad-meta-arg if error.  Presumes that the
        ;; first char available on port is a #\" without checking.
        ;; Does not concatenate adjacent strings.  Consumes final
        ;; double quote from port.
        (read-char port)                  ; throw away opening quote.
        (list->string
         (let loop ((next-char (peek-char port)))
           (if (eof-object? next-char)
               (throw bad-meta-arg)
               (case next-char
                 ;; deal with escape chars immediately -- no state.
                 ((#\\)
                  (read-char port)
                  (cond
                   ((eof-object? (peek-char port)) (throw bad-meta-arg))
                   ((memv (peek-char port) '(#\\ #\"))
                    (cons (read-char port) (loop (peek-char port))))
                   (else (loop (peek-char port)))))
                 ((#\") (read-char port) '())
                 (else
                  (cons (read-char port) (loop (peek-char port)))))))))
      
      ;; Skip any initial whitespace.
      (skip-whitespace port)
      
      (apply string-append
             (let loop ((next-char (peek-char port)))
               
               (if (eof-object? next-char)
                   '()
                   (if (char-whitespace? next-char)
                       '()
                       (case next-char
                         ;; deal with escape chars immediately -- no state.
                         ((#\\)
                          (read-char port)
                          (cond
                           ((eof-object? (peek-char port)) (throw bad-meta-arg))
                           ((char=? #\\ (peek-char port))
                            (cons (read-char port) (loop (peek-char port))))
                           (else (loop (peek-char port)))))
                         ((#\!)
                          (read-char port)
                          (cond
                           ((eof-object? (peek-char port)) '())
                           ((char=? #\# (peek-char port))
                            (begin (read-char port) '("!#")))
                           (else (cons "!" (loop (peek-char port))))))
                         ((#\') (cons (get-single-quote-arg port)
                                      (loop (peek-char port))))
                         ((#\") (cons (get-double-quote-arg port)
                                      (loop (peek-char port))))
                         (else (cons (string (read-char port))
                                     (loop (peek-char port))))))))))

-- 
Rob Browning <address@hidden> PGP=E80E0D04F521A094 532B97F5D64E3930



reply via email to

[Prev in Thread] Current Thread [Next in Thread]