| 1 |
(in-package :bknr.utils) |
|---|
| 2 |
|
|---|
| 3 |
(define-constant +whitespace-chars+ |
|---|
| 4 |
'(#\Space #\Newline #\Tab #\Linefeed)) |
|---|
| 5 |
|
|---|
| 6 |
(defun whitespace-char-p (c) |
|---|
| 7 |
(member c +whitespace-chars+)) |
|---|
| 8 |
|
|---|
| 9 |
(defun whitespace-p (c-or-s) |
|---|
| 10 |
(cond ((stringp c-or-s) |
|---|
| 11 |
(every #'whitespace-char-p c-or-s)) |
|---|
| 12 |
((characterp c-or-s) |
|---|
| 13 |
(whitespace-char-p c-or-s)) |
|---|
| 14 |
(t nil))) |
|---|
| 15 |
|
|---|
| 16 |
(defun bknr-read-string-until (s endchar &key (start nil) |
|---|
| 17 |
(test #'eql) test-not (unread-endchar nil)) |
|---|
| 18 |
(do ((c (peek-char nil s nil 'eof) |
|---|
| 19 |
(peek-char nil s nil 'eof)) |
|---|
| 20 |
(ret (copy-list start)) |
|---|
| 21 |
(escaped nil (and (not escaped) (eql c #\\)))) |
|---|
| 22 |
((or (eq c 'eof) |
|---|
| 23 |
(and (not escaped) |
|---|
| 24 |
(if test-not |
|---|
| 25 |
(not (funcall test-not c endchar)) |
|---|
| 26 |
(funcall test c endchar)))) |
|---|
| 27 |
(unless (or unread-endchar |
|---|
| 28 |
(eq c 'eof)) |
|---|
| 29 |
(push (read-char s) ret)) |
|---|
| 30 |
(coerce (nreverse ret) 'string)) |
|---|
| 31 |
(push (read-char s) ret))) |
|---|
| 32 |
|
|---|
| 33 |
(defun bknr-read-string (s) |
|---|
| 34 |
(bknr-read-string-until s #\" :start '(#\"))) |
|---|
| 35 |
|
|---|
| 36 |
(defun bknr-read-comment (s) |
|---|
| 37 |
(bknr-read-string-until s '(#\Newline #\Linefeed) :test #'member :unread-endchar t)) |
|---|
| 38 |
|
|---|
| 39 |
(defun bknr-read-whitespace (s) |
|---|
| 40 |
(bknr-read-string-until s +whitespace-chars+ :test-not #'member :unread-endchar t)) |
|---|
| 41 |
|
|---|
| 42 |
(defun bknr-read-something (s) |
|---|
| 43 |
(bknr-read-string-until s (append +whitespace-chars+ '(#\( #\" #\))) :test #'member |
|---|
| 44 |
:unread-endchar t)) |
|---|
| 45 |
|
|---|
| 46 |
(defun bknr-read-delimited-list (s endchar &optional eof-error-p eof-value collect-whitespace) |
|---|
| 47 |
(do ((c (peek-char nil s nil 'eof) |
|---|
| 48 |
(peek-char nil s nil 'eof)) |
|---|
| 49 |
ret) |
|---|
| 50 |
((or (eq c 'eof) |
|---|
| 51 |
(eq c endchar)) |
|---|
| 52 |
(when (eq c endchar) |
|---|
| 53 |
(read-char s)) |
|---|
| 54 |
(nreverse ret)) |
|---|
| 55 |
(push (bknr-read s eof-error-p eof-value collect-whitespace) ret))) |
|---|
| 56 |
|
|---|
| 57 |
(defun bknr-read (s &optional (eof-error-p t) eof-value (collect-whitespace t)) |
|---|
| 58 |
(prog () |
|---|
| 59 |
again |
|---|
| 60 |
(let ((c (peek-char nil s eof-error-p eof-value))) |
|---|
| 61 |
(cond ((and eof-value |
|---|
| 62 |
(eq c eof-value)) |
|---|
| 63 |
(return eof-value)) |
|---|
| 64 |
((eq c #\() |
|---|
| 65 |
(read-char s) |
|---|
| 66 |
(return |
|---|
| 67 |
(if collect-whitespace |
|---|
| 68 |
(collect-whitespace (bknr-read-delimited-list |
|---|
| 69 |
s #\) eof-error-p eof-value collect-whitespace)) |
|---|
| 70 |
(bknr-read-delimited-list |
|---|
| 71 |
s #\) eof-error-p eof-value collect-whitespace)))) |
|---|
| 72 |
((eq c #\") |
|---|
| 73 |
(read-char s) |
|---|
| 74 |
(return (bknr-read-string s))) |
|---|
| 75 |
((eq c #\;) |
|---|
| 76 |
(return (bknr-read-comment s))) |
|---|
| 77 |
((eq c #\)) |
|---|
| 78 |
(read-char s) |
|---|
| 79 |
(return ")")) |
|---|
| 80 |
((whitespace-char-p c) |
|---|
| 81 |
(let ((whitespace (bknr-read-whitespace s))) |
|---|
| 82 |
(if collect-whitespace |
|---|
| 83 |
(return whitespace) |
|---|
| 84 |
(go again)))) |
|---|
| 85 |
(t (return (bknr-read-something s))))))) |
|---|
| 86 |
|
|---|
| 87 |
(defun collect-whitespace (list) |
|---|
| 88 |
(do ((l list (cdr l)) |
|---|
| 89 |
whitespace) |
|---|
| 90 |
((or (null l) |
|---|
| 91 |
(not (whitespace-p (car l)))) |
|---|
| 92 |
(cond ((and (null whitespace) |
|---|
| 93 |
(null l)) |
|---|
| 94 |
nil) |
|---|
| 95 |
(t (cons (apply #'concatenate 'string (nreverse whitespace)) |
|---|
| 96 |
(unless (null l) |
|---|
| 97 |
(cons (car l) (collect-whitespace (cdr l)))))))) |
|---|
| 98 |
(when (> (length (car l)) 0) |
|---|
| 99 |
(push (car l) whitespace)))) |
|---|
| 100 |
|
|---|
| 101 |
(defun string-beginning-with-p (string beginning) |
|---|
| 102 |
(let ((beginlen (length beginning))) |
|---|
| 103 |
(and (stringp string) |
|---|
| 104 |
(and (>= (length string) beginlen) |
|---|
| 105 |
(string-equal (subseq string 0 beginlen) beginning))))) |
|---|
| 106 |
|
|---|
| 107 |
(defun string-delimited-by-p (string char) |
|---|
| 108 |
(and (stringp string) |
|---|
| 109 |
(let ((len (length string))) |
|---|
| 110 |
(and (> len 2) |
|---|
| 111 |
(eql (char string 0) char) |
|---|
| 112 |
(eql (char string (1- len)) char))))) |
|---|
| 113 |
|
|---|