let handle_syntax_error ~source ~lexbuf f = try f () with | Lexer.IllegalCharacter illegal_char -> Error.illegal_character ~loc:(Asai.Range.of_lexbuf ~source lexbuf) illegal_char | Grammar.Error -> Error.syntax_error ~loc:(Asai.Range.of_lexbuf ~source lexbuf) let parse_expr (s : string) : Ast.expr = let lexbuf = Lexing.from_string s in let string_source : Asai.Range.string_source = { title = None; content = s; } in let source = `String string_source in Eff.run ~env:source @@ fun () -> handle_syntax_error ~source ~lexbuf @@ fun () -> Grammar.start_expr Lexer.token lexbuf let parse_file (path : string) : Ast.file = let inchan = try open_in path with | Sys_error msg -> Error.file_open_error ~path ~msg in let lexbuf = Lexing.from_channel inchan in let source = `File path in Eff.run ~env:source @@ fun () -> handle_syntax_error ~source ~lexbuf @@ fun () -> Grammar.start_file Lexer.token lexbuf