-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathtask-7-exp.rkt
79 lines (62 loc) · 2.18 KB
/
task-7-exp.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#lang racket
(provide
LETTERS
#; {String -> {U Integer False}}
valid-content
#; {String -> Exp* u False}
string->exp*
#; {Exp* u False -> String}
exp*->string
#; {Exp* -> (Listof Ref*)}
depends-on
#;{ Exp* [Hashof Ref* Integer] -> Integer}
evaluate)
(require 7GUI/should-be-racket)
(define LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
;; EXPRESSIONS: EXTERNAL, STRING-BASED REPRESENTATION
#; {Index : N in [0,99]}
#; {Reference is a Letter followed by an Index}
#; {Expression = Reference || Integer || (+ Expression Expression)}
;; EXPRESSIONS: INTERNAL
#; {Ref* = (List Letter Index)}
#; {Exp* = Ref* || Integer || (list '+ Exp* Exp*)}
(define (valid-content x)
(and* (string->number x) => (lambda (n) (and (integer? n) n))))
(define (string->exp* x)
(define ip (open-input-string x))
(define y (read ip))
(and (eof-object? (read ip))
(let loop ([y y])
(match y
[(? valid-cell) (valid-cell y)]
[(? integer?) y]
[(list '+ y1 y2) (list '+ (loop y1) (loop y2))]
[else #f]))))
(define (exp*->string exp*)
(if (boolean? exp*)
""
(let render-exp* ((exp* exp*))
(match exp*
[(? number?) (~a exp*)]
[(list letter index) (~a letter index)]
[(list '+ left right) (format "(+ ~a ~a)" (render-exp* left) (render-exp* right))]))))
(define (depends-on exp*)
(let loop ([exp* exp*][accumulator (set)])
(match exp*
[(? number?) accumulator]
[(list L I) (set-add accumulator exp*)]
[(list '+ left right) (loop left (loop right accumulator))])))
(define (evaluate exp* global-env)
(let loop ([exp* exp*])
(match exp*
[(? number?) exp*]
[(list L I) (hash-ref global-env exp* 0)]
[(list '+ left right) (+ (loop left) (loop right))])))
#; {Symbol -> (List Letter Index) u False}
(define (valid-cell x:sym)
(and (symbol? x:sym)
(let* ([x:str (symbol->string x:sym)])
(or (and* (regexp-match #px"([A-Z])(\\d\\d)" x:str) => split)
(and* (regexp-match #px"([A-Z])(\\d)" x:str) => split)))))
(define (split x)
(match x [(list _ letter index) (list (string-ref letter 0) (string->number index))]))