lib/std/lang/scanner/tests.rad 17.8 KiB raw
1
use std::lang::strings;
2
use std::mem;
3
use std::testing;
4
5
/// String pool for testing.
6
static TEST_STRING_POOL: strings::Pool = strings::Pool { table: [""; 32768], count: 0 };
7
8
/// Create a scanner backed by the test string pool.
9
fn testScanner(source: *[u8]) -> super::Scanner {
10
    return super::scanner(super::SourceLoc::File("test.r"), source, &mut TEST_STRING_POOL);
11
}
12
13
@test fn testScanTokens() throws (testing::TestError) {
14
    let mut s = testScanner(
15
        "'x' < fnord fnord: 0 => >> mod and nil"
16
    );
17
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Char);
18
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Lt);
19
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Ident);
20
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Ident);
21
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Colon);
22
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Number);
23
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::FatArrow);
24
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::GtGt);
25
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Mod);
26
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::And);
27
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Nil);
28
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Eof);
29
}
30
31
@test fn testScanChars() throws (testing::TestError) {
32
    let mut s = testScanner(
33
        "'\\0'"
34
    );
35
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Char);
36
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Eof);
37
}
38
39
@test fn testScanWhitespace() throws (testing::TestError) {
40
    let mut s = testScanner(
41
        " X\n\nY //\n Z//1 \n"
42
    );
43
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Ident);
44
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Ident);
45
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Ident);
46
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Eof);
47
}
48
49
@test fn testScanIdentsAndKeywords() throws (testing::TestError) {
50
    let mut s = testScanner(
51
        "m mo mod modo"
52
    );
53
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Ident);
54
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Ident);
55
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Mod);
56
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Ident);
57
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Eof);
58
}
59
60
@test fn testScanIdentifiers() throws (testing::TestError) {
61
    let mut s = testScanner(
62
        "fnord::yikes no1 4j"
63
    );
64
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Ident);
65
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::ColonColon);
66
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Ident);
67
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Ident);
68
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Number);
69
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Ident);
70
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Eof);
71
}
72
73
@test fn testScanAtIdentifiers() throws (testing::TestError) {
74
    let mut s = testScanner(
75
        "@default @"
76
    );
77
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::AtIdent);
78
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Invalid);
79
}
80
81
@test fn testScanStrings() throws (testing::TestError) {
82
    let mut s = testScanner(
83
        "\"Hello World!\" \"\\\"\""
84
    );
85
    let mut t: super::Token = super::next(&mut s, &mut TEST_STRING_POOL);
86
    try testing::expect(t.kind == super::TokenKind::String);
87
    try testing::expect(t.source.len == 14); // Includes quotes.
88
    try testing::expect(mem::eq(t.source, "\"Hello World!\""));
89
90
    set t = super::next(&mut s, &mut TEST_STRING_POOL);
91
    try testing::expect(t.kind == super::TokenKind::String);
92
    try testing::expect(t.source.len == 4);
93
    try testing::expect(mem::eq(t.source, "\"\\\"\""));
94
}
95
96
@test fn testGetLocation() throws (testing::TestError) {
97
    let mut s = testScanner(
98
        "abc\n  def\n    ghi"
99
    );
100
    let mut tok: super::Token = super::next(&mut s, &mut TEST_STRING_POOL);
101
    try testing::expect(tok.kind == super::TokenKind::Ident);
102
    try testing::expect(tok.source.len == 3);
103
104
    if let loc = super::getLocation(s.sourceLoc, s.source, tok.offset) {
105
        try testing::expect(loc.line == 1);
106
        try testing::expect(loc.col == 1);
107
    } else {
108
        try testing::expect(false);
109
    }
110
    set tok = super::next(&mut s, &mut TEST_STRING_POOL);
111
    try testing::expect(tok.kind == super::TokenKind::Ident);
112
    try testing::expect(tok.source.len == 3);
113
114
    if let loc = super::getLocation(s.sourceLoc, s.source, tok.offset) {
115
        try testing::expect(loc.line == 2);
116
        try testing::expect(loc.col == 3);
117
    } else {
118
        try testing::expect(false);
119
    }
120
    set tok = super::next(&mut s, &mut TEST_STRING_POOL);
121
    try testing::expect(tok.kind == super::TokenKind::Ident);
122
    try testing::expect(tok.source.len == 3);
123
124
    if let loc = super::getLocation(s.sourceLoc, s.source, tok.offset) {
125
        try testing::expect(loc.line == 3);
126
        try testing::expect(loc.col == 5);
127
    } else {
128
        try testing::expect(false);
129
    }
130
}
131
132
@test fn testScanEmptyInput() throws (testing::TestError) {
133
    let mut s = testScanner("");
134
    let tok: super::Token = super::next(&mut s, &mut TEST_STRING_POOL);
135
136
    try testing::expect(tok.kind == super::TokenKind::Eof);
137
    try testing::expect(tok.source.len == 0);
138
    try testing::expect(tok.offset == 0);
139
}
140
141
@test fn testScanSingleCharTokens() throws (testing::TestError) {
142
    let mut s = testScanner(
143
        "(){}[] ,;+-*~|&"
144
    );
145
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::LParen);
146
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::RParen);
147
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::LBrace);
148
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::RBrace);
149
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::LBracket);
150
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::RBracket);
151
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Comma);
152
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Semicolon);
153
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Plus);
154
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Minus);
155
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Star);
156
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Tilde);
157
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Pipe);
158
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Amp);
159
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Eof);
160
}
161
162
@test fn testScanDoubleCharTokens() throws (testing::TestError) {
163
    let mut s = testScanner(
164
        "== <> <= >= < > >> << -> =>"
165
    );
166
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::EqualEqual);
167
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::LtGt);
168
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::LtEqual);
169
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::GtEqual);
170
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Lt);
171
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Gt);
172
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::GtGt);
173
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::LtLt);
174
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Arrow);
175
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::FatArrow);
176
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Eof);
177
}
178
179
@test fn testScanIdentifierLengths() throws (testing::TestError) {
180
    let mut s = testScanner(
181
        "sho xyz981 lal_lel"
182
    );
183
    let mut tok: super::Token = super::next(&mut s, &mut TEST_STRING_POOL);
184
    try testing::expect(tok.kind == super::TokenKind::Ident);
185
    try testing::expect(tok.source.len == 3);
186
187
    set tok = super::next(&mut s, &mut TEST_STRING_POOL);
188
    try testing::expect(tok.kind == super::TokenKind::Ident);
189
    try testing::expect(tok.source.len == 6);
190
191
    set tok = super::next(&mut s, &mut TEST_STRING_POOL);
192
    try testing::expect(tok.kind == super::TokenKind::Ident);
193
    try testing::expect(tok.source.len == 7);
194
}
195
196
@test fn testScanNumbers() throws (testing::TestError) {
197
    let mut s = testScanner(
198
        "2 -2 +2 value-2 value+2 value--2 value+-2 value-+2 f(-2)"
199
    );
200
    let expected: [super::TokenKind; 29] = [
201
        super::TokenKind::Number,
202
        super::TokenKind::Minus, super::TokenKind::Number,
203
        super::TokenKind::Plus, super::TokenKind::Number,
204
        super::TokenKind::Ident, super::TokenKind::Minus, super::TokenKind::Number,
205
        super::TokenKind::Ident, super::TokenKind::Plus, super::TokenKind::Number,
206
        super::TokenKind::Ident, super::TokenKind::Minus, super::TokenKind::Minus,
207
            super::TokenKind::Number,
208
        super::TokenKind::Ident, super::TokenKind::Plus, super::TokenKind::Minus,
209
            super::TokenKind::Number,
210
        super::TokenKind::Ident, super::TokenKind::Minus, super::TokenKind::Plus,
211
            super::TokenKind::Number,
212
        super::TokenKind::Ident, super::TokenKind::LParen, super::TokenKind::Minus,
213
            super::TokenKind::Number, super::TokenKind::RParen,
214
        super::TokenKind::Eof,
215
    ];
216
    for expectedKind in expected {
217
        try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == expectedKind);
218
    }
219
}
220
221
@test fn testScanKeywords() throws (testing::TestError) {
222
    let mut s = testScanner("nil mod not static unsafe where");
223
    let tok1: super::Token = super::next(&mut s, &mut TEST_STRING_POOL);
224
225
    try testing::expect(tok1.kind == super::TokenKind::Nil);
226
    try testing::expect(tok1.source.len == 3);
227
228
    let tok2: super::Token = super::next(&mut s, &mut TEST_STRING_POOL);
229
    try testing::expect(tok2.kind == super::TokenKind::Mod);
230
    try testing::expect(tok2.source.len == 3);
231
232
    let tok3: super::Token = super::next(&mut s, &mut TEST_STRING_POOL);
233
    try testing::expect(tok3.kind == super::TokenKind::Not);
234
    try testing::expect(tok3.source.len == 3);
235
236
    let tok4: super::Token = super::next(&mut s, &mut TEST_STRING_POOL);
237
    try testing::expect(tok4.kind == super::TokenKind::Static);
238
    try testing::expect(tok4.source.len == 6);
239
240
    let tok5: super::Token = super::next(&mut s, &mut TEST_STRING_POOL);
241
    try testing::expect(tok5.kind == super::TokenKind::Unsafe);
242
    try testing::expect(tok5.source.len == 6);
243
244
    let tok6: super::Token = super::next(&mut s, &mut TEST_STRING_POOL);
245
    try testing::expect(tok6.kind == super::TokenKind::Where);
246
    try testing::expect(tok6.source.len == 5);
247
}
248
249
@test fn testScanVoidAsIdent() throws (testing::TestError) {
250
    let mut s = testScanner("void");
251
    let tok: super::Token = super::next(&mut s, &mut TEST_STRING_POOL);
252
    try testing::expect(tok.kind == super::TokenKind::Ident);
253
    try testing::expect(tok.source.len == 4);
254
}
255
256
@test fn testScanWhitespaceAndComments() throws (testing::TestError) {
257
    let mut s = testScanner(
258
        "  \t\n  // This is a comment..\n  42"
259
    );
260
    let tok: super::Token = super::next(&mut s, &mut TEST_STRING_POOL);
261
    try testing::expect(tok.kind == super::TokenKind::Number);
262
    try testing::expect(tok.source.len == 2);
263
    try testing::expect(super::isEof(&s));
264
}
265
266
@test fn testScanInvalidCharacters() throws (testing::TestError) {
267
    let mut s = testScanner(
268
        "`#$"
269
    );
270
    let mut tok: super::Token = super::next(&mut s, &mut TEST_STRING_POOL);
271
    try testing::expect(tok.kind == super::TokenKind::Invalid);
272
    try testing::expect(tok.offset == 0);
273
274
    set tok = super::next(&mut s, &mut TEST_STRING_POOL);
275
    try testing::expect(tok.kind == super::TokenKind::Invalid);
276
    try testing::expect(tok.offset == 1);
277
278
    set tok = super::next(&mut s, &mut TEST_STRING_POOL);
279
    try testing::expect(tok.kind == super::TokenKind::Invalid);
280
    try testing::expect(tok.offset == 2);
281
}
282
283
@test fn testScanUnterminatedString() throws (testing::TestError) {
284
    let mut s = testScanner("\"Hello World!");
285
    let tok: super::Token = super::next(&mut s, &mut TEST_STRING_POOL);
286
287
    try testing::expect(tok.kind == super::TokenKind::Invalid);
288
    try testing::expect(tok.source == "unterminated string");
289
    try testing::expect(tok.offset == 0);
290
}
291
292
@test fn testScanUnderminatedStringEscape() throws (testing::TestError) {
293
    let mut s = testScanner("\"\\");
294
    let tok: super::Token = super::next(&mut s, &mut TEST_STRING_POOL);
295
296
    try testing::expect(tok.kind == super::TokenKind::Invalid);
297
}
298
299
@test fn testScanFunctionDefinition() throws (testing::TestError) {
300
    let mut s = testScanner(
301
        "fn add(a: i32, b: i32) -> i32 { return a + b; }"
302
    );
303
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Fn);
304
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Ident);
305
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::LParen);
306
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Ident);
307
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Colon);
308
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::I32);
309
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Comma);
310
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Ident);
311
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Colon);
312
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::I32);
313
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::RParen);
314
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Arrow);
315
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::I32);
316
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::LBrace);
317
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Return);
318
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Ident);
319
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Plus);
320
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Ident);
321
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Semicolon);
322
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::RBrace);
323
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Eof);
324
}
325
326
/// Region tokens preserve their names and do not consume character literals.
327
@test fn testScanRegions() throws (testing::TestError) {
328
    let mut s = testScanner("'x 'long_2 'x' '\\n' 'outer<'inner");
329
    let first = super::next(&mut s, &mut TEST_STRING_POOL);
330
    try testing::expect(first.kind == super::TokenKind::Region);
331
    try testing::expect(mem::eq(first.source, "'x"));
332
    let second = super::next(&mut s, &mut TEST_STRING_POOL);
333
    try testing::expect(second.kind == super::TokenKind::Region);
334
    try testing::expect(mem::eq(second.source, "'long_2"));
335
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Char);
336
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Char);
337
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Region);
338
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Lt);
339
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Region);
340
    try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Eof);
341
}
342
343
/// An apostrophe without a name or a closing quote is invalid.
344
@test fn testScanMalformedRegions() throws (testing::TestError) {
345
    for text in ["'", "'1", "'\\", "'\n"] {
346
        let mut s = testScanner(text);
347
        try testing::expect(super::next(&mut s, &mut TEST_STRING_POOL).kind == super::TokenKind::Invalid);
348
    }
349
}