git.fiddlerwoaroof.com
Raw Blame History
(define *annotation-escape* '())

(define (parse-annotations)
 (let ((save-layout (dynamic *layout-stack*)))
  (setf (dynamic *layout-stack*) '())
  (advance-token)
  (let/cc annotation-escape
   (setf *annotation-escape* (lambda () 
			       (setf (dynamic *layout-stack*) save-layout)
			       (advance-to-annotation-end)
			       (funcall annotation-escape '())))
   (let ((res (start-layout (function parse-annotation-list-1))))
    (setf (dynamic *layout-stack*) save-layout)
    (token-case
     (end-annotation res)
     (else (signal-annotation-error)))))))

(define (parse-annotation-list-1 in-layout?)
  (let ((kind (get-annotation-kind)))
    (cond ((eq? kind 'decl)
	   (let ((d (parse-annotation-decl)))
	     (token-case
	      (\; (cons d (parse-annotation-list-1 in-layout?)))
	      (else (close-layout in-layout?)
		    (list d)))))
	  ((eq? kind 'value)
	   (let ((d (parse-annotation-value)))
	     (token-case
	      (\; (cons d (parse-annotation-list-1 in-layout?)))
	      (else (close-layout in-layout?)
		    (list d)))))
	  (else
	   (close-layout in-layout?)
	   '()))))

(define (get-annotation-kind)
  (token-case
   ((no-advance end-annotation) 'end)
   ((no-advance \() 'decl)
   ((var con)
    (let ((next (peek-1-type)))
      (cond ((eq? next '|,|)
	     'decl)
	    ((eq? next '|::|)
	     'decl)
	    (else
	     'value))))
   (else 'error)))

(define (parse-annotation-decl)
  (let* ((names (parse-aname-list))
	 (decls (parse-aval-list)))
    (make annotation-decl (names names) (annotations decls))))

(define (parse-aname-list)
 (let ((name 'foo))
  (token-case
   (var
    (setf name (var->symbol)))
   (con
    (setf name (con->symbol)))
   (else (signal-annotation-error)))
  (token-case (\, (cons name (parse-aname-list)))
	      (|::| (list name))
	      (else (signal-annotation-error)))))


(define (parse-aval-list)
  (let ((ann (parse-annotation-value)))
    (token-case (\, (cons ann (parse-aval-list)))
		(else (list ann)))))

(define (parse-annotation-value)
  (token-case
   (name (let* ((name (token->symbol))
		(args (parse-annotation-args name)))
	   (make annotation-value (name name) (args args))))))

(define (parse-annotation-args name)
  (token-case
   (\( (parse-annotation-args-1 name 0))
   (else '())))

;;; This routine can invoke special parsers for the arguments

(define (parse-annotation-args-1 name i)
  (let* ((argtype (get-annotation-arg-description name i))
	 (arg (parse-annotation-arg argtype)))
    (token-case
     (\) (list arg))
     (\, (cons arg (parse-annotation-args-1 name (1+ i))))
     (else (signal-annotation-error)))))

(define (parse-annotation-arg type)
  (cond ((eq? type 'string)
	 (token-case
	  ((string no-advance)
	   (let ((res (car *token-args*)))
	     (advance-token)
	     res))
	  (else (signal-annotation-error))))
	;; The following is for a datatype import/export.  It is
	;; Type(Con1(strs),Con2(strs),...)
	((eq? type 'integer)
	 (token-case
	  ((integer no-advance) (token->integer))
	  (else (signal-annotation-error))))
	((eq? type 'constr-list)
	 (parse-annotation-constr-list))
	(else
	 (signal-annotation-error))))
	   
(define (signal-annotation-error)
  (parser-error/recoverable 'annotation-error "Error in annotation syntax")
  (funcall *annotation-escape*))

(define (parse-annotation-constr-list)
  (token-case
   (tycon (let ((type-name (token->symbol)))
	    (token-case (\( (let* ((args (parse-acl1))
				   (res (tuple type-name args)))
			      (token-case  ; leave the ) to end the args
			       ((no-advance \)) (list res))
			       (\, (cons res (parse-annotation-constr-list)))
			       (else (signal-annotation-error)))))
			(else (signal-annotation-error)))))
   (else (signal-annotation-error))))

(define (parse-acl1)
  (token-case
   (con (let ((con-name (con->symbol)))
	  (token-case (\( (let ((str-args (parse-string-list)))
			    (token-case
			     (\, (cons (tuple con-name str-args)
				       (parse-acl1)))
			     (\) (list (tuple con-name str-args)))
			     (else (signal-annotation-error)))))
		      (else (signal-annotation-error)))))
   (else (signal-annotation-error))))

(define (parse-string-list)
  (token-case
   ((string no-advance)
    (let ((res (read-lisp-object (car *token-args*))))
      (advance-token)
      (token-case
       (\) (list res))
       (\, (cons res (parse-string-list)))
       (else (signal-annotation-error)))))
   (else (signal-annotation-error))))

(define (advance-to-annotation-end)
  (token-case
   (eof '())
   (end-annotation
     (advance-token))
   (else
    (advance-token)
    (advance-to-annotation-end))))
  
(define *known-annotations* '(
  (|LispName| string)
  (|Prelude|)
  (|Strictness| string)
  (|Strict|)
  (|NoConversion|)
  (|Inline|)
  (|STRICT|)
  (|ImportLispType| constr-list)
  (|ExportLispType| constr-list)
  (|Complexity| integer)
  ))

(define (get-annotation-arg-description annotation i)
  (let ((s (assq annotation *known-annotations*)))
    (cond ((eq? s '#f)
	   (parser-error/recoverable 'unknown-annotation
             "Annotation ~A is not defined in this system - ignored."
	     annotation)
	   'unknown)
	  ((>= i (length s))
	   'error)
	  (else (list-ref s (1+ i))))))