package smtml
Source file parse.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84(* SPDX-License-Identifier: MIT *) (* Copyright (C) 2023-2026 formalsec *) (* Written by the Smtml programmers *) exception Syntax_error of string module Smtml = struct open Lexer open Lexing let pp_pos fmt lexbuf = let pos = lexbuf.lex_curr_p in Fmt.pf fmt "%s:%d:%d" pos.pos_fname pos.pos_lnum (pos.pos_cnum - pos.pos_bol + 1) let parse_with_error parser lexbuf = try parser Lexer.token lexbuf with | SyntaxError msg -> raise (Syntax_error (Fmt.str "%a: %s" pp_pos lexbuf msg)) | Parser.Error -> raise (Syntax_error (Fmt.str "%a: syntax error" pp_pos lexbuf)) module Script = struct let from_file filename = let res = Bos.OS.File.with_ic filename (fun chan () -> let lexbuf = Lexing.from_channel chan in lexbuf.lex_curr_p <- { lexbuf.lex_curr_p with pos_fname = Fpath.to_string filename }; parse_with_error Parser.script lexbuf ) () in match res with Error (`Msg e) -> Fmt.failwith "%s" e | Ok v -> v let from_string contents = parse_with_error Parser.script (Lexing.from_string contents) end module Expr = struct let from_file filename = let res = Bos.OS.File.with_ic filename (fun chan () -> let lexbuf = Lexing.from_channel chan in lexbuf.lex_curr_p <- { lexbuf.lex_curr_p with pos_fname = Fpath.to_string filename }; parse_with_error Parser.s_expr lexbuf ) () in match res with Error (`Msg e) -> Fmt.failwith "%s" e | Ok v -> v let from_string contents = parse_with_error Parser.s_expr (Lexing.from_string contents) end end module Smtlib = struct let from_file filename = try let _, st = Smtlib.parse_all (`File (Fpath.to_string filename)) in Lazy.force st with | Dolmen.Std.Loc.Syntax_error (loc, `Regular msg) -> raise (Syntax_error (Fmt.str "%a: syntax error: %t" Dolmen.Std.Loc.print_compact loc msg) ) | Dolmen.Std.Loc.Syntax_error (loc, `Advanced (x, _, _, _)) -> raise (Syntax_error (Fmt.str "%a: syntax error: %s" Dolmen.Std.Loc.print_compact loc x) ) end let from_file filename = match Fpath.split_ext filename with | _, ".smtml" -> Smtml.Script.from_file filename | _, ".smt2" -> Smtlib.from_file filename | fname, ext -> ( (* FIXME: I don't like this *) match Fpath.to_string fname with | "-" -> Smtml.Script.from_file filename | _ -> Fmt.failwith "Unsupported script type with extension '%s'" ext )