Scanner = { src: String, i: int, hint: Callable, current: Callable, consume: Callable, consumeSpaces: Callable }; fun isSpace(c: String) return c == ' ' or c == '\t' or c == '\n'; fun newScanner(src: String) { scan = { src: src, i: 0, 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 scan->hint(0); fun consume(scan: Scanner, n: int = 1) { assert(n > 0); limit = count(scan.src); scan.i = min(scan.i + n, limit); return scan->current(); } fun consumeSpaces(scan: Scanner) { char = scan->current(); while isSpace(char): char = scan->consume(); return char; } }; assert(istypeof(Scanner, scan)); return scan; } fun isDigit(char: ?String) { if char == none: return false; ord = string.ord; return ord(char) >= ord('0') and ord(char) <= ord('9'); }