project1.lpr(4,20) Fatal: Syntax error, ";" expected but "ELSE" found
Simple question: are the FPC developers interested in correcting error messages that dangerously border on being incorrect ?
junk.lpr(4,28) Fatal: Syntax error, ";" expected but "ELSE" found
Fatal: Compilation aborted[/code]
which is not right since placing a semicolon between the "do" and the "else" does not yield a syntactically valid statement.
Delphi:
junk.lpr(4) Error: 'END' expected but 'ELSE' found
junk.lpr(19)which clearly indicates that the "else" simply doesn't belong there since it is followed by the expected keyword ("end" in this case.)
procedure yy;
begin
while true>false do
end;
procedure yy;
begin
while true>false do ;
end;
...This is your opinion, not fact. Solution C relegates the original else to text that gets ignored after the end of the program. Why is it any less correct to assume the else is out of place up front, and get the user to fix it.
The only possibility left, which is the correct one, is "end".
After adding an "end" (TEST_B) the compiler will complain about it not being followed by a period ".", after adding the period (per error message - TEST_C), the program is correct.
Both "end" and ";" would fix the "while".the semicolon is incorrect. I will explain, in detail why, below.
Both leave an error after it:true but, putting a semicolon will _not_ lead to a correct program. Putting "end" will. That's important.
You say that there can not be a ";", because after the ";" there must be a statement (and "else" is not).
This is your opinion, not fact.That's my opinion like 2 + 2 = 4 is my "opinion" too. I hope the explanation about the compound statement production above is sufficient to demonstrate that.
If the compiler finds a keyword, it must be either, a keyword that starts a new statement or "end" to match the compound statement's "begin".Well yes, we all agree that "else" should give an error, because it can not occur there.
After adding an "end" (TEST_B) the compiler will complain about it not being followed by a period ".", after adding the period (per error message - TEST_C), the program is correct.
Following Delphi's error message instructions yields a correct program. Following FPC's error message instructions does _not_ lead to a correct program.
procedure yy;
begin
while true>false do else
end;
But how do we getI didn't say it must expect a keyword. What I said is, if it finds a keyword that does not start a new statement, as in the case with "else", then the keyword must be "end". The reason for that is because the compiler is parsing a compound statement, therefore, it must expect a keyword to terminate the compound statement and, the _only_ keyword that does not start another statement that fulfills the requirement is "end".
- From: The compiler found an incorrect keyword
- To: Therefore it must expect a keyword (just a different keyword)?
If the keyword "else" is wrong, we can conclude something else must be expected. But that something else can be anything: A new none-empty statement, an empty statement followed by a ";", an "end".No, it cannot be anything. What the compiler (Delphi) is saying, if you want a keyword that does not start another statement (as is the case with "else") there then it _must_ be "end". There is no other choice.
Following your argument, that the compiler should treat an unexpected keyword as a special error, then it should simply stateIt's not a special error. A compound statement is terminated with "end". There is no reason for the compiler to go "generic" and state "incorrect keyword" when it knows that the only acceptable keyword that does not start another statement is "end". Since "else" does not start another statement then the only acceptable keyword that does not start another statement (as "else" is) is "end".
"incorrect keyword"
Yet, point in your favour:It's not so much that it uses knowledge of the outer block, once the "while" is parsed, execution returns to the "repeat" production to finish parsing it, at that time, it finds an "else". The only keyword that does not start another statement that "repeat" is going to accept is "until". Since, "else" does not start another statement, the production demands an "until" keyword, as it should.gives: Fatal: Syntax error, "UNTIL" expected but "ELSE" found
repeat while true do else
So it uses the knowledge about the outer block.
Personally, I would like to see the "; expected" error in the last case too. Just for consistency. (As both errors are equally good)It really shouldn't do that because, at some point the "repeat" production has to ask/demand the "until" it needs. It can't just go asking for another semicolon every time it needs an "until".
Of course, one has to ask why change the error at all.No, technically, it is incorrect. That's the problem, a compound statement is not ended with a semicolon, it's ended with an "end" keyword. It can't keep asking for semicolons endlessly. It really has to ask for the "end" and it has to ask for it whenever it see a symbol that does not start a new statement, whatever it may be.
Purely technically it is correct. (It is not complete, but it is one correct possibility, and neither would "end expected" be complete).
The reasons to change an error message are:On the contrary, the first applies in full. The compound statement is not asking for its terminating symbol, that's incorrect/wrong/bad/no good/trump.
1- It is plain wrong (but this is a subset of the next point)
2- The message can be improved to give the user a better idea what is wrong.
The first does not apply.
Given that ";" is statistically more likely, the "; expected" error is actually ever so slightly more helpful.Not if the programmer wants to eventually have a program that compiles because all the semicolons in the universe put before the else aren't going to do it.
It is basically a summary of the state of the parser, not a correction advise.Error messages are not correction advise ? ... if doing what they state isn't going to lead to a correct statement then why does the compiler bother emitting them ?... ascii visual entertainment ?...
Example: Delphi gives the exact same error for this code:But, here is the thing you are attempting to avoid. If you follow Delphi's corrective "suggestions" (not advice, of course) you will eventually end up with a program that compiles.
I think the Delphi solution is inferior.Interesting that the solution that leads to a syntactically correct program is "inferior" while the "solution" that has the programmer adding semicolons for infinity is not inferior.
Example: Delphi gives the exact same error for this code:But, here is the thing you are attempting to avoid. If you follow Delphi's corrective "suggestions" (not advice, of course) you will eventually end up with a program that compiles.
if you follow the instructions given by the compiler (Delphi), you end up with this (which compiles!) :
program TestWhileFOLLOW2; procedure yy; begin while true > false do end; //flup; end.
But how do we getI didn't say it must expect a keyword. What I said is, if it finds a keyword that does not start a new statement, as in the case with "else", then the keyword must be "end". The reason for that is because the compiler is parsing a compound statement, therefore, it must expect a keyword to terminate the compound statement and, the _only_ keyword that does not start another statement that fulfills the requirement is "end".
- From: The compiler found an incorrect keyword
- To: Therefore it must expect a keyword (just a different keyword)?
Obviously, a very minor thing but, it would be nice to see correct error messages whenever possible.
Delphis error message is completely wrong, there is no case in which While ... do end would be correct.
So the real error here should be something like "else without any if block found"
FPC's error message is also wrong but not as wrong as Delphis, because a do needs to be followed by an instruction which is in most cases terminated by a semicolon (note that begin-end block is nothing more than a composite instruction, and is like any other instruction usually terminated with a semicolon). That said, an instruction is only terminated by a semicolon in "most cases", the only case where this is not the case is an else expression, where the semicolon is ommited.
Pascal does not terminate statements, it separates them! This is a subtle, but important difference.Which is IMHO actually something bad about pascals syntax because it allows for omitting the ; before an end (and is also the reason why the stupid no ; before else thing exists), which in my oppinion is just a delayed compilation error, that occurs when you start to add lines later on.
As said above the parser does not know about this.But isn't this pretty much just an implementation detail? I mean whats stopping the parser from, when encountering the error, doing some more checks? I mean such an error only occurs if the if is dangling, so can't the parser on encountering this unexpected else just traverse the already parsed nodes backwards until it finds either begin of current block or if, and if there is no if then this else is dangling?
The entire point is, why must it be replaced/insertatian by a keyword?????Because the programmer typed a keyword - specifically "while" - that's one reason why. The other reasons are , because putting a semicolon before the "else" does not create a valid statement and, there is a "begin" that is expecting an "end" which is the only keyword that doesn't start another statement that is valid in that case. Those are the reasons why.
So the expected token can very well be a ";".No, because a ";" in that case violates the rules of the Pascal grammar, therefore ";" there, is not a possibility that leads to a syntactically valid program.
Delphis error message is completely wrong, there is no case in which While ... do end would be correct.In that case, all the Pascal compilers that compile this are "completely wrong":
The parser does not know at the moment of parsing the else that it is inside the statement block of the while-statement, it simply tries to read a statement (which can also be a begin … end block).But, there is one thing the parser knows with complete certainty which is, it was not parsing an "if" statement because if it had been parsing an "if" statement, the "if" production would have consumed the "else". Therefore, the parser knows that "else" in that location is incorrect.
The entire point is, why must it be replaced/insertatian by a keyword?????Because the programmer typed a keyword - specifically "while" - that's one reason why. The other reasons are , because putting a semicolon before the "else" does not create a valid statement and, there is a "begin" that is expecting an "end" which is the only keyword that doesn't start another statement that is valid in that case. Those are the reasons why.
Pascal does not terminate statements, it separates them! This is a subtle, but important difference.Which is IMHO actually something bad about pascals syntax because it allows for omitting the ; before an end (and is also the reason why the stupid no ; before else thing exists), which in my oppinion is just a delayed compilation error, that occurs when you start to add lines later on.
But I think as this is one of the core syntax structures of pascal, this will never change, and overall pascal is pretty good so I can live with such drawbacks
QuoteAs said above the parser does not know about this.But isn't this pretty much just an implementation detail? I mean whats stopping the parser from, when encountering the error, doing some more checks? I mean such an error only occurs if the if is dangling, so can't the parser on encountering this unexpected else just traverse the already parsed nodes backwards until it finds either begin of current block or if, and if there is no if then this else is dangling?
The parser does not know at the moment of parsing the else that it is inside the statement block of the while-statement, it simply tries to read a statement (which can also be a begin … end block).But, there is one thing the parser knows with complete certainty which is, it was not parsing an "if" statement because if it had been parsing an "if" statement, the "if" production would have consumed the "else". Therefore, the parser knows that "else" in that location is incorrect.
... apparently inaccurate error messages.Apparently ?...
Free Pascal Compiler version 3.0.4 [2017/10/06] for x86_64FPC seems to expect semicolons a little more than it should (semicolon fetish maybe ?). I really don't think that dividing by a semicolon will work in Pascal (it probably works in C though)
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Win64 for x64
Compiling TestMissingIdentifierInExpression.lpr
TestMissingIdentifierInExpression.lpr(7,28) Error: Illegal expression
TestMissingIdentifierInExpression.lpr(7,32) Fatal: Syntax error, ";" expected but "ordinal const" found
Fatal: Compilation aborted
But... I have to admit, I should have used the example in this post to make the point instead of the more terse example I used in the OP.
I'll have to check which route the parser takes to get to the error for this. If we can easily improve an error message we do, but some are simply a sideeffect of the parser's structure and reworking that is more effort than it's worth (like for your original example). So if you find others please continue to remark them, but don't be disappointed if we say "sorry, nothing to be done there".I don't want to give the wrong impression. I can tell that there are some areas in the compiler where the developers clearly made an effort to emit a reasonably good error message, in some cases, better than I expected. I definitely appreciate that and, because of that, I thought it might be helpful to report error messages that can certainly be "improved".
I understand that some of the error messages are a result of the parser's structure. That's normal. OTH, it is usually possible to assert the current symbol is in the set of expected/valid symbols and, only if it is not, then add some code in there to do a bit of analysis to emit a reasonably accurate error message (at least something in the problem ballpark.)
One should also regard that it is often not as simple as checking an "if" before an "else", because that is more complicated due to possible nesting, and separation between scanner and actual parser.No doubt there are a fair number of syntactic errors that can put the compiler in a bind because, as a result of the syntactic error, the statement is ambiguous and the compiler can only state what the valid possibilities are instead of emitting a message that unambiguously solves the problem.
Ok, I got the one and only answer. And it is not 42. It is "&".There is a lot of fun to be had with the "&". :)
The error message should clearly suggest: & expected