I'am trying to read "words" from a stream. A word is eather just a number "1234", a usual alpha character words "test" and contraction of usual words with apostorph "you're".
Sure there are billions of ways to do this. I'am trying to use tagbody to implement something like a state maschine to parse the words. My implementation works if the correct input is given but fails for input that doesn't resemple words. I'am trying to skip input until new whitespace or eof is reached, but thats giving me an infinite loop and I don't know why.
Can someone expain it?
Here is my code
(defun whitespace-or-nil-p (c)
"Returns if a character is whitespace"
(member c '(#\ #\Tab #\Return #\Newline nil)))
(defun read-word (stream)
(let ((c nil))
(with-output-to-string (out)
(tagbody
read-initial
(setf c (read-char stream nil))
(cond
((whitespace-or-nil-p c) (peek-char t stream nil) (go read-initial))
((not (alphanumericp c)) (go skip-til-next))
((digit-char-p c) (go read-number))
((alpha-char-p c) (go read-simple-or-contracted-word))
(t (return-from read-word))
)
skip-til-next
(get-output-stream-string out)
(loop until (whitespace-or-nil-p (peek-char nil stream nil)) do (read-char stream nil))
(go read-initial)
read-number
(write-char c out)
(setf c (read-char stream nil))
(cond
((whitespace-or-nil-p c)
(return-from read-word (get-output-stream-string out)))
((not (digit-char-p c)) (go skip-til-next))
(t (go read-number))
)
read-simple-or-contracted-word
(write-char c out)
(setf c (read-char stream nil))
(cond
((whitespace-or-nil-p c)
(return-from read-word (get-output-stream-string out)))
((and (char/= c #\') (not (alpha-char-p c))) (go skip-til-next))
(t (go read-simple-or-contracted-word))
)
))))