Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2023-12

case statement

25 messages · 11 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Adriaan van Os

I am looking in detail at the syntax diagrams in the Freepascal Language Reference (version 3.2.0)

Section 13.2.2 discusses the case-statement. Translated to EBNF (WSN) the syntax is

case-statement = "CASE" expression "OF" case { ";" case } [ else-part ] [ ";" ] . case = constant [ ".." constant ] { "," constant [ ".." constant ] } ":" statement . else-part = [ "ELSE" | "OTHERWISE" ] statementlist .

If this is correct (and the compiler really allows it) then a semicolon between <case> and <else-part> is not required. Consequently, there is an ambiguity between an if-then-else statement (as last statement of the <case>) and an if-then statement (as last statement of the <case>) and an <else-part>. This is extremely dangerous and I feel that at least the Language Reference should warn against it.

Even with an obliged semicolon, I always use "OTHERWISE instead of ELSE, but that's my personal preference.

By the way, the Language Reference doesn't specify what a <statementlist> is.

Regards,

Adriaan van Os

Michael Van Canneyt
to Adriaan van Os: I am looking in detail at the syntax diagrams in the Freepascal Language Reference…
Adriaan van Os wrote 15 lines
I am looking in detail at the syntax diagrams in the Freepascal Language Reference (version 3.2.0) Section 13.2.2 discusses the case-statement. Translated to EBNF (WSN) the syntax is case-statement = "CASE" expression "OF" case { ";" case } [ else-part ] [ ";" ] . case = constant [ ".." constant ] { "," constant [ ".." constant ] } ":" statement . else-part = [ "ELSE" | "OTHERWISE" ] statementlist . If this is correct (and the compiler really allows it) then a semicolon between <case> and <else-part> is not required.

It is not required.

Show quoted text 5 lines
Consequently, there is an ambiguity between an if-then-else statement (as last statement of the <case>) and an if-then statement (as last statement of the <case>) and an <else-part>. This is extremely dangerous and I feel that at least the Language Reference should warn against it.

A good point. I will add a warning.

Even with an obliged semicolon, I always use "OTHERWISE instead of ELSE, but that's my personal preference.

Indeed. By contrast I abhorr the OTHERWISE. Tastes differ.

Thanks for bringing the ambiguity to my attention.

Michael.

Adriaan van Os
to Michael Van Canneyt
Michael Van Canneyt wrote 21 lines
On Thu, 14 Dec 2023, Adriaan van Os via fpc-pascal wrote: > > I am looking in detail at the syntax diagrams in the Freepascal > Language Reference (version 3.2.0) > > Section 13.2.2 discusses the case-statement. Translated to EBNF (WSN) > the syntax is > > case-statement = "CASE" expression "OF" case { ";" case } [ else-part > ] [ ";" ] . > case = constant [ ".." constant ] { "," constant [ ".." constant ] } > ":" statement . > else-part = [ "ELSE" | "OTHERWISE" ] statementlist . > > If this is correct (and the compiler really allows it) then a > semicolon between <case> and <else-part> is not required. It is not required.

In addition to what I wrote, I believe the <case-statement> diagram is also incorrect in that it doesn't allow an optional semicolon between <case> and <else-part>.

Regards,

Adriaan van Os

Adriaan van Os
to James Richters
James Richters wrote
I didn’t know there was such a thing as OTHERWISE. Is there any functional difference between OTHERWISE and ELSE?

No. It is just that OTHERWISE doesn't have the IF-THEN-ELSE ambiguity. Macintosh Pascal compilers had OTHERWISE but not ELSE. Maybe, OTHERWISE was added to FPC when imlementing the macpas mode.

Regards,

Adriaan van Os

Sven Barth
to James Richters: I didn’t know there was such a thing as OTHERWISE. Is there any functional difference…

James Richters via fpc-pascal schrieb am
Do., 14. Dez. 2023, 20:13:

I didn’t know there was such a thing as OTHERWISE. Is there any functional difference between OTHERWISE and ELSE?

"otherwise" is what had been defined by ISO Extended Pascal for the cause-statement.

Aside from not having the else-problem mentioned in this thread there is no functional difference.

Regards,
Sven

James Richters
to Martin Wynne

I have occasionally had ambiguity with ELSE, for example when you have IF statements nested inside other IF statements,
sometimes the ELSE is seen as part of the inner, not the outer, or vice versa, depending on where the one-liners are
but I just resolve it with some BEGIN - END Blocks, even if they are not actually needed because there is only one line, ambiguity resolved.

For years I have just been in the habit of always putting BEGIN and END on all IF and ELSE statements, as well as all entries of CASE statements, whether needed or not, just because it's so much easier to stick in some temporary diagnostic code if needed, it's easier to just always have them and not have to add them later if you want to do a second thing, which always seems to be happening. I guess that's why I never noticed there could be an issue with CASE statements.

It is handy to know about OTHERWISE though, I'll probably throw it in just to help remind me that this belongs to the CASE
Statement, and not part of some IF, maybe it will be more readable that way.

James

Earlier message 12 lines
-----Original Message----- From: fpc-pascal On Behalf Of Martin Wynne via fpc-pascal Sent: Thursday, December 14, 2023 3:16 PM To: Cc: Martin Wynne Subject: Re: [fpc-pascal] case statement I've been using ELSE in IF statements and in CASE statements for 25 years without realising there was a problem. What a dim-wit I have been. Martin.
Adriaan van Os
to James Richters

Note that the same ambiguity exists in the <exception-handler> syntax (and this is less well known)

exceptionhandlers = [ exception-handler { ";" exception-handler } [ "ELSE" statement-list ] | statement-list ] .
exception-handler = "ON" [ identifier ":" ] class-type-identifier "DO" statement .

as <exception-handler> ends with a <statement> and the optional <"ELSE" statement-list> part start with "ELSE". Sloppy language design, I assume by Borland.

Regards,

Adriaan van Os

Michael Van Canneyt
to Adriaan van Os
Adriaan van Os wrote 11 lines
Note that the same ambiguity exists in the <exception-handler> syntax (and this is less well known) exceptionhandlers = [ exception-handler { ";" exception-handler } [ "ELSE" statement-list ] | statement-list ] . exception-handler = "ON" [ identifier ":" ] class-type-identifier "DO" statement . as <exception-handler> ends with a <statement> and the optional <"ELSE" statement-list> part start with "ELSE". Sloppy language design, I assume by Borland.

What exactly do you consider "sloppy" ?

The fact that the semicolon before the else is optional ?

Michael.

Adriaan van Os
to Michael Van Canneyt
Michael Van Canneyt wrote 17 lines
On Fri, 15 Dec 2023, Adriaan van Os via fpc-pascal wrote: > Note that the same ambiguity exists in the <exception-handler> syntax > (and this is less well known) > > exceptionhandlers = [ exception-handler { ";" exception-handler } [ > "ELSE" statement-list ] | statement-list ] . > exception-handler = "ON" [ identifier ":" ] class-type-identifier "DO" > statement . > > as <exception-handler> ends with a <statement> and the optional > <"ELSE" statement-list> part start with "ELSE". Sloppy language > design, I assume by Borland. What exactly do you consider "sloppy" ?

The ambiguity in the syntax whether ELSE belong to <statement> or to <"ELSE" statement-list>.

The fact that the semicolon before the else is optional ?

I don't see a semicolon in the formal syntax.

Regards,

Adriaan van Os

Michael Van Canneyt
to Adriaan van Os
Adriaan van Os wrote 21 lines
Michael Van Canneyt via fpc-pascal wrote: > > > On Fri, 15 Dec 2023, Adriaan van Os via fpc-pascal wrote: > >> Note that the same ambiguity exists in the <exception-handler> syntax (and >> this is less well known) >> >> exceptionhandlers = [ exception-handler { ";" exception-handler } [ >> "ELSE" statement-list ] | statement-list ] . >> exception-handler = "ON" [ identifier ":" ] class-type-identifier "DO" >> statement . >> >> as <exception-handler> ends with a <statement> and the optional <"ELSE" >> statement-list> part start with "ELSE". Sloppy language design, I assume >> by Borland. > > What exactly do you consider "sloppy" ? The ambiguity in the syntax whether ELSE belong to <statement> or to <"ELSE" statement-list>.

Why do you think this is ambiguous ? It always belongs to statement list.

If there is ambiguity, it is in the if then else construct. This makes it difficult to read for humans.

> The fact that the semicolon before the else is optional ? I don't see a semicolon in the formal syntax.

This works:

---
{$mode objfpc}
uses sysutils;
begin
   try
   except
     on E: EAccessViolation do
       begin
       end;
     on E: EInoutError do
       begin
       end; // can be removed or not.
     else
       begin
       Writeln('OK');
       end;
   end;
end.
---

Michael.

Adriaan van Os
to Michael Van Canneyt: Why do you think this is ambiguous ? It always belongs to statement list. If there is…
Michael Van Canneyt wrote 5 lines
>> The fact that the semicolon before the else is optional ? > > I don't see a semicolon in the formal syntax. This works:

OK, than an optional semicolon must be added to the <exceptionhandlers> rule

exceptionhandlers = [ exception-handler { ";" exception-handler } [ ";" ] [ "ELSE" statement-list ] | statement-list ] .

Regards,

Adriaan van Os

Michael Van Canneyt
to Adriaan van Os: OK, than an optional semicolon must be added to the <exceptionhandlers> rule…
Adriaan van Os wrote 12 lines
Michael Van Canneyt via fpc-pascal wrote: >>> The fact that the semicolon before the else is optional ? >> >> I don't see a semicolon in the formal syntax. > > This works: OK, than an optional semicolon must be added to the <exceptionhandlers> rule exceptionhandlers = [ exception-handler { ";" exception-handler } [ ";" ] [ "ELSE" statement-list ] | statement-list ] .

Well, you can have ;;;;; as well.

It means exception-handler can be empty in your repeat:

{ ';' [exception-handler] }

Or the whole ; is simply sloppyness on the part of the compiler.

Michael.

Gerhard Scholz
to Adriaan van Os: I am looking in detail at the syntax diagrams in the Freepascal Language Reference…

statement list = statement { ";" statement }

statementlist itself is not explained; I assume "statementlist" to be the same as "statement list"

It is included in the definition of the try...except statement.

ELSE/OTHERWISE

I assume that came historically; the first implementation of a PASCAL compiler I have seen had no else or otherwise in the case startement. Some ater dialects introduced ELSE, other dialect(s) used OTHERWISE, FPC then allowed both.

Ambiguity:

It is so. I was a bit astonished.

   i := 4 ;
   case i of
     1,
     2: if odd ( i )
          then write ( 'odd' )
         else write ( 'even' ) ;
    end ;

produces nothing, else is part of the if statement, in case of ambiguity the nearest possibility is used.

   i := 4 ;
   case i of
     1,
     2: if odd ( i )
          then write ( 'odd' )
    ;     else write ( 'even' ) ;
    end ;

produces the print 'even', else is part of the case statement

As I read the syntax of the case statement in ref.pdf, the semicolon before the else is not even allowed.

the syntax is (see below)

case-statement = "CASE" expression "OF" case { ";" case } [ else-part ] [ ";" ] .

if you change that to

case-statement = "CASE" expression "OF" case { ";" case } [ ";" ] [ else-part [ ";" ] ] .

then you have what the compiler does.

I never had the problem because before the else I always inserted a ";"

Earlier message 42 lines
----- Original Message ----- From: "Adriaan van Os via fpc-pascal" To: "FPC-Pascal users discussions" Cc: "Adriaan van Os" Sent: Thursday, December 14, 2023 4:53 PM Subject: [fpc-pascal] case statement > > I am looking in detail at the syntax diagrams in the Freepascal Language > Reference (version 3.2.0) > > Section 13.2.2 discusses the case-statement. Translated to EBNF (WSN) the > syntax is > > case-statement = "CASE" expression "OF" case { ";" case } [ else-part ] > [ ";" ] . > case = constant [ ".." constant ] { "," constant [ ".." constant ] } ":" > statement . > else-part = [ "ELSE" | "OTHERWISE" ] statementlist . > > If this is correct (and the compiler really allows it) then a semicolon > between <case> and <else-part> is not required. Consequently, there is an > ambiguity between an if-then-else statement (as last statement of the > <case>) and an if-then statement (as last statement of the <case>) and an > <else-part>. This is extremely dangerous and I feel that at least the > Language Reference should warn against it. > > Even with an obliged semicolon, I always use "OTHERWISE instead of ELSE, > but that's my personal preference. > > By the way, the Language Reference doesn't specify what a <statementlist> > is. > > Regards, > > Adriaan van Os > > _______________________________________________ > fpc-pascal maillist - > https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Tony Whyman
to Gerhard Scholz
Gerhard Scholz wrote 7 lines
ELSE/OTHERWISE I assume that came historically; the first implementation of a PASCAL compiler I have seen had no else or otherwise in the case startement. Some ater dialects introduced ELSE, other dialect(s) used OTHERWISE, FPC then allowed both.

The historical context has interested me as well.

Going back to the original "Pascal User Manual and Report" (Jensen and Wirth 1978), there is no Else/Otherwise clause for a case statement. The syntax is given as (in the original BNF):

<case statement> ::= case <expression> of
   <case list element> |;<case list element>] end
<case list element> ::= <case label list> : <statement> | <empty>
<case label list> ::= <case label> | [ , <case label> ]

Note that the semi-colon is used here in its traditional Algol role as a statement separator and not the 'C' usage as a statement terminator.

Back in the early eighties, I worked at ICL and we made extensive use of the Prospero Pascal compiler building embedded systems based on the Z80 microprocessor. I still have a 1988 edition of the language specification, and this uses EBNF to define the case statement as:

case-statement = "CASE" case-index "OF"
  case-list-element {";" case-list-element }
   [ ";" OTHERWISE statement][";"] "END"

case-index = expression
case-list-element = case-range-list ":" statement
case-range-list = case-range {"," case-range }
case-range = case-constant [".." case-constant ]
case-constant = constant

What is interesting about the above is not just that it uses "otherwise" but that it insists on a semi-colon before the "otherwise". This may not have been strictly necessary but it does enforce the separation between the case -list-elements and the "otherwise", making the "otherwise" clause into another case-list-element. It also aids readability and it may be why I have always added a semi-colon after the final case-list-element. Note that the final optional ";" is probably needed to allow those that always like to end a statement in a semi-colon.

Prospero Pascal was close to ISO Pascal (although I have lost my original copy of ISO Pascal) and I would guess that the above is copied from ISO Pascal.

The change from "otherwise" to "else" is probably a Borland Pascal invention preferring a shorter word and then overlooking the importance of the semi-colon case-list-element separator and the resulting ambiguity. The same error then flowed through to exception handling.

As an aside, I much prefer OTHERWISE to ELSE given that it is much closer to natural language. The IF...THEN..ELSE construct probably dates back to Algol 60 and I wonder why it was proposed. In normal English use, "else" is not used in this way. It usually follows another word, such as "anyone else", "anything else", "or else".

You might say

"If I go to town then I will be out. Otherwise, I will stay at home". I would never replace "otherwise" with "else" in such a sentence. "Else" belongs in a statement such "Does anyone else have a view".

Tony Whyman

Adriaan van Os
to Tony Whyman
Tony Whyman wrote
Prospero Pascal was close to ISO Pascal (although I have lost my original copy of ISO Pascal) and I would guess that the above is copied from ISO Pascal.

You can find the ISO-7185 document on the internet, just search for "iso7185.pdf".

A less known aspect of the ISO-7185 Pascal case-statement is that it is an error if none of the case-conditions is met.

6.8 .3.5 Case-statements
The values denoted by the case-constants of the case-constant-lists of the case-list-elements of a case-statement shall be distinct and of the same ordinal-type as the expression of the case-index of the case-statement . On execution of the case-statement the case-index shall be evaluated . That value shall then specify execution of the statement of the case-list-element closest-containing the case-constant denoting that value . One of the case-constants shall be equal to the value of the case-index upon entry to the case-statement ; otherwise, it shall be an error.

I find the idea of a "closest containing value" rather weird. For me, programming is strict logic, not finding something "closest".

Anyway, the innocent looking case-statement does have some interesting aspects.

Show quoted text 5 lines
As an aside, I much prefer OTHERWISE to ELSE given that it is much closer to natural language. The IF...THEN..ELSE construct probably dates back to Algol 60 and I wonder why it was proposed. In normal English use, "else" is not used in this way. It usually follows another word, such as "anyone else", "anything else", "or else". You might say "If I go to town then I will be out. Otherwise, I will stay at home". I would never replace "otherwise" with "else" in such a sentence. "Else" belongs in a statement such "Does anyone else have a view".

Interesting observation !

Regards,

Adriaan van Os

Bernd Oppolzer
to Adriaan van Os: You can find the ISO-7185 document on the internet, just search for "iso7185.pdf". A less…
Adriaan van Os wrote
Anyway, the innocent looking case-statement does have some interesting aspects.

Indeed.

My Stanford compiler tries to be portable across platforms; due to its IBM mainframe heritage even on platforms that have "strange" character sets like EBCDIC.
When I ported it to ASCII based machines in 2016, I had some trouble with case statements based on
character variables and expressions.

See the story here:

http://bernd-oppolzer.de/job9i025.htm

_______________________________________________ fpc-pascal maillist  -  https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Adriaan van Os
to Tony Whyman: The historical context has interested me as well. Going back to the original "Pascal User…
Tony Whyman wrote 27 lines
Back in the early eighties, I worked at ICL and we made extensive use of the Prospero Pascal compiler building embedded systems based on the Z80 microprocessor. I still have a 1988 edition of the language specification, and this uses EBNF to define the case statement as: case-statement = "CASE" case-index "OF" case-list-element {";" case-list-element } [ ";" OTHERWISE statement][";"] "END" case-index = expression case-list-element = case-range-list ":" statement case-range-list = case-range {"," case-range } case-range = case-constant [".." case-constant ] case-constant = constant What is interesting about the above is not just that it uses "otherwise" but that it insists on a semi-colon before the "otherwise". This may not have been strictly necessary but it does enforce the separation between the case -list-elements and the "otherwise", making the "otherwise" clause into another case-list-element. It also aids readability and it may be why I have always added a semi-colon after the final case-list-element. Note that the final optional ";" is probably needed to allow those that always like to end a statement in a semi-colon. Prospero Pascal was close to ISO Pascal (although I have lost my original copy of ISO Pascal) and I would guess that the above is copied from ISO Pascal.

ISO-7185 Pascal doesn't have an else/otherwise in the case-statement, ISO-10206 Extended Pascal does, but it is of later date.

The change from "otherwise" to "else" is probably a Borland Pascal invention preferring a shorter word and then overlooking the importance of the semi-colon case-list-element separator and the resulting ambiguity. The same error then flowed through to exception handling.

As the otherwise-clause is not in ISO-7185 Pascal, it seems more plausible that Borland invented the else-clause (without semicolon) independently. All other Pascals I have looked at, use an otherwise-clause (with an obligatory semicolon). The motivation for this, given in IBM Pascal is interesting. The manual says that the statement-part of the otherwise-clause can be intentionally "left blank" and be used "to prevent possible errors during execution". I recall that in ISO-7185 Pascal it is an error if no case discriminator , the otherwise-clause was seen as a way to get around that !

Regards,

Adriaan van Os

Bernd Oppolzer
to Adriaan van Os
Adriaan van Os wrote 12 lines
As the otherwise-clause is not in ISO-7185 Pascal, it seems more plausible that Borland invented the else-clause (without semicolon) independently. All other Pascals I have looked at, use an otherwise-clause (with an obligatory semicolon). The motivation for this, given in IBM Pascal is interesting. The manual says that the statement-part of the otherwise-clause can be intentionally "left blank" and be used "to prevent possible errors during execution". I recall that in ISO-7185 Pascal it is an error if no case discriminator , the otherwise-clause was seen as a way to get around that !

This was one of Niklaus Wirth's mistakes: that the original Pascal definition did not tell how the syntax of the "otherwise" part of the case statement should be.
I recall that our profs in the computer science classes in the 1970s criticized this serious flaw of the language.

So almost every compiler had to find its own solution.

The compilers for the IBM machines were, to some degree, influenced by PL/1. There we have:
IF ... THEN ... ELSE
and
SELECT ... WHEN ... OTHER(WISE) ... END

SELECT is much the same as case, although more general; not limited to simple expressions;
not even limited to expressions ... there are two flavors of SELECT:

SELECT (expr); WHEN (A) ...; WHEN (B) ...; OTHER ...; END;
SELECT; WHEN (cond1) ...; WHEN (cond2) ...; OTHER ...; END;

PL/1 was first defined in the mid 1960s, so maybe some of the Pascal compiler designers may have been influenced (to some degree) by PL/1. Even C was influenced by PL/1 (because PL/1 was the implementation language of the Multics system, and K & R had that experience and agreed about how things should NOT be done).

BTW: my Stanford compiler uses OTHERWISE (no abbreviation). There is no error, if OTHERWISE is omitted and no case label matches; in this case, simply no action is taken. And: my compiler took some inspiration from IBMs Pascal compilers ... and some builtin functions were inspired by PL/1 functions, indeed.

Kind regards

Bernd

Show quoted text 6 lines
Regards, Adriaan van Os _______________________________________________ fpc-pascal maillist  -  https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Steve Litt
to Gerhard Scholz: statement list = statement { ";" statement } statementlist itself is not explained; I…

Gerhard Scholz via fpc-pascal said on Sat, 16 Dec 2023 20:07:45 +0100

I never had the problem because before the else I always inserted a ";"

I know it's 50+ years too late for me to submit ideas for the Pascal language, but in my perfect world you could put a semicolon at the end of anything, and if it "doesn't belong there" it's just treated as a no-op. I know this makes it harder for the compiler designer, but it sure makes it easier for me as a user.

SteveT

Steve Litt

Autumn 2023 featured book: Rapid Learning for the 21st Century http://www.troubleshooters.com/rl21