CS 491/591 Advanced Scheme Programming and Implementation

Homework 2 (Spring 2004)

  1. The following grammar defines a subset of LOGO: <input> := <subroutines> <instructions> <subroutines> := <subroutine> <subroutines> | "" <subroutine> := to <symbol> <variable list> [<instructions>] <variable list> := () | ( <variables> ) <variables> := <variable> | <variable> , <variables> <instruction> := <0-arity command> <instruction> := <1-arity command> <value> <instruction> := if <boolean> <action> | if <boolean> <action> else <action> <boolean> := <value> = <value> | <value> < <value> | <value> > <value> <action> := <instruction> | [ <instructions> ] <instructions> := <instruction> <instructions> | "" <instruction> := repeat <value> <action> <instruction> := make <symbol> <value> <value list> := () | ( <values> ) <values> := <value> | <value> , <values> <instruction> := <symbol> <value list> <value> := <E> + <value> | <E> - <value> | <E> <E> := <F> * <E> | <F> / <E> | <F> <F> := <atom> | (<value>) <atom> := <symbol> | <number> <0-arity command> := penup | pendown | stop | push | pop <1-arity command> := forward | backward | left | right | color Using the parser defined here as a model, write a backtracking parser which parses sentences derived from the <value list> non-terminal using success and failure continuations. You may use the scanner given here to transform the input string into a list of tokens. Your parser should take input like this: "(13, x*y+1, foo)" and produce output like this: '(13 (+ (* x y) 1) foo). If you are really ambitious, you may then (optionally) extend your parser so that it parses sentences derived from the <input> non-terminal, i.e., LOGO programs. The extended parser should take input like this: "to starfish(side, angle, inc) [ repeat 90 [ forward side right angle make angle angle+inc ] ] penup forward 50 pendown starfish(30, 2, 20)" and produce output like this: '((to starfish (side angle inc) (repeat 90 (forward side) (right angle) (make angle (+ angle inc)) ) ) (penup) (forward 50) (pendown) (starfish 30 2 20)) and input like this: "to tree(depth, count) [ forward depth*20 right 90 if depth > 1 [ repeat 5 [ push left count*30 tree(depth-1, 1) pop make count count+1 ] ] ] tree(4, 1)" and produce output like this: '((to tree (depth count) (forward (* depth 20)) (right 90) (if (> depth 1) ((repeat 5 (push) (left (* count 30)) (tree (- depth 1) 1) (pop) (make count (+ count 1)) )) ) ) (tree 4 1)).
  2. Declare a macro with keyword and, which may take any number of subexpressions. If called with no subexpressions, it is #t. If all of its subexpressions are not #f, it evaluates to the last one; otherwise it is #f.

  3. Many Scheme's have a syntactic form called named-let. Named-let has the following abstract syntax:

    (let <name> ((<var1> <val1>)...(<varN> <valN>)) 
      <expr1>
      .
      .
      .
      <exprM>)
    
    =>
    ((letrec
      ((<name> 
        (lambda (<var1>...<varN>)
          <expr1>
          .
          .
          .
          <exprM>)))
        <name>) <val1>...<valN>)
    
    It can be used as follows: >(let loop ((x 4) (acc 1)) (if (= x 1) acc (loop (- x 1) (* x acc)))) 24 > Use define-macro to define named-let.

  4. The special form, while, is a control structure common to many programming languages. In while, an expression is evaluated repeatedly as long as a given condition is true. We can effect the behavior of a while expression as illustrated by the following program, which sums the numbers from 1 to 100: (let ((n 100) (sum 0)) (letrec ((loop (lambda () (if (positive? n) (begin (set! sum (+ sum n)) (set! n (sub1 n)) (loop)))))) (loop) sum)) We would like to introduce the special form, while, which allows us to write the above program as: (let ((n 100) (sum 0)) (while (positive? n) (set! sum (+ sum n)) (set! n (sub1 n))) sum) While has the following abstract syntax:
    (while <test> <expr1>...<exprN>)
    
    =>
    (letrec
      ((loop
        (lambda ()
          (if <test>
            (begin
              <expr1>
    	  .
    	  .
    	  .
    	  exprN>
    	  (loop))))))
      (loop))
    
    Define while using define-macro. You must take into account the potential variable capturing that is caused when the variable loop occurs free in test or expression.

  5. Read Chapters 1 and 2 of Kent Dybvig's Ph.D. thesis, Three Implementation Models for Scheme. Use define-macro to implement the record-case macro he describes on p. 28.