+++ /dev/null
-(cl:in-package #:sod)
-
-(defun play-fetch-token (string)
- (with-parser-context (string-parser :string string)
- (labels ((digit (radix)
- (parse (filter (lambda (ch)
- (digit-char-p ch radix)))))
- (number (radix &optional (initial 0))
- (parse (many (a initial (+ (* radix a) it))
- (digit radix))))
- (numeric (radix sigil)
- (parse (seq ((first (peek (seq ((nil (funcall sigil))
- (d (digit radix)))
- d)))
- (result (number radix first)))
- result))))
- (multiple-value-call #'values
- (loop
- (parse :whitespace)
-
- (cond-parse ()
-
- ;; Give up at end-of-file.
- (:eof
- (return (values :eof nil)))
-
- ;; Pick out comments.
- ((peek (and #\/ #\*))
- (parse (skip-many () ; this may fail at eof; don't worry
- (and (skip-many () (not #\*))
- (skip-many (:min 1) #\*))
- (not #\/)))
- (if-parse :eof ()
- (cerror* "Unterminated comment")
- (parse :any)))
- ((and (peek (seq (#\/ #\/)))
- (skip-many () (not #\newline))
- (or :eof #\newline)))
-
- ;; Quoted strings and characters.
- ((or #\' #\")
- (let ((quote it)
- (out (make-string-output-stream)))
- (parse (skip-many ()
- (or (seq ((ch (satisfies (lambda (ch)
- (and (char/= ch #\\)
- (char/= ch quote))))))
- (write-char ch out))
- (seq (#\\ (ch :any))
- (write-char ch out)))))
- (if-parse :eof ()
- (cerror* "Unterminated ~:[string~;character~] constant"
- (char= quote #\'))
- (parse :any))
- (let ((string (get-output-stream-string out)))
- (ecase quote
- (#\" (return (values :string string)))
- (#\' (case (length string)
- (0 (cerror* "Empty character constant")
- (return (values :char #\?)))
- (1 (return (values :char (char string 0))))
- (t (cerror* "Multiple characters in ~
- character constant")
- (return (values :char (char string 0))))))))))
-
- ;; Identifiers.
- ((seq ((first (satisfies (lambda (ch)
- (or (char= ch #\_)
- (alpha-char-p ch)))))
- (ident (many (out (let ((s (make-string-output-stream)))
- (write-char first s)
- s)
- (progn (write-char it out) out)
- :final (get-output-stream-string out))
- (satisfies (lambda (ch)
- (or (char= ch #\_)
- (alphanumericp ch)))))))
- (return (values :id ident))))
-
- ;; Numbers -- uses the machinery in the labels above.
- ((or (seq (#\0
- (i (or (numeric 8 (parser () (or #\o #\O)))
- (numeric 16 (parser () (or #\x #\X)))
- (number 8))))
- i)
- (seq ((first (digit 10))
- (rest (number 10 first)))
- rest))
- (return (values :integer it)))
-
- ;; Special separator tokens.
- ("..."
- (return (values :ellipsis :ellipsis)))
-
- ;; Anything else is a standalone delimiter character.
- (:any
- (return (values it it)))))
- (parse (list () :any))))))