The power of Lists Keith Wright (15 Aug 2005 03:14 UTC)
Re: The power of Lists Jens Axel Søgaard (15 Aug 2005 20:43 UTC)
Re: The power of Lists Keith Wright (16 Aug 2005 04:16 UTC)
Re: The power of Lists Michael Sperber (16 Aug 2005 06:19 UTC)
Re: The power of Lists Andre van Tonder (19 Aug 2005 13:35 UTC)
Re: The power of Lists Michael Sperber (20 Aug 2005 07:00 UTC)
Re: The power of Lists Andre van Tonder (20 Aug 2005 15:28 UTC)
Re: The power of Lists Andre van Tonder (22 Aug 2005 14:30 UTC)

Re: The power of Lists Jens Axel Søgaard 15 Aug 2005 20:42 UTC

Hi Keith,

> If it were done with some procedural macro system that represents
> syntax as a special type, it could not have been tested on lists of
> symbols, it would have been full of syntax->list and list->syntax
> conversions in non-obvious places, and I just don't think it would
> have been so much fun that I would have stayed up half the night
> working on it, or finished it before morning.

I liked your example so much I decided to put in the conversions.

(define wall '#(wall))  ;; and end marker

The first change is that the table isn't syntax, but a list.
You defined the table as

     (define table (syntax ((:= . 8)(or . 7) (and . 6)
                            (< . 5) (= . 4)(+ . 3)(* . 2))))

although it is only the identifiers are syntax-objects in
this context. (Btw - that's an example of "breaking the abstraction")
The assocations from identifiers to weights can be written directly as:

(define table `((,#':= . 8) (,#'or . 7) (,#'and . 6)
                 (,#'< . 5)  (,#'= . 4)  (,#'+ . 3) (,#'* . 2)))

or if you prefer your way better, then the a syntax->list
must be added, since table needs to be a list.

(define table (syntax->list
                   (syntax ((:= . 8)(or . 7) (and . 6)
                            (< . 5) (= . 4)(+ . 3)(* . 2)))))

These versions will work in both macro systems.

The definitions of assoid and weight requires no changes.

(define (assoid key == tab)
   (let look ((tab tab))
     (if (null? tab)
         (begin (display (list key " not found in " table)) (newline) #f)
         (if (== key (caar tab))
             (cdar tab)
             (look (cdr tab))))))

(define (weight op)
   (if (eq? op wall)
       500
       (assoid op free-identifier=? table)))

The routine parse is changed to be a function which
takes a list of syntax-objects representing sub-expressions
as input.

Since parse is recursive and calls it selv with a subexpression
(which now is syntax-object) we let parse convert a syntax-objects
representing lists into lists of syntax-objects automaticcally.
I.e. the body of parse is changed from (get 10) into
(if (syntax? tokens) (parse (syntax->list tokens)) (get 10)).

Since your version uses list? and pair? to check whether a
subexpression is a compound expression, we need stx-list?
and stx-pair? when checking for compund subexpressions.

(require (lib "stx.ss" "syntax"))  ; for stx-list? and stx-pair?

; parse : (list stx) -> stx
(define (parse tokens)
   ; this : -> stx
   (define (this) (if (null? tokens) wall (car tokens)))
   (define (next) (set! tokens (cdr tokens)))

   (define (get greed)
     (if (zero? greed)
         (let ((a (this)))
           (next)
           (if (stx-list? (this))
               (let ((arg (this)))
                 (next)
                 (list a (parse arg)))
               (if (stx-pair? a) (parse a) a)))
         (let ((a  (get (- greed 1))))
           (let more ((a a)
                      (op (this)))
             (if (< greed (weight op))
                 a
                 (begin
                   (next)
                   (let ((b (get (- greed 1))))
                     (list op a (more b (this))))))))))

   (if (syntax? tokens)
       (parse (syntax->list tokens))
       (get 10))) ; parse just primes the pump

(parse #'((1 + 2) * 3))

--
Jens Axel Søgaard