Search code examples
syntax-errorocamlfinite-automata

Ocaml does not recognize else


I am relatively new to Ocaml and I have come across an annoying error. My code is here:

let rec nfa_to_dfa_step (nfa: ('q,'s) nfa_t) (dfa: ('q list, 's) nfa_t)
    (work: 'q list list) : ('q list, 's) nfa_t =
  match work with 
  | [] -> dfa
  | h::t -> 
    if (h <> []) then 
      (match nfa with { sigma; qs; q0; fs; delta } ->
        (let states = (new_states nfa h) in 
          (union states qs);
          (union states t);
          (union (new_trans nfa h) delta);
          (union (fold_left (fun acc state -> 
            let cur_final = (new_finals nfa state) in
            if (cur_final <> []) then (cur_final::acc) else acc) [] states) fs);
          (nfa_to_dfa_step nfa dfa t)));;
    else 
        (nfa_to_dfa_step nfa dfa t)

and I get a syntax error on the else statement in the second to last line. I'm fairly sure it has something to do with parentheses and needing to put some where there aren't any, but I've put parentheses around everything and I've checked and double checked for mismatched ones. if I put parens around the entire if else statement I get a different error:

Error: Syntax error: ')' expected
File "src/nfa.ml", line 90, characters 4-5:
90 |     (if (h <> []) then
         ^
  This '(' might be unmatched

What am I doing wrong? Any ideas on how to debug this sort of error? I've been having issues like this quite a bit as I've been programming in ocaml. As someone who is used to imperative low level languages like c++, any advice on how to interpret and debug error messages like these would be appreciated.


Solution

  • As mentioned, ;; just after (nfa_to_dfa_step nfa dfa t))) is the culprit. To be a little more nuanced, ;; is not useless / syntactically invalid, it is used to end the "toplevel phrase". For example:

    (* say_hello is at toplevel *)
    let say_hello x = 
      (* the body of the function is not *)
      let message = "Hello " ^ x ^ "!" in
      print_endline ()
    ;; (* here, ;; is a terminaison for the function `say_hello`
          it is perfectly valid *)
    

    In order to avoid confusion, we can read here and there that ;; is only useful in the REPL. In my opinion it can be useful for error reporting. But if you don't want to worry about it, I recommend that you never put them on and use OCamlformat to have them place them for you.