fun dummy() {} Func = type(dummy) | type(print); Scanner = { src: String, i: int, hint: Func, current: Func, consume: Func, consumeSpaces: Func }; fun hint(scan: Scanner, n: int = 1) { k = scan.i + n; if k < count(scan.src): return scan.src[k]; return none; } fun current(scan: Scanner) return hint(scan, 0); fun consume(scan: Scanner, n: int = 1) { assert(n > 0); limit = count(scan.src); scan.i = min(scan.i + n, limit); return current(scan); } fun consumeSpaces(scan: Scanner) { char = current(scan); while isSpace(char): char = consume(scan); return char; } fun newScanner(src: String) { scan = { src: src, i: 0, hint: hint, consume: consume, current: current, consumeSpaces: consumeSpaces }; assert(istypeof(Scanner, scan)); return scan; } fun isDigit(char: ?String) { if char == none: return false; return string.ord(char) >= string.ord('0') and string.ord(char) <= string.ord('9'); } fun isSpace(c: String) return c == ' ' or c == '\t' or c == '\n'; fun min(x, y) { if x < y: return x; return y; }