Skip to content

Instantly share code, notes, and snippets.

@dyoo
Created September 10, 2012 19:34
Show Gist options
  • Save dyoo/3693260 to your computer and use it in GitHub Desktop.
Save dyoo/3693260 to your computer and use it in GitHub Desktop.
#lang racket
;; http://stackoverflow.com/questions/12345647/rewrite-this-script-by-designing-an-interpreter-in-racket
;; A pexpr is one of the following:
;; * a primitive string,
;; * a seq, or
;; * a repeat
(struct seq (bodies) #:transparent)
(struct repeat (n body) #:transparent)
;; For convenience, we define some abbreviations s and r for seq and repeat,
;; respectively.
(define (s . bodies)
(seq bodies))
(define (r n . bodies)
(repeat n (seq bodies)))
;; For example:
(define an-example
(s
(r 3 (r 9 "X") "\n")
(r 6 (r 3 " ") (r 3 "X") "\n")
(r 3 (r 9 "X") "\n")))
;; interpret: pexpr -> void
(define (interpret expr)
(match expr
[(? string?)
(display expr)]
[(struct seq (bodies))
(for-each interpret bodies)]
[(struct repeat (n body))
(for ([i n]) (interpret body))]))
;; Finally, let's look at the output:
(interpret an-example)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require unstable/sequence)
;; We can write a quick and dirty parser for lines:
;; parse-line: string -> pexpr
(define (parse-line str)
(define parts (regexp-split #px"\\s+" str))
(define num-lines (string->number (first parts)))
(repeat num-lines
(seq (append (for/list ([count+ch (in-slice 2 (rest parts))])
(repeat (string->number (first count+ch))
(if (string=? (second count+ch) "b")
" "
(second count+ch))))
(list "\n")))))
(define (parse-lines str)
(seq (map parse-line (string-split str "\n"))))
(define a
"3 9 X
6 3 b 3 X 3 b
3 9 X")
(printf "\n\none more time:\n")
(interpret (parse-lines a))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment