{Record show} Where Let (show file_name text message i) Let {line start} (locate_token text i) Let end i In Do (STDIO.print_line (STRING.concat [file_name ":" (Z.show line) ": " message])) Do If (start < (STRING.length text)) (show_token text start end) {} In {} Where Let (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.whitespace text i) In Let {i _} (SCAN.token text i) In If (i = j) {line start} Continue {i} Let (show_token text start end) Let n (STRING.length text) In Iterate {j line line_start} From {0 0 0} 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)} ; In Do (STDIO.print_line (STRING.clip text line_start line_end)) Do Iterate {i} From {line_start} Cond | !(i = start) Do (STDIO.print " ") In Continue {(i + 1)} | True {} ; Do Iterate {i} From {start} Cond | !(i = end) Do (STDIO.print "^") In Continue {(i + 1)} | True {} ; Do (STDIO.print_line "") In {} | ((STRING.fetch text j) = '\n') Continue {(j + 1) (line + 1) (j + 1)} | True Continue {(j + 1) line line_start} ; Where Let OS Package "os" Let SCAN Package "scan" Let STDIO Package "stdio" Let STRING Package "string" Let Z Package "z"