{Record whitespace token} Where Let (whitespace text i) Let n (STRING.length text) In Let (chomp_line i) Iterate {i} From {i} If (i = n) i If ((STRING.fetch text i) = '\n') (i + 1) Continue {(i + 1)} In Iterate {i} From {i} If (i = n) i Switch (STRING.fetch text i) | ' ' Continue {(i + 1)} | '\n' Continue {(i + 1)} | '\\' Continue {(chomp_line i)} | _ i ; Let (token text i) If (i = (STRING.length text)) {i `eof} Switch (STRING.fetch text i) | '\'' (scan_char text i) | '"' (scan_string text i) | c Cond | (ASCII.is_letter c) (scan_word text i) | (ASCII.is_digit c) (scan_number text i) | True (scan_basic_symbol text i) ; ; Where Let (scan_char text i) Let i (i + 1) In Let {c i} Switch (peek text i) | '\\' Let i (i + 1) In Switch (peek text i) | '\\' {'\\' i} | 'n' {'\n' i} | '\'' {'\'' i} | _ (OS.die "Invalid character escape sequence.") ; | '\'' (OS.die "Empty character literal.") | '\n' (OS.die "Character literal contains newline.") | c {c i} ; In If !((peek text (i + 1)) = '\'') (OS.die "Expected quotation mark to end character literal.") {(i + 2) `num.c} Let (scan_string text i) Let begin i Let i (i + 1) In Iterate {i} From {i} Switch (peek text i) | '"' Let end (i + 1) In Let token `str.(STRING.clip text begin end) In {end token} | '\\' Let j (i + 1) Let k (i + 2) In Switch (peek text j) | '\\' Continue {k} | 'n' Continue {k} | '"' Continue {k} | _ (OS.die "Invalid character escape sequence.") ; | '\n' (OS.die "String literal contains newline.") | _ Continue {(i + 1)} ; Let (scan_number text i) Iterate {i num} From {i 0} Let c (peek text i) In If !(ASCII.is_digit c) {i `num.num} Continue {(i + 1) ((10 * num) + (c - '0'))} Let (scan_word text i) Let begin i In Iterate {i seen_upper seen_lower} From {i False False} Switch (peek text i) | '_' Continue {(i + 1) seen_upper seen_lower} | '\'' Continue {(i + 1) seen_upper seen_lower} | c If (ASCII.is_digit c) Continue {(i + 1) seen_upper seen_lower} If (ASCII.is_letter c) Continue {(i + 1) Or seen_upper (ASCII.is_upper c) Or seen_lower (ASCII.is_lower c)} If And seen_upper seen_lower {i `sym.(STRING.clip text begin i)} {i `id.(STRING.clip text begin i)} ; Let (scan_basic_symbol text i) {(i + 1) `sym.(STRING.clip text i (i + 1))} Where Let (peek text i) If (i >= (STRING.length text)) (OS.die "Unexpected EOF.") (STRING.fetch text i) Where Let ASCII Package "ascii" Let OS Package "os" Let STRING Package "string"