Lazarus

Free Pascal => General => Topic started by: 440bx on July 05, 2020, 03:51:52 am

Title: About compiler error messages...
Post by: 440bx on July 05, 2020, 03:51:52 am
Hello,

Simple question: are the FPC developers interested in correcting error messages that dangerously border on being incorrect ?

For instance, consider this program:
Code: Pascal  [Select][+][-]
  1. program TestErrorMessage;
  2.  
  3. begin
  4.   while 1 > 2    do        else
  5. end.
  6.  

FPC emits the following error:
Code: Text  [Select][+][-]
  1. Compiling junk.lpr
  2. junk.lpr(4,28) Warning: unreachable code
  3. junk.lpr(4,28) Fatal: Syntax error, ";" expected but "ELSE" found
  4. Fatal: Compilation aborted
which is not right since placing a semicolon between the "do" and the "else" does not yield a syntactically valid statement.

The correct error message should state that the expected keyword in that first case is "end", not semicolon ";" as Delphi does:
Code: Text  [Select][+][-]
  1. Delphi for Win32  Version 9.0  Copyright (c) 1983,96 Borland International
  2. junk.lpr(4) Hint: FOR or WHILE loop executes zero times - deleted
  3. junk.lpr(4) Error: 'END' expected but 'ELSE' found
  4. 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.)

Obviously, a very minor thing but, it would be nice to see correct error messages whenever possible.



Title: Re: About compiler error messages...
Post by: ccrause on July 05, 2020, 11:00:21 am
IMHO it is a matter of interpretation.  My interpretation is that Delphi's suggestion does not make sense.  Trying to follow Delphi's suggestion to fix the code:
Code: Pascal  [Select][+][-]
  1. program TestErrorMessage;
  2.  begin
  3.   while 1 > 2    do        end
  4. end.
This is not valid code either. So my interpretation of Delphi's suggestion is different from your interpretation which (I assume) is that the else is superfluous.

Where I do agree is that FPC's message is not that helpful either:
Code: Pascal  [Select][+][-]
  1. program TestErrorMessage;
  2.  begin
  3.   while 1 > 2    do        ; else
  4. end.
This still gives the error
Quote
project1.lpr(4,20) Fatal: Syntax error, ";" expected but "ELSE" found

My view of the original situation is that the parser is expecting a statement after do , but encounters a reserved word.  It seems that the presence of else outside a valid construct is resulting in this kind of error message in FPC. Following this line of thinking leads me to suggestion the following error message: "Statement expected but reserved word "ELSE" encountered".  So if one substitutes "empty statement" for ";" then FPC's error message makes sense (at least according to my interpretation).  But refering to ";" as substitute for "statement" is not generally valid since ";" is a statement separator in Pascal.
Title: Re: About compiler error messages...
Post by: Thaddy on July 05, 2020, 11:12:40 am
In my opinion FPC is more clear than Delphi. And correct.
The else is dangling and the while do needs a terminating ;
Where did Delphi get that end from? that is really wrong.
Title: Re: About compiler error messages...
Post by: marcov on July 05, 2020, 12:03:44 pm


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.)

Both seem to indicate that the ELSE is out of place, IMHO they are equivalent, just focussing on a different expected production.

After a do, possible productions are (begin..end block) or  (statement)

Statements are separated by ; but can be empty, so

Code: [Select]
  procedure yy;
  begin
    while true>false do 
  end;

is correct but

Code: [Select]
  procedure yy;
  begin
    while true>false do  ;
   
  end;

is also correct.

So if you are pedantic, the error message should be  "begin",";" or "end" expected. If it is a main block, you could change the "end" to "end." even.

But I really wonder what that would change other that increased frustration among compiler message translators that have to translate all those extra messages.

added later: hmm, other keywords like REPEAT, FOR and WHILE are also possible, so to be complete that would be a real long list.

I agree somewhat Thaddy in that it is IMHO more logical that statements are expected to follow than that the end of the procedure is expected. So I would prefer FPC's choice over Delphi's.
Title: Re: About compiler error messages...
Post by: 440bx on July 05, 2020, 02:02:26 pm
The compiler cannot state that it expects a semicolon when it is sitting on an "else" keyword because the semicolon is a statement separator and "else" is not a statement and the compiler knows that.  Therefore, semicolon is out, no can be.

The other possibility is "else" but, it can't be "else" (it's already there and the compiler knows it's wrong) because the "while" statement isn't in an "if" statement and, the compiler knows that too.  Therefore, it cannot be "else".

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.

Following Delphi's error message instructions yields a correct program.  Following FPC's error message instructions does _not_ lead to a correct program.

For fun, here is a little bit of code to play with:(NOTE: other than commenting and uncommenting the $DEFINE lines, _no_ other editing is required because the compiler should ignore the text after "end."
Code: Pascal  [Select][+][-]
  1. {$APPTYPE CONSOLE}
  2.  
  3.  
  4. { uncomment these defines below to perform each test  }
  5.  
  6. //{$DEFINE TEST_A}
  7. //{$DEFINE TEST_B}
  8. //{$DEFINE TEST_C}
  9.  
  10. {$IFDEF TEST_A}
  11. program TestWhileFOLLOW;
  12.  
  13. begin
  14.   while 1 > 2    do        else
  15. end.
  16.  
  17. output messages:
  18.  
  19. a. From Delphi
  20.  
  21. Delphi for Win32  Version 9.0  Copyright (c) 1983,96 Borland International
  22. TestWhileFOLLOW.lpr(11) Hint: FOR or WHILE loop executes zero times - deleted
  23. TestWhileFOLLOW.lpr(11) Error: 'END' expected but 'ELSE' found
  24. TestWhileFOLLOW.lpr(14)
  25.  
  26. b. From FPC
  27.  
  28.    this error message does _not_ lead to a syntactically correct program
  29.  
  30. Free Pascal Compiler version 3.0.4 [2017/10/06] for x86_64
  31. Copyright (c) 1993-2017 by Florian Klaempfl and others
  32. Target OS: Win64 for x64
  33. Compiling TestWhileFOLLOW.lpr
  34. TestWhileFOLLOW.lpr(11,28) Warning: unreachable code
  35. TestWhileFOLLOW.lpr(11,28) Fatal: Syntax error, ";" expected but "ELSE" found
  36. Fatal: Compilation aborted
  37. {$ENDIF}
  38.  
  39.  
  40. { add "end" as suggested by Delphi }
  41.  
  42.  
  43. {$IFDEF TEST_B}
  44. program TestWhileFOLLOW;
  45.  
  46. begin
  47.   while 1 > 2    do        end     else
  48. end.
  49.  
  50. output messages:
  51.  
  52. a. From Delphi
  53.  
  54. Delphi for Win32  Version 9.0  Copyright (c) 1983,96 Borland International
  55. TestWhileFOLLOW.lpr(41) Hint: FOR or WHILE loop executes zero times - deleted
  56. TestWhileFOLLOW.lpr(41) Error: '.' expected but 'ELSE' found
  57. TestWhileFOLLOW.lpr(49)
  58.  
  59. b. From FPC
  60.  
  61.    it gets this one right
  62.  
  63. Free Pascal Compiler version 3.0.4 [2017/10/06] for x86_64
  64. Copyright (c) 1993-2017 by Florian Klaempfl and others
  65. Target OS: Win64 for x64
  66. Compiling TestWhileFOLLOW.lpr
  67. TestWhileFOLLOW.lpr(41,28) Warning: unreachable code
  68. TestWhileFOLLOW.lpr(41,36) Fatal: Syntax error, "." expected but "ELSE" found
  69. Fatal: Compilation aborted
  70. {$ENDIF}
  71.  
  72.  
  73. {$IFDEF TEST_C}
  74. program TestWhileFOLLOW;
  75.  
  76. begin
  77.   while 1 > 2    do        end.     else
  78. end.
  79.  
  80. output messages:
  81.  
  82. a. From Delphi
  83.  
  84. Delphi for Win32  Version 9.0  Copyright (c) 1983,96 Borland International
  85. TestWhileFOLLOW.lpr(77) Hint: FOR or WHILE loop executes zero times - deleted
  86. TestWhileFOLLOW.lpr(77) Warning: Text after final 'END.' - ignored by compiler
  87. TestWhileFOLLOW.lpr(108)
  88. 109 lines, 0.02 seconds, 2992 bytes code, 1224 bytes data.
  89.  
  90. b. From FPC
  91.  
  92.    sort of gets it right and only because of the error message instruction from
  93.    Delphi were followed otherwise it would not lead to a correct program.
  94.  
  95.    Another interesting thing: it created an executable but because it is unhappy
  96.    about not finding the $ENDIF, it did not output the number of lines compiled,
  97.    time spent and the size of the code and data.
  98.  
  99. Free Pascal Compiler version 3.0.4 [2017/10/06] for x86_64
  100. Copyright (c) 1993-2017 by Florian Klaempfl and others
  101. Target OS: Win64 for x64
  102. Compiling TestWhileFOLLOW.lpr
  103. TestWhileFOLLOW.lpr(77,28) Warning: unreachable code
  104. Linking TestWhileFOLLOW.exe
  105. TestWhileFOLLOW.lpr(77,28) Error: $ENDIF expected for $IFDEF TEST_C defined in TestWhileFOLLOW.lpr line 73
  106.  
  107. vvvvvvvv $ENDIF is right there!
  108. {$ENDIF}
  109.  

Title: Re: About compiler error messages...
Post by: Martin_fr on July 05, 2020, 03:20:19 pm
Both "end" and ";" would fix the "while".

Both leave an error after it:
You say that there can not be a ";", because after the ";" there must be a statement (and "else" is not).

But after an "end" there must be valid code too. And "else" is not valid there either.
(or after "end.", there must be no code, and "else" is not)

So expecting "end" leads to all the same issues.
And statistically a ";" is more likely.


Also
   "while foo do else"
seems to be as
   "while foo do  <empty statement> [error after statement] else".
If there was no empty statement, then a statement would need to be expected.

So *if* the error message needs any change, then one could argue it should say "statement expected" (changing the compiler to assume there was no empty statement).
Or it could ask for: "statement, end or ; expected".
Title: Re: About compiler error messages...
Post by: ccrause on July 05, 2020, 03:25:07 pm
...
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.
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.

Looking at the parser logic the following high level processing happens:
1. after the DO token, parse a statement block.
2. if no statement is found, it is per definition empty (OK, this bit is my interpretation to digest the parser logic).
3. an empty statement should be followed either by the end of a statement block (end; or end. or finalization), if not, more statements are expected, in which case a statement separator is expected.

So the compiler's error message makes sense in the context of the parser.  So either the compilers reports the final failure it encounters (which then depends on the order of the various checks) or a more sophisticated error needs to be generated at a higher level in the parser to indicate all the possible causes of an error.
Title: Re: About compiler error messages...
Post by: 440bx on July 05, 2020, 03:34:36 pm
Everything you say is reasonable... but...

Both "end" and ";" would fix the "while".
the semicolon is incorrect.  I will explain, in detail why, below.

Both leave an error after it:
You say that there can not be a ";", because after the ";" there must be a statement (and "else" is not).
true but, putting a semicolon will _not_ lead to a correct program.  Putting "end" will.  That's important.

The reason why "end" is the only correct symbol is because, the compiler is parsing a compound statement, i.e, "begin"/"end".  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".

Therefore, "else" not being a keyword that starts a new statement, the only valid keyword at that location is the one that completes the compound statement which is, "end".

The production for a compound statement is: _CompoundStatement      = "begin" _Statement { ";" _Statement } "end" therefore, in the absence of another statement, that production should be requesting an "end".



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.

HTH.


Title: Re: About compiler error messages...
Post by: Martin_fr on July 05, 2020, 04:10:19 pm
Quote
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.

But how do we get
- 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".



Following your argument, that the compiler should treat an unexpected keyword as a special error, then it should simply state
"incorrect keyword"

In the same way as
Code: Pascal  [Select][+][-]
  1.   while true do 'abc'
gives: "Error: Illegal expression"

and
Code: Pascal  [Select][+][-]
  1.   while true do XX
gives: "Error: Identifier not found"

Btw, many other keywords give "illegal expression".
And that would be fine for the "else" too.

Yet, point in your favour:
Code: Pascal  [Select][+][-]
  1. repeat
  2.   while true do else
  3.  
gives: Fatal: Syntax error, "UNTIL" expected but "ELSE" found
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)



Of course, one has to ask why change the error at all.
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:
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.

As for the second, "; expected" or "end expected" are both equally helpful.
Given that ";" is statistically more likely, the "; expected" error is actually ever so slightly more helpful.




Title: Re: About compiler error messages...
Post by: marcov on July 05, 2020, 04:34:05 pm
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.

Yes. And in neither case it was meant to simply substitute. It is basically a summary of the state of the parser, not a correction advise. 

Example: Delphi gives the exact same error for this code:

Code: [Select]
  procedure yy;
  begin
    while true>false do  else

  end;

And here substuting ELSE with  "end" is not a solution, IOW the Delphi message is not meant as a "insert this" solution either. As said before, the substitute for else is more likely to be something else then END than that it is END, so I think the Delphi solution is inferior.
Title: Re: About compiler error messages...
Post by: 440bx on July 05, 2020, 05:04:07 pm
But how do we get
- From: The compiler found an incorrect keyword
- To: Therefore it must expect a keyword (just a different keyword)?
I 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". 

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.

FPC stating that it expected a semicolon, in addition to being incorrect, it is also utterly useless because semicolons separate empty statements.  The compiler could ask for 200 semicolons there and achieve just as much.  It's asking for a semicolon is the same (in that case) as asking for a space characters.  Utterly useless.

Following your argument, that the compiler should treat an unexpected keyword as a special error, then it should simply state
"incorrect keyword"
It'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".


Yet, point in your favour:
Code: Pascal  [Select][+][-]
  1. repeat
  2.   while true do else
  3.  
gives: Fatal: Syntax error, "UNTIL" expected but "ELSE" found
So it uses the knowledge about the outer block.
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.

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.
Purely technically it is correct. (It is not complete, but it is one correct possibility, and neither would "end expected" be complete).
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.

The reasons to change an error message are:
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.
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.


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.

Attempting to use FPC's "ascii visual entertainment" yields a request for more and more semicolons and never a program that compiles successfully.

That applies to the example you showed.  I used your example.  Followed Delphi's "suggestions" and after a few compiles had a syntactically correct program.  If I were still following FPC's suggestion (not advice!) this entire post would be semicolons and the program would still not compile (and not ever compile.)

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.

Anyway, I just wanted to know if there was interest in having correct error message.  I have the answer and, have no doubt about what it is.


Title: Re: About compiler error messages...
Post by: marcov on July 05, 2020, 05:25:50 pm
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.

Nope. There is no way to place END in that source code to make it compile. That it happens to be for your original code is coincidence. Again: fix this by adding end or replacing else by end;

Code: Pascal  [Select][+][-]
  1. procedure yy;
  2.   begin
  3.     while true>false do  else
  4.   end;
  5.  

In case the end isn't far enough, and you get confused again, use this code:

Code: Pascal  [Select][+][-]
  1. procedure yy;
  2.   begin
  3.     while true>false do  else
  4.     flup;
  5.   end;
  6.  

to make sure you don't accidentally reach the end of the procedure again.
Title: Re: About compiler error messages...
Post by: 440bx on July 05, 2020, 05:50:57 pm
if you follow the instructions given by the compiler (Delphi), you end up with this (which compiles!) :
Code: Pascal  [Select][+][-]
  1. program TestWhileFOLLOW2;
  2.  
  3. procedure yy;
  4. begin
  5.   while true > false do  end;
  6.   //flup;
  7. end.
  8.  
  9. begin
  10. end.
  11.  
I did have to add a "program" clause.  I think you should be ok with that.
Title: Re: About compiler error messages...
Post by: marcov on July 05, 2020, 06:21:35 pm
if you follow the instructions given by the compiler (Delphi), you end up with this (which compiles!) :
Code: Pascal  [Select][+][-]
  1. program TestWhileFOLLOW2;
  2.  
  3. procedure yy;
  4. begin
  5.   while true > false do  end;
  6.   //flup;
  7. end.
  8.  

Suddenly, that ; has become a ".".  So you just wrangled things till it compile, (and falsely, potentially omitting umpteen functions defined after this one). And way  more than what Delphi says. With a ";", it doesn't compile if you replace else by "end;"

And yes, of course i had a begin..end. further down, that was just left out for clarity.
Title: Re: About compiler error messages...
Post by: Martin_fr on July 05, 2020, 08:05:38 pm
But how do we get
- From: The compiler found an incorrect keyword
- To: Therefore it must expect a keyword (just a different keyword)?
I 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". 

Ignoring the rest of your reply. Makes no sense to talk about any other point, as long as you completely missed the point on this.

You say it yourself: "I didn't say it  must expect a keyword."

As for: "if it finds a keyword that does not start a new statement, "...." then the keyword must be "end""
The entire point is, why must it be replaced/insertatian by a keyword?????
It does (and you said so) not have to expect one in first.
It finds an error (that happens to be a keyword, but that might well be a misspelled function name "Esel" (German word)).

The random fact that the token causing an error happens to be a keyword, does not in any way implicate that the correct token (the token to be expected) actually has to be a keyword.
So the expected token can very well be a ";".

Title: Re: About compiler error messages...
Post by: Warfley on July 05, 2020, 09:03:26 pm
Delphis error message is completely wrong, there is no case in which While ... do end would be correct. 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. Thats why the error message is actually wrong here, because before an else there should not be a semicolon:
Code: Pascal  [Select][+][-]
  1. if ... then
  2.   while ... do
  3.     foo
  4. else
  5.   ...

But the thing here is, that the real error is something totally different, that it is a dangling else. Because the following syntax is (even though fucked up) allowed:
Code: Pascal  [Select][+][-]
  1. if ... then
  2.   while ... do
  3. else
  4.   ...
As this would be the same as
Code: Pascal  [Select][+][-]
  1. if ... then
  2.   while ... do begin end
  3. else
  4.   ...
i.e. having an empty statement in the while loop.

So the real error here should be something like "else without any if block found"

Edit: I must correct myself, I forgott that there is a case where there needs to be a semicolon before else, this is the case in a case statement:
Code: Pascal  [Select][+][-]
  1. case ... of
  2. ...:
  3.   while ... do ;
  4. else
  5.   ...
  6. end.
Honestly the "no semicolon before an else statement" rule is pretty stupid, its a special syntax that applys only in a single use case, and not even in the other case where else is used... The world would be a better place if this rule would not exist (just my oppinion because I always get this wrong in case ... of statements)
Title: Re: About compiler error messages...
Post by: PascalDragon on July 05, 2020, 09:27:58 pm
Obviously, a very minor thing but, it would be nice to see correct error messages whenever possible.

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 beginend block). Thus it ignores any else, until or end which will then be reacted to at the outside when trying to read the statement separator for the while loop (where the only valid possibilities are ;, end or finalization (the later for initialization sections)). As a catch all and error recovery (so that the parser can hopefully continue to provide further errors) it's simply a ; that is forcefully parsed if something else (in this case the else) is found. Delphi simply chose end here as recovery as the following would be valid:

Code: Pascal  [Select][+][-]
  1. program TestErrorMessage;
  2.  
  3. begin
  4.   while 1 > 2    do
  5. end.

So no, there is nothing that can be improved for this without sacrificing other error locations.

Delphis error message is completely wrong, there is no case in which While ... do end would be correct.

Delphi's error message is just as valid, as it's allowed for the statement of the whiledo statement to be empty, thus due to Pascal using statement separators the end of the surrounding block may follow directly. It's in most cases not in any way useful, but it's syntactially correct.

So the real error here should be something like "else without any if block found"

As said above the parser does not know about this.

Edit:

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.
Title: Re: About compiler error messages...
Post by: Warfley on July 05, 2020, 09:40:16 pm
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

Quote
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?
Title: Re: About compiler error messages...
Post by: 440bx on July 05, 2020, 11:31:00 pm
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":
Code: Pascal  [Select][+][-]
  1. program TestErrorMessage;
  2.  
  3. begin
  4.   while 1 > 2    do
  5. end.
That might be why Borland replaced the name "Pascal" with Delphi.   Since Free Pascal compiles that and, according to you "there is no case in which While ... do end would be correct.", maybe it should be called Free "Fred" (abbreviated F2... sounds like a fighter jet.)



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 beginend 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.

Since, the "while" production is done and there is no "if", control returns to the compound statement production and that one know that "else" isn't a statement therefore no separating semicolon is valid.  Therefore, the only correct symbol, that does not start another statement, in that location is "end".

Anyway, I have the answer to my question... this is the first time and, the last one, I bring up anything about the correctness (or lack thereof) of error messages.

In any case, thank you for the explanation, I do appreciate it.



Title: Re: About compiler error messages...
Post by: Martin_fr on July 06, 2020, 02:29:11 am
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.

- The fact that the program compiles (in particular cases) is not saying anything. The error is fixed when the program does what its indented to do. Putting in an end is not fixing this.
- Also again. REPLACING the "else" by a ";" does compile.
- And, in your example it was not the "end" but the "." thereafter that made it compile....

If you role a dice often enough you get the desired number. That does not mean you can get it at will.

But you ignored the main point.
"else" is a type for "esel", the programmer never wanted to type a keyword.



Title: Re: About compiler error messages...
Post by: PascalDragon on July 06, 2020, 09:25:11 am
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

Correct. That will never change. Just like no semicolon in front of an else will never change.

Quote
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?

Yes, it's an implementation detail, but that's simply how FPC's recursive descent parser is written. That's also not likely to change, especially as we have more important problems than apparently inaccurate error messages.

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 beginend 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.

No, it does not know that. At least not in the sense that it's useful for better error messages. The function that parses an if-statement knows that it's inside an if-statement, but the recursively called parser functions don't know anything about that (because they don't need to for correct function!).
Title: Re: About compiler error messages...
Post by: 440bx on July 06, 2020, 04:54:18 pm
I was going to leave this alone but, I couldn't resist... sorry!

... apparently inaccurate error messages.
Apparently ?...

try this one:
Code: Pascal  [Select][+][-]
  1. {$APPTYPE CONSOLE}
  2.  
  3. program TestMissingIdentifierExpression;
  4. var
  5.   IntegerV : integer;
  6. begin
  7.   IntegerV :=              div 3;
  8. end.
  9.  
which produces the following error message:
Quote
Free Pascal Compiler version 3.0.4 [2017/10/06] for x86_64
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
FPC 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)

I agree with you, "apparently" FPC does emit the "occasional" inaccurate error message (it usually includes a request for a semicolon... I'm stocking up on those :))

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.
Title: Re: About compiler error messages...
Post by: PascalDragon on July 07, 2020, 09:41:21 am
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".
Title: Re: About compiler error messages...
Post by: 440bx on July 07, 2020, 11:06:32 am
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.) 

There are a number of places in FPC where the compiler seems to simply ask for a semicolon even if it doesn't make any sense to put a semicolon there.  The expression parser seems rather prone to that behavior.  Here is an example:
Code: Pascal  [Select][+][-]
  1. begin
  2.   IntegerA :=    := 1;
  3. end.
  4.  
replacing the numeral 1 with a semicolon doesn't help and neither does putting a semicolon between the ":=" and the numeral.  IOW, the problem in that statement isn't going to be solved with semicolons.

If the compiler stated that, after the first ":=" an identifier (or one of the unary operators) was expected, it wouldn't solve the entire problem but, it would be a step in the right direction.  After adding an identifier there (by the programmer of course), it could state that assigning within an expression is not allowed.


Title: Re: About compiler error messages...
Post by: marcov on July 07, 2020, 11:25:04 am
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.
Title: Re: About compiler error messages...
Post by: 440bx on July 07, 2020, 11:33:34 am
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.

What I am trying to point out is that, at least in some cases, what the compiler offers (often when it states that it expected a semicolon), is not even applicable to the solution.
Title: Re: About compiler error messages...
Post by: Martin_fr on July 11, 2020, 01:10:13 pm
Bit of fun:

Ok, I got the one and only answer. And it is not 42. It is "&".
The error message should clearly suggest: & expected

For the below will compile, if an ampersand is inserted.
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. {$mode objfpc}{$H+}
  3.  
  4. procedure &else;
  5. begin
  6. end;
  7.  
  8. begin
  9.   while true do else;
  10. end.
  11.  
Title: Re: About compiler error messages...
Post by: 440bx on July 11, 2020, 02:40:00 pm
Ok, I got the one and only answer. And it is not 42. It is "&".
The error message should clearly suggest: & expected
There is a lot of fun to be had with the "&". :)
TinyPortal © 2005-2018