anchor.diff:                 (body-first-item ))
                (frame ()
                  (multiple-value-bind (type token) (next)
  -                 (assert (eq :identifer type))
  +                 (assert (eq :identifier type))
                    (make-curly-block :type :frame
                                      :name token
                                      :statements (body))))
  
positive.code:                    ((eq token :geometry)
                      (cons (geometry)
                            (body-first-item)))
                     ((eq type :identifer) ; beginning of block statement
                      (cons (body-statement (list token))
                            (body-first-item)))
                     (t (error "Unknown statement type: ~A" type)))))
  
negative.code:   name
    statements)
  
  ;;; Scanner element:
  ;;;    (list regex (or type (lambda (string start end))))
  ;;;    If the second element is a function, its result is
  ;;;    (values (token-value token-type token-start token-end))
  
  
  (declaim (inline token))
  (defun token (value type start end)
    (values value type start end))
  
  (defmacro with-token ((value type start end) token &body body)
    `(multiple-value-bind (,value ,type ,start ,end) ,token
       ,@body))
  
  (defparameter +curly-token-regex+
    `(("{" #\{)
      ("}" #\})
      ("\\(" #\()
      ("\\)" #\))
      ("\\[" #\[)
      ("\\]" #\])
      ("," #\,)
      (";" #\;)
      ;; string
      ("\\\"[^\\\"]*\\\""
       ,(lambda (string start end)
                (token (subseq string (1+ start) (1- end))
                       :string
                       start
                       end)))
      ("[a-zA-Z][a-zA-Z0-9_]*"
       ,(let ((hash (alist-hash-table '(("frame" . :frame)
                                        ("geometry" . :geometry)
                                        ("class" . :class))
                                      :test #'equal)))
             (lambda (string start end)
               (let* ((token-string (subseq string start end))
                      (type (gethash token-string hash :identifier)))
                 (token (if (eq type :identifier)
                            token-string
                            type)
                        type
                        start
                        end)))))
      ("-?(([0-9]+\\.[0-9]*)|(\\.[0-9]+))"
       ,(lambda (string start end)
                (token (parse-float (subseq string start end))
                       :float
                       start end)))
      ("-?[0-9]+"
       ,(lambda (string start end)
                (token (parse-integer string :start start :end end)
                       :integer start (1+ (position-if #'amino::char-isdigit string
                                                       :start start :end end :from-end t)))))))
  
  (defparameter +curly-comment-regex+
    (let ((whitespace "\\s")
          (line-comment "#|//).*(\\n|$")
          (block-comment "/\\*[^(/\\*)]*\\*/"))
      (format nil "^((~A)|(~A)|(~A))*"
              whitespace
              line-comment
              block-comment)))
  
  (let ((token-scanners
         (map 'list (lambda (thing)
                      (destructuring-bind (regex &rest rest) thing
                        (cons (ppcre:create-scanner (format nil "^(~A)" regex)) rest)))
              +curly-token-regex+))
        (comment-scanner
         (ppcre:create-scanner +curly-comment-regex+)))
  
    (defun curly-next-token (string start)
      "Returns (VALUES TOKEN-VALUE TOKEN-TYPE STRING-START STRING-END)"
      (multiple-value-bind (comment-start comment-end)
          (ppcre:scan comment-scanner string :start start)
        (assert (= start comment-start))
        (let ((start comment-end))
          (loop for (scanner type-thing) in token-scanners
             do (multiple-value-bind (start end)
                    (ppcre:scan scanner string :start start)
                  (when start
                    (with-token (value type start end)
                        (if (functionp type-thing)
                            (funcall type-thing string start end)
                            (token type-thing type-thing start end))
                      ;(print (list value type start end))
                      (return (values value type start end))))))))))
  
  (defun curly-tokenize (string)
    (loop with start = 0
       for (value type t-start end) = (multiple-value-list (curly-next-token string start))
       while value
       do (setq start end)
       collect (list value type (subseq string t-start end))))
  
  (defun curly-tokenize-file (file)
    (curly-tokenize (read-file-into-string file)))
  
  
  (defun curly-parse-string (string)
    (let ((start 0))
      (labels ((next ()
                 (multiple-value-bind (value type t-start end)
                     (curly-next-token string start)
                   (declare (ignore t-start))
                   ;; (when value
                   ;;   (format t "~&token: ~A `~A'" value (subseq string t-start end)))
                   (setq start end)
                   (values type value)))
               (start ()
                 ;(print 'start)
                 (multiple-value-bind (type token) (next)
  