(module in-something mzscheme
(require (lib "contract.ss")
(only (lib "13.ss" "srfi") string-prefix?))
(define (string/false? datum)
(or (string? datum)
(eq? datum #f)))
(provide/contract [in-something? (string? . -> . string/false?)])
(define (in-something? str)
(let loop ([i 0]
[in #f]
[escaped-char? #f]
[here-marker #f]
[nested-comments #f])
(define (is? c)
(string-prefix? c str 0 (string-length c) i (string-length str)))
(define (consume c)
(cond [(not in)
(loop (add1 i) c #f here-marker nested-comments)]
[(string=? in c)
(loop (add1 i) #f #f here-marker nested-comments)]
[else
(loop (add1 i) in #f here-marker nested-comments)]))
(define (form-output)
(cond [here-marker
(string-append "\n" here-marker "\n")]
[nested-comments
(string-repeat "|#" nested-comments)]
[(and escaped-char? in)
(string-append "\\" in)]
[escaped-char? "\\"]
[else in]))
(define (handle-here-marker)
(let ([j (+ i
(string-length here-marker)
2)])
(cond
[(and (is? (string-append "\n" here-marker))
(or (>= j (string-length str))
(char-whitespace? (string-ref str j))))
(loop j #f #f #f #f)]
[else
(loop (add1 i) #f #f here-marker #f)])))
(define (handle-nested-comments)
(cond
[(is? "#|")
(loop (+ i 2) #f #f #f (add1 nested-comments))]
[(is? "|#")
(cond [(= nested-comments 1)
(loop (+ i 2) #f #f #f #f)]
[else
(loop (+ i 2) #f #f #f (sub1 nested-comments))])]
[else
(loop (add1 i) #f #f #f nested-comments)]))
(cond
[(>= i (string-length str))
(form-output)]
[here-marker
(handle-here-marker)]
[nested-comments
(handle-nested-comments)]
[escaped-char?
(loop (add1 i) in #f here-marker nested-comments)]
[(and (not in)
(not here-marker)
(is? "#<<"))
(let ([marker (get-here-string-marker str i)])
(loop (add1 (+ i 3 (string-length marker)))
#f #f marker #f))]
[(and (not in)
(not nested-comments)
(is? "#|"))
(loop (+ i 2) #f #f #f 1)]
[(and (not in) (is? ";"))
(loop (add1 i) "" #f here-marker nested-comments)]
[(and (is? "\n") (equal? in ""))
(loop (add1 i) #f #f here-marker nested-comments)]
[(is? "\\")
(loop (+ 1 i) in #t here-marker nested-comments)]
[(is? "\"" )
(consume "\"")]
[(is? "|")
(consume "|")]
[else
(loop (add1 i) in #f here-marker nested-comments)])))
(define (string-repeat an-str n)
(cond [(= n 0)
""]
[else
(string-append an-str (string-repeat an-str (sub1 n)))]))
(define (get-here-string-marker a-str i)
(let loop ([j (+ i (string-length "#<<"))]
[chars-so-far/rev '()])
(cond
[(or (= j (string-length a-str))
(char=? (string-ref a-str j) #\newline))
(list->string (reverse chars-so-far/rev))]
[else
(loop (add1 j) (cons (string-ref a-str j) chars-so-far/rev))]))))