julia
julia copied to clipboard
`unexpected "end"` error message sometimes seems to be not true
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 ")"
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.
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.
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.
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
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.)
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"'
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:
It should be: