git.fiddlerwoaroof.com
parser/annotation-parser.scm
4e987026
 
 (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))))))