aboutsummaryrefslogtreecommitdiff
path: root/test/syntax_error.ml
blob: fed43a7919c52ee37fd9c5222a210e7ff0aeab3a (plain)
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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 () =
  let result =
    {
      level = Error;
      loc = _position;
      message = "Missing separator between instructions";
    }
  in
  let () = _test_instruction "b = 1 a = 2" result
  and () = _test_instruction "let b = 1 a = 2" result
  and () = _test_instruction "set b = 1 a = 2" result in
  ()

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 missing_operand () =
  let result =
    { level = Error; loc = _position; message = "Missing operand" }
  in
  let () = _test_instruction {|if  and other: 1|} result
  and () = _test_instruction {|a =  and other: 1|} result in
  ()

let unknow_function () =
  _test_instruction "a = ran(1, 2)"
    { level = Error; loc = _position; message = "Unexpected expression here." }

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;
      Alcotest.test_case "unclose_comment" `Quick unclose_comment;
      Alcotest.test_case "Syntax error $" `Quick syntax_error;
      Alcotest.test_case "Missing operand" `Quick missing_operand;
      Alcotest.test_case "Unknown function" `Quick unknow_function;
    ] )