Figuring out the error messages from the compiler can sometimes be the hardest part of getting a program to run. The syntax errors are easy enough but the type errors can be confusing even for experienced programmers. The good news is that once you get your program past the type checker there is often not much wrong with it. It's not unusual for programs hundreds of lines in length to just work the first time. The richness of the type system and its enforcement provide logic constraints that keep out many common programming errors.
The parser of the SML/NJ compiler uses error correction. This means that it attempts to correct a syntax error so that it can continue compiling. This lets it report more syntax errors in one run of the compiler. However the error messages report the corrections that it made and you have to invert its logic to figure out what your errors were.
The parser will attempt to either insert or delete one or more symbols to produce syntactically correct input. Here is an example.
fun f x let val i = 1 in i * i end |
syn1.sml:1.7 Error: syntax error: inserting EQUALOP |
This says that on line 1 at character position 7 it inserted an equals symbol. This was the right correction. Here's a more notorious error.
structure Main = struct fun f x = let val msg = "hello" in print msg; print "\n"; end end |
syn2.sml:9.5 Error: syntax error: inserting EQUALOP |
The semicolon in a sequence of expressions is only allowed between the expressions. The one at the end of the last print is wrong. But the parser's correction is to insert something else after the semicolon to get it into an internal position. Curiously, if the function is not inside a structure the parser produces a slightly better error message: syntax error found at END. If you leave out the semicolon between the prints this is not a syntax error but you will get a type error.