module Parser = Qparser.Parser.Make (Qsp_syntax.Tree) module Ast = Qsp_syntax.Tree.Ast let _position = (Lexing.dummy_pos, Lexing.dummy_pos) type 'a report = { level : Qsp_syntax.Report.level; loc : 'a; message : string } [@@deriving eq, show] let report : Ast.pos report Alcotest.testable = let equal = equal_report (fun _ _ -> true) in let pp = pp_report (fun formater _ -> Format.fprintf formater "_position") in Alcotest.testable pp equal let get_report : (Ast.pos Syntax.location, Qsp_syntax.Report.t) result -> Ast.pos report = function | Ok _ -> failwith "No error" | Error { level; loc; message } -> { level; loc; message } let _test_instruction : string -> Ast.pos report -> unit = fun literal expected -> let _location = Printf.sprintf {|# Location %s ------- |} literal in let actual = get_report @@ Syntax.parse _location and msg = literal in Alcotest.(check' report ~msg ~expected ~actual) let else_column () = _test_instruction {|IF 1: 0 ELSE: 1 END|} { level = Error; loc = _position; message = "Unexpected operator after `ELSE`"; } let elseif_no_column () = _test_instruction {|IF 1: 0 ELSEIF 0 1 END|} { level = Error; loc = _position; message = "The `ELIF` expression does not end properly. A `:` is expected before \ any instruction."; } let unclosed_paren () = _test_instruction {|(1 |} { level = Error; loc = _position; message = "Unexpected '('. Did you forgot a function before ?"; } let act_no_column () = _test_instruction {|ACT 1 0 END|} { level = Error; loc = _position; message = "Invalid `ACT` label. You probably missed a ':'"; } let missing_ampersand_1 () = _test_instruction "b = 1 a = 2" { level = Error; loc = _position; message = "Missing separator between instructions"; } let missing_ampersand_2 () = _test_instruction "let b = 1 a = 2" { level = Error; loc = _position; message = "Missing separator between instructions"; } let missing_ampersand_3 () = _test_instruction "set b = 1 a = 2" { level = Error; loc = _position; message = "Missing separator between instructions"; } let unclose_comment () = _test_instruction {| ! that's it|} { level = Error; loc = _position; message = "Unclosed text" } let syntax_error () = _test_instruction {|*clr $ cla|} { level = Error; loc = _position; message = "Unexpected character \"\"" } let test = ( "Syntax Errors", [ Alcotest.test_case "else:" `Quick else_column; Alcotest.test_case "elseif" `Quick elseif_no_column; Alcotest.test_case "(1" `Quick unclosed_paren; Alcotest.test_case "act 1" `Quick act_no_column; Alcotest.test_case "no &" `Quick missing_ampersand_1; Alcotest.test_case "no &" `Quick missing_ampersand_2; Alcotest.test_case "no &" `Quick missing_ampersand_3; Alcotest.test_case "unclose_comment" `Quick unclose_comment; Alcotest.test_case "Syntax error $" `Quick syntax_error; ] )