Commit | Line | Data |
---|---|---|
543d3420 SK |
1 | open Printf |
2 | ||
78c9eca5 SK |
3 | module List = ListLabels |
4 | ||
5 | let test_01 = | |
19284c5d | 6 | let name = "an array type and an array variable" in |
78c9eca5 | 7 | let code = |
8543fc37 | 8 | " \ |
19284c5d | 9 | /* "^name^" */ \ |
8543fc37 SK |
10 | let \ |
11 | type arrtype = array of int \ | |
12 | var arr1:arrtype := \ | |
13 | arrtype [10] of 0 \ | |
14 | in \ | |
15 | arr1 \ | |
16 | end \ | |
78c9eca5 SK |
17 | " |
18 | in | |
19 | let tokens = | |
543d3420 | 20 | let open Tiger.Parser in |
78c9eca5 SK |
21 | [ LET; |
22 | TYPE; ID "arrtype"; EQ; ARRAY; OF; ID "int"; | |
23 | VAR; ID "arr1"; COLON; ID "arrtype"; ASSIGN; | |
24 | ID "arrtype"; LBRACK; INT 10; RBRACK; OF; INT 0; | |
25 | IN; | |
26 | ID "arr1"; | |
27 | END | |
28 | ] | |
29 | in | |
19284c5d | 30 | (name, code, tokens) |
8543fc37 SK |
31 | |
32 | let test_02 = | |
19284c5d | 33 | let name = "arr1 is valid since expression 0 is int = myint" in |
8543fc37 SK |
34 | let code = |
35 | " \ | |
19284c5d | 36 | /* "^name^" */ \ |
8543fc37 SK |
37 | let \ |
38 | type myint = int \ | |
39 | type arrtype = array of myint \ | |
b828a6e7 | 40 | var arr1:arrtype := \ |
8543fc37 SK |
41 | arrtype [10] of 0 \ |
42 | in \ | |
43 | arr1 \ | |
44 | end \ | |
45 | " | |
46 | in | |
47 | let tokens = | |
543d3420 | 48 | let open Tiger.Parser in |
8543fc37 SK |
49 | [ LET; |
50 | TYPE; ID "myint"; EQ; ID "int"; | |
51 | TYPE; ID "arrtype"; EQ; ARRAY; OF; ID "myint"; | |
52 | VAR; ID "arr1"; COLON; ID "arrtype"; ASSIGN; | |
53 | ID "arrtype"; LBRACK; INT 10; RBRACK; OF; INT 0; | |
54 | IN; | |
55 | ID "arr1"; | |
56 | END | |
57 | ] | |
58 | in | |
19284c5d | 59 | (name, code, tokens) |
8543fc37 SK |
60 | |
61 | let test_03 = | |
19284c5d | 62 | let name = "a record type and a record variable" in |
8543fc37 SK |
63 | let code = |
64 | " \ | |
19284c5d | 65 | /* "^name^" */ \ |
8543fc37 SK |
66 | let \ |
67 | type rectype = \ | |
68 | { name : string \ | |
69 | , age : int \ | |
70 | } \ | |
71 | var rec1 : rectype := \ | |
72 | rectype \ | |
73 | { name = \"Nobody\" \ | |
74 | , age = 1000 \ | |
75 | } \ | |
76 | in \ | |
77 | rec1.name := \"Somebody\"; \ | |
78 | rec1 \ | |
79 | end \ | |
80 | " | |
81 | in | |
82 | let tokens = | |
543d3420 | 83 | let open Tiger.Parser in |
8543fc37 SK |
84 | [ LET; |
85 | TYPE; ID "rectype"; EQ; | |
86 | LBRACE; ID "name"; COLON; ID "string"; | |
87 | COMMA; ID "age"; COLON; ID "int"; | |
88 | RBRACE; | |
89 | VAR; ID "rec1"; COLON; ID "rectype"; ASSIGN; | |
90 | ID "rectype"; | |
91 | LBRACE; ID "name"; EQ; STRING "Nobody"; | |
92 | COMMA; ID "age"; EQ; INT 1000; | |
93 | RBRACE; | |
94 | IN; | |
95 | ID "rec1"; DOT; ID "name"; ASSIGN; STRING "Somebody"; SEMICOLON; | |
96 | ID "rec1"; | |
97 | END | |
98 | ] | |
99 | in | |
19284c5d | 100 | (name, code, tokens) |
78c9eca5 | 101 | |
1946b457 SK |
102 | let test_04 = |
103 | let name = "define a recursive function" in | |
104 | let code = | |
105 | " \ | |
106 | /* "^name^" */ \ | |
107 | let \ | |
108 | \ | |
109 | /* calculate n! */ \ | |
110 | function nfactor(n: int): int = \ | |
111 | if n = 0 \ | |
112 | then 1 \ | |
113 | else n * nfactor(n-1) \ | |
114 | \ | |
115 | in \ | |
116 | nfactor(10) \ | |
117 | end \ | |
118 | " | |
119 | in | |
120 | let tokens = | |
543d3420 | 121 | let open Tiger.Parser in |
1946b457 SK |
122 | [ LET; |
123 | FUNCTION; ID "nfactor"; LPAREN; ID "n"; COLON; ID "int"; RPAREN; COLON; ID "int"; EQ; | |
124 | IF; ID "n"; EQ; INT 0; | |
125 | THEN; INT 1; | |
126 | ELSE; ID "n"; TIMES; ID "nfactor"; LPAREN; ID "n"; MINUS; INT 1; RPAREN; | |
127 | IN; | |
128 | ID "nfactor"; LPAREN; INT 10; RPAREN; | |
129 | END | |
130 | ] | |
131 | in | |
132 | (name, code, tokens) | |
133 | ||
cb00a20d SK |
134 | let test_09 = |
135 | let name = "error : types of then - else differ" in | |
136 | let code = | |
543d3420 SK |
137 | " \ |
138 | /* "^name^" */ \ | |
139 | if (5>4) then 13 else \" \" \ | |
cb00a20d SK |
140 | " |
141 | in | |
142 | let tokens = | |
543d3420 | 143 | let open Tiger.Parser in |
cb00a20d SK |
144 | [ IF; LPAREN; INT 5; GT; INT 4; RPAREN; THEN; INT 13; ELSE; STRING " " |
145 | ] | |
146 | in | |
147 | (* TODO: Type error test case *) | |
148 | (name, code, tokens) | |
149 | ||
82e73e6c SK |
150 | let test_queens = |
151 | let code = | |
152 | " \n\ | |
153 | /* A program to solve the 8-queens problem */ \n\ | |
154 | \n\ | |
155 | let \n\ | |
156 | var N := 8 \n\ | |
157 | \n\ | |
158 | type intArray = array of int \n\ | |
159 | \n\ | |
160 | var row := intArray [ N ] of 0 \n\ | |
161 | var col := intArray [ N ] of 0 \n\ | |
162 | var diag1 := intArray [N+N-1] of 0 \n\ | |
163 | var diag2 := intArray [N+N-1] of 0 \n\ | |
164 | \n\ | |
165 | function printboard() = ( \n\ | |
166 | for i := 0 to N-1 do ( \n\ | |
167 | for j := 0 to N-1 do print(if col[i]=j then \" O\" else \" .\"); \n\ | |
168 | print(\"\n\") \n\ | |
169 | ); \n\ | |
170 | print(\"\n\") \n\ | |
171 | ) \n\ | |
172 | \n\ | |
173 | function try(c:int) = ( \n\ | |
174 | /* for i:= 0 to c do print(\".\"); print(\"\n\"); flush();*/ \n\ | |
175 | if c=N \n\ | |
176 | then printboard() \n\ | |
177 | else \n\ | |
178 | for r := 0 to N-1 \n\ | |
179 | do \n\ | |
180 | if row[r]=0 & diag1[r+c]=0 & diag2[r+7-c]=0 \n\ | |
181 | then ( \n\ | |
182 | row[r] := 1; \n\ | |
183 | diag1[r+c] := 1; \n\ | |
184 | diag2[r+7-c] := 1; \n\ | |
185 | col[c] := r; \n\ | |
186 | try(c+1); \n\ | |
187 | row[r] := 0; \n\ | |
188 | diag1[r+c] := 0; \n\ | |
189 | diag2[r+7-c] := 0 \n\ | |
190 | ) \n\ | |
191 | ) \n\ | |
192 | in \n\ | |
193 | try(0) \n\ | |
194 | end \n\ | |
195 | " | |
196 | in | |
197 | (code, code, []) | |
198 | ||
78c9eca5 SK |
199 | let tests = |
200 | [ test_01 | |
8543fc37 SK |
201 | ; test_02 |
202 | ; test_03 | |
1946b457 | 203 | ; test_04 |
cb00a20d | 204 | ; test_09 |
82e73e6c | 205 | ; test_queens |
78c9eca5 SK |
206 | ] |
207 | ||
208 | let () = | |
f03690fc SK |
209 | let tokens_of_code code = |
210 | let lexbuf = Lexing.from_string code in | |
211 | let rec tokens () = | |
212 | let token = Tiger.Lexer.token lexbuf in | |
213 | (* Avoiding fragile pattern-matching *) | |
214 | if token = Tiger.Parser.EOF then [] else token :: tokens () | |
215 | in | |
216 | tokens () | |
217 | in | |
218 | let parsetree_of_code code = | |
219 | let lb = Lexing.from_string code in | |
220 | (match Tiger.Parser.program Tiger.Lexer.token lb with | |
221 | | exception Parsing.Parse_error -> | |
222 | let module L = Lexing in | |
223 | let L.({lex_curr_p = {pos_lnum=l; pos_bol=b; pos_cnum=c; _}; _}) = lb in | |
224 | let msg = sprintf "Syntax error around line: %d, column: %d" l (c - b) in | |
225 | Error msg | |
226 | | parsetree -> | |
227 | Ok parsetree | |
228 | ) | |
229 | in | |
8543fc37 SK |
230 | let bar_sep = String.make 80 '-' in |
231 | let bar_end = String.make 80 '=' in | |
543d3420 SK |
232 | let indent n = String.make (2 * n) ' ' in |
233 | let color_on_green = "\027[0;32m" in | |
234 | let color_on_red = "\027[1;31m" in | |
235 | let color_off = "\027[0m" in | |
858f923a SK |
236 | List.iteri tests ~f:(fun i (name, code, tokens_expected) -> |
237 | let i = i + 1 in (* Because iteri starts with 0 *) | |
543d3420 SK |
238 | printf "%s\n%sTest %d : %S\n" bar_sep (indent 0) i name; |
239 | ||
240 | printf "%sLexing : " (indent 1); | |
8543fc37 SK |
241 | let tokens_emitted = tokens_of_code code in |
242 | (try | |
243 | assert (tokens_emitted = tokens_expected); | |
543d3420 | 244 | printf "%sOK%s\n" color_on_green color_off; |
8543fc37 SK |
245 | with Assert_failure _ -> |
246 | let tokens_to_string tokens = | |
543d3420 | 247 | String.concat "; " (List.map ~f:Tiger.Parser_token.to_string tokens) |
8543fc37 SK |
248 | in |
249 | printf | |
543d3420 SK |
250 | "%sERROR%s\n%sExpected: %s\n%sEmitted : %s\n\n" |
251 | color_on_red | |
252 | color_off | |
253 | (indent 2) | |
8543fc37 | 254 | (tokens_to_string tokens_expected) |
543d3420 | 255 | (indent 2) |
8543fc37 SK |
256 | (tokens_to_string tokens_emitted) |
257 | ); | |
543d3420 SK |
258 | |
259 | printf "%sParsing: " (indent 1); | |
260 | (match parsetree_of_code code with | |
261 | | Error errmsg -> printf "%sERROR:%s %s\n" color_on_red color_off errmsg | |
262 | | Ok parsetree -> printf "%sOK:%s %s\n" color_on_green color_off parsetree | |
263 | ); | |
264 | ||
8543fc37 SK |
265 | ); |
266 | print_endline bar_end; |