julia icon indicating copy to clipboard operation
julia copied to clipboard

`unexpected "end"` error message sometimes seems to be not true

Open StevenWhitaker opened this issue 2 years ago • 6 comments

I'm opening this issue based on a question on discourse.

Consider the following code:

if true
    x +
end

This will result in (at least on Julia 1.7.0)

ERROR: syntax: unexpected "end"

This error makes sense from the parser's perspective: the end is unexpected because a second argument to + is expected. But from the programmer's perspective, one could argue that the end is exactly where one would expect. The real error is that the + function call is missing an argument.

Could the error message be changed to point to the missing argument instead? Something like

ERROR: syntax: attempted to call an infix operator with just one argument

The unexpected "end" error also occurs when x + is replaced with, e.g., f(x,. In this case, a better error message might be something like

ERROR: syntax: incomplete function call - missing closing parenthesis ")"

StevenWhitaker avatar Jun 23 '22 13:06 StevenWhitaker

Would changing this error text to something like unexpected "end" or incomplete expression be sufficiently helpful? Obviously, this has changed nothing but it may help to direct the person to consider whether they've used illegal syntax.

If this error is unique to syntactically-incomplete expressions, a better error might be invalid expression "x +" (showing the incomplete expression rather than the interrupting item). I think that an error like this would quickly lead somebody to discover the issue in this example (or the i++ example from Discourse).

A message like infix used with single argument work well in this example. However, I'm not sure that there aren't different situations where it could be misleading. A little care would be necessary to make sure this only arises where it makes sense.

mikmoore avatar Jun 23 '22 17:06 mikmoore

I agree, but what makes this tricky is that we allow operator calls to continue to the next line, e.g.

1 +
  2

so this code looks like 1 + end to us. The sequence: operator, line break, end maybe deserves a special case though.

JeffBezanson avatar Jun 23 '22 20:06 JeffBezanson

The sequence: operator, line break, end maybe deserves a special case though.

This would certainly help. But I sometimes don't have a newline before end (mainly when working in the REPL). Even without the newline, though, the fact that end was unexpected implies something different was expected (or at least allowed). Wouldn't it be possible for the error to point out something about what was expected?

In other words, does the parser know an operator is being parsed? If so, when an unexpected end (or else or other keyword) is encountered, the parser could throw an error indicating that an operator argument was expected.

StevenWhitaker avatar Jun 23 '22 20:06 StevenWhitaker

We can't special-case on end alone. There are a number of situations where this is relevant:

[x + ]
(x + ,)
x + ;  y

Related, but catching on a different error:

true ? x+ : y

mikmoore avatar Jun 23 '22 20:06 mikmoore

We can't special-case on end alone.

Right. Even though I've been talking about end, I guess in my mind I was thinking that improving the error message for the unexpected "end" case would also cover all these other cases. Isn't it the same parsing code in each case?* Because in all cases the parser gets a valid expression, followed by an operator, and then is looking for a valid expression. It shouldn't matter whether the block began with if or [ or whatever else, IIUC.

*I guess parsing an array indexing expression uses a different parsing scheme because then end is allowed. But that just changes the list of unexpected tokens, otherwise the logic is the same, IIUC.

(BTW, I'm not considering the ternary operator error. In that case I'm not sure how the error message could be clearer.)

StevenWhitaker avatar Jun 24 '22 13:06 StevenWhitaker

Let me chip in with another example. Excuse the length, but the length of it is one reason it's not so easy to find the cause of the 'unexpected "end"'

image

Upon compilation, one gets, of course, the unexpected "end"

ERROR: syntax: unexpected "end"
Stacktrace:
 [1] top-level scope
   @ none:1

Did you spot the error?

There's a lot of nested if-then expressions. One not terminated with end? Is the compiler getting confused with that nested if-then with the else statement? Why does the compiler choke on the end statement that closes the function definition?

None of those.

It's a missing comma in the function definition:

image

It should be:

image

blackeneth avatar Aug 09 '22 10:08 blackeneth