{ :show } Where Define (show file_name text message i) Let {line start} (locate_token text i) Let end i In Begin { (STDIO.print_line (STRING.concat [file_name & ":" & (Z.show line) & ": " & message & 'nil])) When [start < (STRING.length text)] { (show_token text start end) } } Where Define (locate_token text j) Let {k line} Iterate {i line k} From {0 1 0} If [i = j] {k line} If [(STRING.fetch text i) = `\n`] (Continue [i + 1] [line + 1] i) (Continue [i + 1] line k) In Iterate i From k Let start (SCAN.skip_whitespace text i) In Let {i _} (SCAN.token text start) In If [i = j] {line start} (Continue i) Define (show_token text start end) Let n (STRING.length text) In Iterate {j line line_start} From {0 0 0} Begin Cond { | [j = n] (OS.die "Unexpected EOF.") | [j = start] Let line_end Iterate i From j Cond { | [i = n] (OS.die "Unexpected EOF.") | [(STRING.fetch text i) = `\n`] i | True (Continue [i + 1]) } (STDIO.print_line (STRING.clip text line_start line_end)) Iterate i From line_start When [i != start] { (STDIO.print " ") (Continue [i + 1]) } Iterate i From start When [i != end] { (STDIO.print "^") (Continue [i + 1]) } (STDIO.print_line "") | [(STRING.fetch text j) = `\n`] (Continue [j + 1] [line + 1] [j + 1]) | True (Continue [j + 1] line line_start) } Where Open Z { :Infix < :Infix = :Infix != :Infix + } Open LIST {:Infix &} Where Let LIST Package "list" Let OS Package "os" Let SCAN Package "scan" Let STDIO Package "stdio" Let STRING Package "string" Let Z Package "z"