;; Class definition.
(defclass lexer ()
- ((stream :initarg :stream
- :type stream
- :reader lexer-stream)
- (char :initform nil
- :type (or character null)
- :reader lexer-char)
- (pushback-chars :initform nil
- :type list)
- (token-type :initform nil
- :accessor token-type)
- (token-value :initform nil
- :accessor token-value)
- (pushback-tokens :initform nil
- :type list))
+ ((stream :initarg :stream :type stream :reader lexer-stream)
+ (char :initform nil :type (or character null) :reader lexer-char)
+ (pushback-chars :initform nil :type list)
+ (token-type :initform nil :accessor token-type)
+ (token-value :initform nil :accessor token-value)
+ (pushback-tokens :initform nil :type list))
(:documentation
"Base class for lexical analysers.
(defparameter *sod-keywords*
(make-keyword-table
- ;; Words with important meanings to us.
- "class"
- "import" "load" "lisp" "typename"
- "code"
- "extern"
-
;; Words with a meaning to C's type system.
"char" "int" "float" "void"
"long" "short" "signed" "unsigned" "double"
"struct" "union" "enum"))
(defclass sod-lexer (lexer)
- ((keywords :initarg :keywords
- :initform *sod-keywords*
- :type hash-table
- :reader lexer-keywords))
+ ()
(:documentation
"Lexical analyser for the SOD lanuage.
(char= ch #\_))))
(return))))))
- ;; Check to see whether we match any keywords.
- (multiple-value-bind (keyword foundp) (gethash id keywords)
- (return (values (if foundp keyword :id) id)))))
+ ;; Done.
+ (return (values :id id))))
;; Pick out numbers. Currently only integers, but we support
;; multiple bases.
;;; C fragments.
(defclass c-fragment ()
- ((location :initarg :location
- :type file-location
+ ((location :initarg :location :type file-location
:accessor c-fragment-location)
- (text :initarg :text
- :type string
- :accessor c-fragment-text))
+ (text :initarg :text :type string :accessor c-fragment-text))
(:documentation
"Represents a fragment of C code to be written to an output file.
;; Something else. Eat it and continue.
(t (getch)))))
- ;; Return the fragment we've collected.
- (make-instance 'c-fragment
- :location start-floc
- :text (get-output-stream-string output)))))
+ (let* ((string (get-output-stream-string output))
+ (end (position-if (lambda (char)
+ (or (char= char #\newline)
+ (not (whitespace-char-p char))))
+ string
+ :from-end t))
+ (trimmed (if end
+ (subseq string 0 (1+ end))
+ "")))
+
+ ;; Return the fragment we've collected.
+ (make-instance 'c-fragment
+ :location start-floc
+ :text trimmed)))))
(defun c-fragment-reader (stream char arg)
"Reader for C-fragment syntax #{ ... stuff ... }."