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']), ]; 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, ""); defer close(&lexer); for (let j = 0z; j < len(cases[i].1); j += 1) { const want = cases[i].1[j]; const have = lex(&lexer)! as token; 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 };