;; Requires scanner
(define parse
  (lambda (str)
    (letrec
      ((push-until-right
	(lambda (tokens stk d)
	  (if (and (= d 0) (not (null? stk)))
	      (cons stk tokens)
	      (let ((u (car tokens)))
		(cond ((eq? u #\()
		       (push-until-right (cdr tokens) (cons u stk) (+ d 1)))
		      ((eq? u #\.)
		       (push-until-right (cdr tokens) (cons u stk) d))
		      ((or (symbol? u) (number? u))
		       (push-until-right (cdr tokens) (cons u stk) d))
		      ((eq? u #\')
		       (let* ((to-be-quoted (push-until-right (cdr tokens) () 0))
			      (quoted (list 'quote (caar to-be-quoted)))
			      (rest (cdr to-be-quoted)))
			 (push-until-right rest (cons quoted stk) d)))
		      ((eq? u #\))
		       (push-until-right (cdr tokens) (pop-until-left stk ()) (- d 1)))
		      (else 
		       (error "parse error.")))))))
       (pop-until-left
	(lambda (stk acc)
	  (let ((u (car stk)))
	    (if (eq? u #\()
		(cons acc (cdr stk))
		(if (eq? u #\.)
		    (if (null? (cdr acc))
			(pop-until-left (cdr stk) (car acc))
			(error "parse error."))
		    (pop-until-left (cdr stk) (cons u acc))))))))
      (caar (push-until-right (scan (string->list str)) () 0)))))
(define expr->string
  (lambda (s)
    (letrec
      ((cdr->string
	(lambda (ls)
	  (cond ((null? ls) "")
		((pair? ls)
		 (let ((rest (cdr ls)))
		   (string-append
		    " "
		    (expr->string (car ls))
		    (cond ((null? rest) "")
			  ((pair? rest)
			   (cdr->string rest))
			  (else
			   (string-append
			    " . "
			    (expr->string rest)))))))
		(else
		 (string-append
		  " . "
		  (expr->string ls)))))))
      (cond ((null? s) "()")
	    ((pair? s)
	     (string-append
	      "("
	      (expr->string (car s))
	      (cdr->string (cdr s))
	      ")"))
	    ((number? s)
	     (number->string s))
	    ((symbol? s)
	     (symbol->string s))
	    (else
	     (error 'expr->string "Unreadable type."))))))
(define do-nothing
  (lambda (str)
    (expr->string (parse str))))