117 lines
2.7 KiB
Hare
117 lines
2.7 KiB
Hare
use memio;
|
|
use fmt;
|
|
use strings;
|
|
use io;
|
|
|
|
@test fn lex() void = {
|
|
const cases: [_](str, []token) = [
|
|
(`"hello" \greeting def`,
|
|
["hello", mksym("greeting"), mkword("def")]),
|
|
(`[dup *] (a -- a) \square def`,
|
|
[quotstart, mkword("dup"), mkword("*"), quotend,
|
|
mkcomment("a -- a"), mksym("square"),
|
|
mkword("def")]),
|
|
(`#t #f`, [true, false]),
|
|
(`#\a #\space #\nul`, ['a', ' ', '\0']),
|
|
(`"\x0a;" "\x2014;" "\x2f9f4;"`, ["\n", "—", "嶲"]),
|
|
(`#\x #\x0a; #\x2014; #\x2f9f4;`, ['x', '\n', '—', '嶲']),
|
|
];
|
|
|
|
for (let i = 0z; i < len(cases); i += 1) {
|
|
const src = strings::toutf8(cases[i].0);
|
|
const src = memio::fixed(src);
|
|
const lexer = newlexer(&src, "<string>");
|
|
defer close(&lexer);
|
|
|
|
for (let j = 0z; j < len(cases[i].1); j += 1) {
|
|
const want = cases[i].1[j];
|
|
const have = match (lex(&lexer)) {
|
|
case let tok: token =>
|
|
yield tok;
|
|
case io::EOF =>
|
|
assert(false, "reached EOF");
|
|
return;
|
|
case let err: error =>
|
|
assert(false, strerror(err));
|
|
return;
|
|
};
|
|
|
|
if (!tokeq(want, have)) {
|
|
fmt::printfln("Case {}: {}", i, cases[i].0)!;
|
|
fmt::print("\tExpected: ")!;
|
|
tokpp(want);
|
|
fmt::print("\tGot: ")!;
|
|
tokpp(have);
|
|
assert(false);
|
|
};
|
|
};
|
|
|
|
assert(lex(&lexer) is io::EOF);
|
|
};
|
|
};
|
|
|
|
fn tokeq(have: token, want: token) bool = {
|
|
match (want) {
|
|
case quotstart =>
|
|
return have is quotstart;
|
|
case quotend =>
|
|
return have is quotend;
|
|
case mapstart =>
|
|
return have is mapstart;
|
|
case mapend =>
|
|
return have is mapend;
|
|
case let w: word =>
|
|
return (have as word).v == w.v;
|
|
case let s: str =>
|
|
return have as str == s;
|
|
case let s: symbol =>
|
|
return (have as symbol).v == s.v;
|
|
case let c: comment =>
|
|
return (have as comment).v == c.v;
|
|
case let r: rune =>
|
|
return have as rune == r;
|
|
case let b: bool =>
|
|
return have as bool == b;
|
|
};
|
|
};
|
|
|
|
fn tokpp(tok: token) void = {
|
|
match (tok) {
|
|
case quotstart =>
|
|
fmt::println("[")!;
|
|
case quotend =>
|
|
fmt::println("]")!;
|
|
case mapstart =>
|
|
fmt::println("{")!;
|
|
case mapend =>
|
|
fmt::println("}")!;
|
|
case let w: word =>
|
|
fmt::println(w.v)!;
|
|
case let s: symbol =>
|
|
fmt::printfln("{}{}", if (s.kw) ":" else "\\", s.v)!;
|
|
case let s: str =>
|
|
fmt::printfln(`"{}"`, s)!;
|
|
case let c: comment =>
|
|
fmt::printfln("({})", c.v)!;
|
|
case let r: rune =>
|
|
for (let i = 0z; i < len(longcharnames); i += 1) {
|
|
if (r == longcharnames[i].1) {
|
|
fmt::printfln("#\\{}", longcharnames[i].0)!;
|
|
return;
|
|
};
|
|
};
|
|
fmt::printfln("#\\{}", r)!;
|
|
case let b: bool =>
|
|
fmt::println(if (b) "#t" else "#f")!;
|
|
};
|
|
};
|
|
|
|
fn mkword(v: const str) word =
|
|
word{ v = v };
|
|
|
|
fn mkcomment(v: const str) comment =
|
|
comment{ v = v };
|
|
|
|
fn mksym(v: const str, kw: bool = false) symbol =
|
|
symbol{ v = v, kw = kw };
|
|
|