|
1 | 1 | #lang racket |
2 | | -(provide parse parse-e parse-define) |
| 2 | +(provide parse parse-closed parse-e parse-define) |
3 | 3 | (require "ast.rkt") |
4 | 4 |
|
5 | | -;; S-Expr ... -> Prog |
6 | | -(define (parse . s) |
7 | | - (match s |
8 | | - [(cons (and (cons 'define _) d) s) |
9 | | - (match (apply parse s) |
10 | | - [(Prog ds e) |
11 | | - (Prog (cons (parse-define d) ds) e)])] |
12 | | - [(cons e '()) (Prog '() (parse-e e))] |
13 | | - [_ (error "program parse error")])) |
14 | | - |
15 | | -;; S-Expr -> Defn |
| 5 | +;; [Listof S-Expr] -> Prog |
| 6 | +(define (parse . ss) |
| 7 | + (match (parse-prog ss (parse-defn-names ss) '() '() '()) |
| 8 | + [(list _ _ p) p])) |
| 9 | + |
| 10 | +;; [Listof S-Expr] -> ClosedProg |
| 11 | +(define (parse-closed . ss) |
| 12 | + (match (parse-prog ss (parse-defn-names ss) '() '() '()) |
| 13 | + [(list '() '() p) p] |
| 14 | + [(list ys gs p) (error "undefined identifiers" (append ys gs))])) |
| 15 | + |
| 16 | +;; S-Expr -> Expr |
| 17 | +;; Parse a (potentially open) expression |
| 18 | +(define (parse-e s) |
| 19 | + (match (parse-e/acc s '() '() '() '()) |
| 20 | + [(list _ _ e) e])) |
| 21 | + |
| 22 | +;; S-Expr -> Expr |
| 23 | +;; Parse a (potentially open) definition |
16 | 24 | (define (parse-define s) |
| 25 | + (match (parse-define/acc s '() '() '() '()) |
| 26 | + [(list _ _ d) d])) |
| 27 | + |
| 28 | +;; S-Expr -> r:[Listof Id] |
| 29 | +;; where: (distinct? r) |
| 30 | +;; Extracts defined function names from given program-like s-expr |
| 31 | +;; Does not fully parse definition |
| 32 | +;; Example: |
| 33 | +;; (parse-defn-names '((define (f x) x) (define (g y) y) 1) -> '(f g) |
| 34 | +(define (parse-defn-names ss) |
| 35 | + (define (rec ss fs) |
| 36 | + (match ss |
| 37 | + [(list s) fs] |
| 38 | + [(cons (cons 'define sd) sr) |
| 39 | + (match (parse-defn-name sd) |
| 40 | + [f (if (memq f fs) |
| 41 | + (error "duplicate definition" f) |
| 42 | + (rec sr (cons f fs)))])] |
| 43 | + [_ (error "parse error")])) |
| 44 | + (rec ss '())) |
| 45 | + |
| 46 | +(define (parse-defn-name s) |
| 47 | + (match s |
| 48 | + [(cons (cons (? symbol? f) _) _) f] |
| 49 | + [(cons (? symbol? f) _) f] |
| 50 | + [_ (error "parse error")])) |
| 51 | + |
| 52 | +;; S-Expr [Listof Id] [Listof Id] [Listof Id] [Listof Id] -> (list [Listof Id] [Listof Id] Prog) |
| 53 | +;; s: program shaped s-expr to be parsed |
| 54 | +;; fs: defined function names |
| 55 | +;; xs: bound variables |
| 56 | +;; ys: free variables |
| 57 | +;; gs: undefined function names |
| 58 | +;; returns list of free variables, undefined function names, and parse of program |
| 59 | +(define (parse-prog s fs xs ys gs) |
| 60 | + (match s |
| 61 | + [(list s) |
| 62 | + (match (parse-e/acc s fs xs ys gs) |
| 63 | + [(list ys gs e) |
| 64 | + (list ys gs (Prog '() e))])] |
| 65 | + [(cons s ss) |
| 66 | + (match (parse-define/acc s fs xs ys gs) |
| 67 | + [(list ys gs (and d (Defn f _))) |
| 68 | + (match (parse-prog ss (cons f fs) xs ys gs) |
| 69 | + [(list ys gs (Prog ds e)) |
| 70 | + (list ys gs (Prog (cons d ds) e))])])])) |
| 71 | + |
| 72 | + |
| 73 | +;; S-Expr [Listof Id] [Listof Id] [Listof Id] [Listof Id] -> (list [Listof Id] [Listof Id] Defn) |
| 74 | +;; s: definition shaped s-expr to be parsed |
| 75 | +;; fs: defined function names |
| 76 | +;; xs: bound variables |
| 77 | +;; ys: free variables |
| 78 | +;; gs: undefined function names |
| 79 | +;; returns list of free variables, undefined function names, and parse of definition |
| 80 | +(provide (all-defined-out)) |
| 81 | +(define (parse-define/acc s fs xs ys gs) |
| 82 | + (match s |
| 83 | + [(list 'define (? symbol? f) (cons 'case-lambda sr)) |
| 84 | + (match (parse-case-lambda/acc sr fs xs ys gs) |
| 85 | + [(list ys gs fun) |
| 86 | + (list ys gs (Defn f fun))])] |
| 87 | + [(cons 'define (cons (cons (? symbol? f) ps) sr)) |
| 88 | + (match (parse-define-plain-or-rest-fun/acc (cons ps sr) fs xs ys gs) |
| 89 | + [(list ys gs fun) |
| 90 | + (list ys gs (Defn f fun))])] |
| 91 | + [_ (error "parse error")])) |
| 92 | + |
| 93 | +(define (parse-case-lambda/acc s fs xs ys gs) |
| 94 | + (match s |
| 95 | + ['() (list ys gs (FunCase '()))] |
| 96 | + [(cons s sr) |
| 97 | + (match (parse-define-plain-or-rest-fun/acc s fs xs ys gs) |
| 98 | + [(list ys gs l) |
| 99 | + (match (parse-case-lambda/acc sr fs xs ys gs) |
| 100 | + [(list ys gs (FunCase ls)) |
| 101 | + (list ys gs (FunCase (cons l ls)))])])] |
| 102 | + [_ (error "parse error")])) |
| 103 | + |
| 104 | +(define (parse-define-plain-or-rest-fun/acc s fs xs ys gs) |
| 105 | + (match s |
| 106 | + [(list '() s) |
| 107 | + (match (parse-e/acc s fs xs ys gs) |
| 108 | + [(list ys gs e) |
| 109 | + (list ys gs (FunPlain '() e))])] |
| 110 | + [(list (? symbol? r) s) |
| 111 | + (match (parse-e/acc s fs (cons r xs) ys gs) |
| 112 | + [(list ys gs e) |
| 113 | + (list ys gs (FunRest '() r e))])] |
| 114 | + [(list (cons (? symbol? x) r) s) |
| 115 | + (match (parse-define-plain-or-rest-fun/acc (list r s) fs (cons x xs) ys gs) |
| 116 | + [(list ys gs (FunPlain xs e)) |
| 117 | + (list ys gs (FunPlain (cons x xs) e))] |
| 118 | + [(list ys gs (FunRest xs r e)) |
| 119 | + (list ys gs (FunRest (cons x xs) r e))])] |
| 120 | + [_ (error "parse error")])) |
| 121 | + |
| 122 | +;; S-Expr [Listof Id] [Listof Id] [Listof Id] [Listof Id] -> (list [Listof Id] [Listof Id] Expr) |
| 123 | +;; s: expression shaped s-expr to be parsed |
| 124 | +;; fs: defined function names |
| 125 | +;; xs: bound variables |
| 126 | +;; ys: free variables |
| 127 | +;; gs: undefined function names |
| 128 | +;; returns list of free variables, undefined function names, and parse of expression |
| 129 | +(define (parse-e/acc s fs xs ys gs) |
| 130 | + (define (rec s xs ys gs) |
| 131 | + (define ns (append fs xs)) |
| 132 | + (match s |
| 133 | + [(and 'eof (? (not-in ns))) |
| 134 | + (list ys gs (Eof))] |
| 135 | + [(? datum?) |
| 136 | + (list ys gs (Lit s))] |
| 137 | + [(list 'quote (list)) |
| 138 | + (list ys gs (Lit '()))] |
| 139 | + [(? symbol? (? (not-in fs))) |
| 140 | + (if (memq s xs) |
| 141 | + (list ys gs (Var s)) |
| 142 | + (list (cons s ys) gs (Var s)))] |
| 143 | + [(list-rest (? symbol? (? (not-in ns) k)) sr) |
| 144 | + (match k |
| 145 | + ['let |
| 146 | + (match sr |
| 147 | + [(list (list (list (? symbol? x) s1)) s2) |
| 148 | + (match (rec s1 xs ys gs) |
| 149 | + [(list ys gs e1) |
| 150 | + (match (rec s2 (cons x xs) ys gs) |
| 151 | + [(list ys gs e2) |
| 152 | + (list ys gs (Let x e1 e2))])])] |
| 153 | + [_ (error "let: bad syntax" s)])] |
| 154 | + ['apply |
| 155 | + (match sr |
| 156 | + [(list-rest (? symbol? f) sr) |
| 157 | + (parse-apply/acc sr f fs xs ys (if (memq f fs) gs (cons f gs)))])] |
| 158 | + [_ |
| 159 | + (match (parse-es/acc sr fs xs ys gs) |
| 160 | + [(list ys gs es) |
| 161 | + (match (cons k es) |
| 162 | + [(list (? op0? o)) |
| 163 | + (list ys gs (Prim0 o))] |
| 164 | + [(list (? op1? o) e1) |
| 165 | + (list ys gs (Prim1 o e1))] |
| 166 | + [(list (? op2? o) e1 e2) |
| 167 | + (list ys gs (Prim2 o e1 e2))] |
| 168 | + [(list (? op3? o) e1 e2 e3) |
| 169 | + (list ys gs (Prim3 o e1 e2 e3))] |
| 170 | + [(list 'begin e1 e2) |
| 171 | + (list ys gs (Begin e1 e2))] |
| 172 | + [(list 'if e1 e2 e3) |
| 173 | + (list ys gs (If e1 e2 e3))] |
| 174 | + [(list-rest g es) |
| 175 | + (list ys (cons g gs) (App g es))])])])] |
| 176 | + [(list-rest (? symbol? g) sr) |
| 177 | + (match (parse-es/acc sr fs xs ys gs) |
| 178 | + [(list ys s es) |
| 179 | + (list ys (if (memq g fs) gs (cons g gs)) (App g es))])] |
| 180 | + [_ |
| 181 | + (error "parse error" s)])) |
| 182 | + (rec s xs ys gs)) |
| 183 | + |
| 184 | +;; S-Expr Id [Listof Id] [Listof Id] [Listof Id] [Listof Id] -> (list [Listof Id] [Listof Id] Apply) |
| 185 | +(define (parse-apply/acc s f fs xs ys gs) |
| 186 | + (match s |
| 187 | + [(list s) |
| 188 | + (match (parse-e/acc s fs xs ys gs) |
| 189 | + [(list ys gs e) |
| 190 | + (list ys gs (Apply f '() e))])] |
| 191 | + [(cons s sr) |
| 192 | + (match (parse-e/acc s fs xs ys gs) |
| 193 | + [(list ys gs e) |
| 194 | + (match (parse-apply/acc sr f fs xs ys gs) |
| 195 | + [(list ys gs (Apply f es e0)) |
| 196 | + (list ys gs (Apply f (cons e es) e0))])])])) |
| 197 | + |
| 198 | +;; S-Expr [Listof Id] [Listof Id] [Listof Id] [Listof Id] -> (list [Listof Id] [Listof Id] [Listof Expr]) |
| 199 | +;; s: list of expressions shaped s-expr to be parsed |
| 200 | +;; fs: defined function names |
| 201 | +;; xs: bound variables |
| 202 | +;; ys: free variables |
| 203 | +;; gs: undefined function names |
| 204 | +;; returns list of free variables, undefined function names, and list of parsed expressions |
| 205 | +(define (parse-es/acc s fs xs ys gs) |
17 | 206 | (match s |
18 | | - [(list 'define (? symbol? f) |
19 | | - (cons 'case-lambda cs)) |
20 | | - (Defn f (FunCase (parse-case-lambda-clauses cs)))] |
21 | | - [(list 'define (cons (? symbol? f) xs) e) |
22 | | - (if (all symbol? xs) |
23 | | - (Defn f (parse-param-list xs e)) |
24 | | - (error "parse definition error"))] |
25 | | - [_ (error "Parse defn error" s)])) |
26 | | - |
27 | | -;; like andmap, but work on improper lists too |
| 207 | + ['() (list ys gs '())] |
| 208 | + [(cons s ss) |
| 209 | + (match (parse-e/acc s fs xs ys gs) |
| 210 | + [(list ys gs e) |
| 211 | + (match (parse-es/acc ss fs xs ys gs) |
| 212 | + [(list ys gs es) |
| 213 | + (list ys gs (cons e es))])])] |
| 214 | + [_ (error "parse error")])) |
| 215 | + |
| 216 | +(define (distinct? xs) |
| 217 | + (not (check-duplicates xs))) |
| 218 | + |
| 219 | +;; like andmap, but works on improper lists too |
28 | 220 | (define (all p? xs) |
29 | 221 | (match xs |
30 | 222 | ['() #t] |
31 | 223 | [(cons x xs) (and (p? x) (all p? xs))] |
32 | 224 | [x (p? x)])) |
33 | 225 |
|
34 | | -;; S-Expr -> [Listof FunCaseClause] |
35 | | -(define (parse-case-lambda-clauses cs) |
36 | | - (match cs |
37 | | - ['() '()] |
38 | | - [(cons c cs) |
39 | | - (cons (parse-case-lambda-clause c) |
40 | | - (parse-case-lambda-clauses cs))] |
41 | | - [_ |
42 | | - (error "parse case-lambda error")])) |
43 | | - |
44 | | -;; S-Expr -> FunRest |
45 | | -(define (parse-case-lambda-clause c) |
46 | | - (match c |
47 | | - [(list (? symbol? x) e) |
48 | | - (FunRest '() x (parse-e e))] |
49 | | - [(list xs e) |
50 | | - (parse-param-list xs e)])) |
51 | | - |
52 | | -;; S-Expr S-Expr -> FunPlain or FunRest |
53 | | -(define (parse-param-list xs e) |
54 | | - (match xs |
55 | | - ['() (FunPlain '() (parse-e e))] |
56 | | - [(cons x xs) |
57 | | - (match (parse-param-list xs e) |
58 | | - [(FunPlain xs e) (FunPlain (cons x xs) e)] |
59 | | - [(FunRest xs y e) (FunRest (cons x xs) y e)])] |
60 | | - [(? symbol? xs) |
61 | | - (FunRest '() xs (parse-e e))] |
62 | | - [_ |
63 | | - (error "parse parameter list error")])) |
64 | | - |
65 | | -;; S-Expr -> Expr |
66 | | -(define (parse-e s) |
67 | | - (match s |
68 | | - [(? datum?) (Lit s)] |
69 | | - ['eof (Eof)] |
70 | | - [(? symbol?) (Var s)] |
71 | | - [(list 'quote (list)) (Lit '())] |
72 | | - [(list (? op0? p0)) (Prim0 p0)] |
73 | | - [(list (? op1? p1) e) (Prim1 p1 (parse-e e))] |
74 | | - [(list (? op2? p2) e1 e2) (Prim2 p2 (parse-e e1) (parse-e e2))] |
75 | | - [(list (? op3? p3) e1 e2 e3) |
76 | | - (Prim3 p3 (parse-e e1) (parse-e e2) (parse-e e3))] |
77 | | - [(list 'begin e1 e2) |
78 | | - (Begin (parse-e e1) (parse-e e2))] |
79 | | - [(list 'if e1 e2 e3) |
80 | | - (If (parse-e e1) (parse-e e2) (parse-e e3))] |
81 | | - [(list 'let (list (list (? symbol? x) e1)) e2) |
82 | | - (Let x (parse-e e1) (parse-e e2))] |
83 | | - [(cons 'apply (cons (? symbol? f) es)) |
84 | | - (parse-apply f es)] |
85 | | - [(cons (? symbol? f) es) |
86 | | - (App f (map parse-e es))] |
87 | | - [_ (error "Parse error" s)])) |
88 | | - |
89 | | -;; Id S-Expr -> Expr |
90 | | -(define (parse-apply f es) |
91 | | - (match es |
92 | | - [(list e) (Apply f '() (parse-e e))] |
93 | | - [(cons e es) |
94 | | - (match (parse-apply f es) |
95 | | - [(Apply f es e0) |
96 | | - (Apply f (cons (parse-e e) es) e0)])] |
97 | | - [_ (error "parse apply error")])) |
| 226 | +;; [Listof Any] -> (Any -> Boolean) |
| 227 | +(define (not-in m) |
| 228 | + (λ (x) (not (memq x m)))) |
| 229 | +(define (in m) |
| 230 | + (λ (x) (memq x m))) |
98 | 231 |
|
99 | 232 |
|
100 | 233 | ;; Any -> Boolean |
|
0 commit comments