Schemely parser combinators, first take added by DerGuteMoritz on Wed Jul 11 10:03:29 2012

(load "comparse.scm")
(import comparse)
(use test)

(define (quoted-string #!key
                       (delimiter (satisfies (char-set #\" #\')))
                       (escape (is #\\)))
  (let ((escaped-char (all-of escape item))
        (string-char (all-of (none-of delimiter) item)))
    (sequence ((_ (zero-or-more (satisfies char-set:whitespace)))
               (actual-delimiter delimiter)
               (chars (zero-or-more
                       (any-of escaped-char
                               (all-of (none-of escape (is actual-delimiter))
                                       item))))
               (_ (is actual-delimiter)))
              (result (list->string chars)))))

(receive (result more) (parse (quoted-string) "\"string 1\" 'string 2'  some trailing ")
  (test "string 1" (car result))
  (let ((result (parse (quoted-string) (cdr result))))
    (test "string 2" (car result))
    (test-assert (not (parse (quoted-string) (cdr result))))))

(let ((singly-quoted-bang-string (quoted-string delimiter: (is #\') escape: (is #\!))))
  (test "this 'is' a string" (car (parse singly-quoted-bang-string "'this !'is!' a string'")))
  (test "ok\\" (car (parse singly-quoted-bang-string "'ok\\'")))
  (test-assert (not (parse singly-quoted-bang-string "\"check\""))))

(test-assert (not (parse (quoted-string) "this ain't a string")))