Syntax Errors, oh no!

| | Comments (10)

"Syntax Error" is basically the compiler's version of throwing its hands into the air and saying "I dunno what's wrong here, but something's not right!" In an ideal world, you'd never see the cryptic "syntax error" creep into your programs. However, in an ideal world you'd never see "paramErr" or "ERROR_INVALID_PARAMETER", etc. At some point in every API designer's lifetime, they fall into this trap and it's just an unfortunate fact that sometimes programming can be obtuse.

Thankfully, REALbasic's compiler does a fairly reasonable job of protecting you from nondescript error codes. It's certainly gotten better over the years! Generally speaking, the compiler goes to great pains to figure out what the root of the problem is and tell you about it. But, sometimes you'll still run into a totally useless "syntax error" message -- how should you track down the real issue?

The vast majority of the time, your code isn't too far from being correct. So the logical place to start looking is at identifier names. If the identifier is actually a reserved word, the compiler really chokes on that and typically gives out "syntax errors" like candy at Halloween when you do it. The reason is because of the way the parser is implemented -- it makes tradeoffs between maintainability, extensibility and unfortunately, error reporting. The good news is, this case is generally easy to spot because of syntax highlighting. The bad news is that the IDE doesn't syntax highlight code item declarations (like method parameter lists, structures, etc). But, if you do run into a syntax error on a declaration, you can be pretty sure it's because you've inadvertently used a keyword as an identifier.

Generally speaking, the rest of the time when you get a syntax error, it's because you've done something so far outside of the language that the compiler cannot predict what you were going for. Some things are easy: missing a then at the end of an if statement. The compiler saw "if", and if the "then" is missing, it can tell you. But other things are hard. What should this do:


// This code is useless, don't expect it to work!
dim i() as Integer
(do while true)
i(0) = 12
loop

This code is obviously quite wrong. For starters, you use parens for grouping expressions, but do is a statement. What's more, do doesn't take the form of "do while" -- in fact, while doesn't belong in a do loop at all. Obviously, when you're code is this far off the beaten path, the compiler has a much harder time trying to decipher what you're after. Did you want a do loop? A while loop? An expression that evaluates out to a value? Something else entirely? It should come as no surprise that the compiler is unable to help you in this situation.

My recommendation is: if you get a syntax error outside of a declaration -- check the language reference to see whether you're doing things right as it may point out your mistake. If you meant to use a do loop, then look it up and see what syntax the compiler is expecting. If you're matching the expected syntax, then you're still rather stuck unfortunately. But most of the time, these two tidbits of information will help you to quickly find the root cause of the nefarious "syntax error."

This all boils down to the fact that the compiler views syntax errors as the catch-all for "this doesn't match any known patterns of code." What's more, the compiler views keywords as totally different things from identifiers. To the compiler, "CType" is as different from "foobar" as "foobar" is from "+". So if you mix and match keywords, identifiers and symbolics (like parens, or plus and minus, etc) in incoherent ways, the compiler is most likely going to give you a "syntax error" for your troubles.

That's not to say there's an excuse for ever throwing a "syntax error" as a compiler writer. It's totally useless information, and should be rectified by putting in more logic to improve the error reporting. Especially with a tool like REALbasic, considering the market it targets. But at least now, you hopefully have some new tools in your belt to help you out!

10 Comments

[quote]That's not to say there's an excuse for ever throwing a "syntax error" as a compiler writer.[/quote]
Oh come on, Aaron, short of renaming the error "I give up, why not try some REALbasic", it just isn't always possible to guess what the coder is aiming for, is it?

@Steve -- in the general sense, no. The compiler is never going to be able to guess what you mean with 100% accuracy when you feed it utter garbage. However, it is able to do much, much better than what RB does currently. Things like "syntax error" because you used a keyword instead of an identifier is entirely avoidable in much the same way as "missing then" is totally avoidable.

If you stare at it long enough, you'll see that the two problems are actually the *same*. In both cases, the source doesn't match any pattern in the grammar. It's a "syntax error." The difference is that we changed the grammar so that missing the "then" token *does* match the grammar -- we throw the error manually. But we've never changed the grammar so that you can get a reasonable error when you use a keyword in place of an identifier.

There are a lot of places where changing the compiler's parser implementation would actually yield significantly better error reporting. I just happened to pick on the most generic and useless error message of all time. :-P

hit on a method

hello:

goto hello

hello:

' where is goto go ? :)

@rgb -- hah! That's certainly an error situation, but I'm betting the compiler doesn't handle it too well. It should give you an intelligent error on the second definition of the "hello" label and fail to compile.

@rgb -- That's really funny, I didn't think the goto keyword even existed in RB. A quick test in 2008r4.2 shows that this compiles, and it chooses the label that occured first. What would Dijkstra say? :)

RB has always supported Goto. Nobody ever uses it, though. The Goto statement I implemented in the Houdini compiler (RB 5.0) was broken for over a year before anyone got around to filing a bug report.

Actually, I use it occasionally when calling C functions, when jumping to error handlers in the C style is appropriate.

@Charles -- which probably explains why it "worked" for you -- you weren't hitting the error handlers. ;-) Goto was broken such that it was basically a noop for almost a year before anyone reported it. That's a pretty telling sign that no one uses the feature.

Even though no one uses GOTO, I am glad to know that it is fixed. While you have some spare time, allow me to refer you to a paper by Guy Steele. In particular, see the "Note Omniscient Implementors".

@Charles -- if it's a supported language feature, even not one widely used, it had better work. And you are right, there are times when goto is a useful construct, just like there are times when MDI applications are appropriate on Windows. As in either case, when you see it initially, you recoil in disgust, but eventually you get over it. ;-)

Leave a comment