From: Niklas Ulvinge <[EMAIL PROTECTED]>
Date: 2008/7/2
Subject: Fresh ideas from a beginner
To: readable-discuss@lists.sourceforge.net


Hello
I've seen that this list has been a little inactive lately,
but it doesn't matter. Here's an implementation of
both a i-expression pretty printer (idisplay), and an
i-expression reader (iread). Currently I do not escape
characters, and that's the only thing my code can't
handle as far as I can see.

My pretty printer also prints much more beautiful code
than the others I've tried.

I don't know how well this conforms to the standard,
(or the scheme standard, for that matter) but it looks
like it should work very well.

I also don't know how good it is to write code with it
but that is going to change, as my next project will
be written with only iexpr.

Well, here's the code:

(define (flatten l)
  (if (not (list? l))
    (list l)
    (if (null? l)
      '()
      (append (flatten (car l))
              (flatten (cdr l))))))

(define (idisplay l)
  (define group "group ")

  (define (indent i)
    (make-string i #\space))

  (define (len l)
    (if (null? l)
      0
      (+ (string-length (car l))
         (len (cdr l)))))

  (define (make-single l)
    (define (remove-multiple-newlines l)
      (if (null? (cdr l))
        '()
        (if (equal? (car l) "\n")
          (if (equal? (cadr l) "\n")
            (remove-multiple-newlines (cdr l))
            (cons "\n"
                  (remove-multiple-newlines (cdr l))))
          (cons (car l)
                (remove-multiple-newlines (cdr l))))))
    (apply string-append (remove-multiple-newlines l)))

  (define (parse l i)
    (write (list i l)) (newline)
    (flatten
      (cond ((list? l)   (parse-list l i))
            ((symbol? l) (list (symbol->string l)))
            ((number? l) (list (number->string l)))
            ((null? l)   "'()")
            ((string? l) (list "\"" l "\""))
            ((pair? l) (list "(" (parse (car l)) " . " (parse (cdr l)) ")"))
            (else "undef"))))

  (define (parse-list l i)
      (if (list? (car l))
        (list group
              (parse (car l) (+ i (string-length group)))
              (map (lambda(k)
                     (list "\n"
                           (indent  (+ i (string-length group)))
                           (parse k (+ i (string-length group)))))
                   (cdr l)))
        (let* ((first  (parse (car l) i))
               (len    (len first)))
          (list (if (null? (cdr l))
                  (list group first)
                  (list first
                        (indent 1)
                        (parse (cadr l) (+ i len 1))
                        (map (lambda(k)
                               (list "\n"
                                     (indent  (+ i len 1))
                                     (parse k (+ i len 1))))
                             (cddr l))))
                "\n"))))

  (make-single (parse l 0)))

*********************************** iread ***********************************

(define (iread port)
  (define lparen #\()
  (define rparen #\))
  (define peek '())
  (define indent 0)
  (define (get)
    (let ((ret peek))
      (if (equal? ret #\newline)
        (set! indent 0)
        (set! indent (+ 1 indent)))
      (if (eof-object? (peek-char port))
        (set! peek '())
        (begin
          (set! peek  (read-char port))))
      ret))

  (define (tokenise)
    (define (read-token)
      (define (loop)
        (if (or (null? peek)
                (char-whitespace? peek)
                (equal? #\; peek)
                (equal? lparen peek))
          '()
          (cons (get)
                (loop))))
      (list->string (loop)))
    (define (read-comment)
      (if (equal? peek #\newline)
        (read-whitespace)
        (begin (get)
               (read-comment))))
    (define (read-whitespace)
      (if (equal? peek #\;) ; ; IS preceded by whitespace
        (read-comment)
        (if (and (not (null? peek))
                 (char-whitespace? peek))
            (begin (get)
                   (read-whitespace)))))
    (define (read-string)
      (define (loop)
        (if (null? peek)
          '()
          (if (equal? peek #\")
            (cons (get)
                  '())
            (cons (get)
                  (loop)))))
      (list->string (cons (get) ;becouse of the first #\"
                          (loop))))
    (define (read-sexpr)
      (define (loop n-open-parens)
        (cond ((null? peek) '())
              ((equal? peek lparen) (cons (get)
                                          (loop (+ n-open-parens 1))))
              ((equal? peek rparen) (if (= 1 n-open-parens)
                                      (cons (get) ;exit loop
                                            '())
                                      (cons (get)
                                            (loop (- n-open-parens 1)))))
              (else (cons (get)
                          (loop n-open-parens)))))
      (list->string (loop 0)))

    (read-whitespace)
    (cons indent
          (if (equal? peek lparen)
            (read-sexpr)
            (if (equal? peek #\")
              (read-string)
              (read-token)))))
  (define peekt '())
  (define (gett)
    (let ((ret peekt))
      (set! peekt (tokenise))
      (if (equal? (cdr peekt) "")
        (set! peekt '(-1 . ())))
      ret))

  (define (tokens->list i)
    (define (head i)
      (let ((first (cdr (gett))))
        (if (equal? "group" first)
          (body (car peekt))
          (if (< i (car peekt)) ;we have childs
            (append (list first)
                    (body (car peekt)))
            first))))
    (define (body i)
      (if (= i (car peekt))
        (cons (head i)
              (body i))
        '()))
    (body i))

  (define (to-string l)
    (define (loop l)
      (if (list? l)
        (append (list "(")
                (map loop l)
                (list ") "))
        (list l " ")))
    (apply string-append (flatten (loop l))))

  (set! peek (peek-char port))
  (gett)
  (call-with-input-string (to-string (tokens->list 0))
                          read))


(define input1 "
define fac x
       if = x
            0
          1
          * x
            fac - x
                  1
fac 4
")
(define input2 "
z a
  b c
  (+ 1 d)
  group e f
        g ;test
        group h
  i
  \"hello\"
  quote j
")


(define fac '(define (fac x)
               (if (= x 0)
                 1
                 (* x
                    (fac (- x 1))))))

(define (iexecute port)
  (map (lambda(e) (write e) (newline) (write (eval e)) (newline))
       (iread port)))

(display input1) (newline)
(iexecute (open-input-string input1)) (newline)

************************************ EOF ************************************

Please excuse my poor coding style, I've only been
programming in scheme for about a month.

Another thing I found out is that the (a) special case
for a list with only one item in it isn't necessary,
it can be solved with group a instead....

Niklas Ulvinge aka IDK
wishes everybody happy
programming and bliss.

-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08
_______________________________________________
Readable-discuss mailing list
Readable-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/readable-discuss

Reply via email to