Hash :
e26e54fe
Author :
Thomas de Grivel
Date :
2017-02-10T13:15:50
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
(in-package :parse-css)
(defclass item ()
((parent :initarg :parent
:accessor item-parent
:type (or null item))))
(defclass named-item (item)
((name :initarg :name
:accessor item-name
:type string)))
(defclass with-prelude (item)
((prelude :initarg :prelude
:initform nil
:accessor item-prelude
:type list)))
(defclass with-block (item)
((block :initarg :block
:initform nil
:accessor item-block
:type list)))
(defclass stylesheet (item) ())
(defclass toplevel-flag (item)
((toplevel :initarg :toplevel
:initform nil
:accessor item-toplevel
:type boolean)))
(defclass at-rule (named-item with-prelude with-block toplevel-flag) ())
(defclass qualified-rule (with-prelude with-block toplevel-flag) ())
(defclass css-declaration (named-item)
((value :initarg :value
:accessor item-value
:type list)
(important-p :initarg :important
:initform nil
:accessor important-p
:type boolean)))
(defclass component-value (item) ())
(defclass css-parser (parser)
((item :initform (make-instance 'stylesheet)
:accessor parser-item
:type item)))
;; Parsing
(defgeneric parser-error (parser message))
(defgeneric assert-item (parser type))
(defgeneric parse-at-rule (parser &key toplevel))
(defgeneric parse-qualified-rule (parser &key toplevel))
(defgeneric parse-component-value* (parser))
(defgeneric parse-{}-block (parser))
(defmethod parser-error ((p parser) (message string))
(error "CSS error ~S ~A line ~D character ~D"
message
(parser-input p)
(parser-input-line p)
(parser-input-character p)))
(defmethod assert-item ((p parser) (type symbol))
(or (typep (parser-item p) type)
(parser-error p (format nil "rule expected inside ~A" type))))
(defmethod parse-at-rule ((p parser) &key toplevel)
(let ((at-keyword (at-keyword-token p)))
(when at-keyword
(let* ((parent (parser-item p))
(name (token-string (token-ident at-keyword)))
(prelude (parse-component-value* p))
(item (make-instance 'at-rule
:parent parent
:name name
:prelude prelude
:toplevel toplevel)))
(setf (parser-item p) item)
(or (semicolon-token p)
(parse-{}-block p))
(push item (item-at-rules parent))))))
(defmethod parse-rule-list ((p parser))
(or (and (or (parse-at-rule p)
(parse-qualified-rule p)
(whitespace-token p))
(parse-rule-list p))
t))
(defmethod parse-stylesheet ((p parser))
(setf (parser-item p) (make-instance 'stylesheet :parent nil))
(or (and (or (parse-at-rule p :toplevel t)
(parse-qualified-rule p :toplevel t)
(whitespace-token p)
(cdc-token p)
(cdc-token p))
(parse-stylesheet p))
(eof-token p)
(parser-error p "at top level")))