13.2.2 The Case statement

Free Pascal supports the case statement. Its syntax diagram is

_________________________________________________________________________________________________________
Case statement

--            -    -         -  ---   ------------------   -----
  case-statement  case  expression  of  -case| -       -| - --|end
                                    ;    else- part    ;

--case -|-constant- expression--|----------------------: -statement------
       |------------------..-constant- expression---|
                           ,

--else- part--|--else -----statement-list-------------------------------
           -otherwise --
____________________________________________

The constants appearing in the various case parts must be known at compile-time, and can be of the following types: enumeration types, Ordinal types (including chars) or string types. The case expression must be also of this type, or a compiler error will occur. All case constants must have the same type.

The compiler will evaluate the case expression. If one of the case constants’ value matches the value of the expression, the statement that follows this constant is executed. After that, the program continues after the final end.

If none of the case constants match the expression value, the statement list after the else or otherwise keyword is executed. This can be an empty statement list. If no else part is present, and no case constant matches the expression value, program flow continues after the final end.

The case statements can be compound statements (i. e. a Begin..End block), but for the else case multiple statements are allowed (as can be seen in the syntax diagram). You may enclose them in an extra Begin..End block, but it is not necessary.

Note that the semicolon in front of the else clause is optional. This may lead to confusion if the last label contains an if statement.

In the following example, when a equals 3, nothing will be executed:

case a of
1 :
  DoSomething;
2 :
  If b>1 then
    DoSomething
else
  DoSomethingElse;
end;

But in the following example, when a equals 3, DoSomethingElse will be executed.

case a of
1 :
  DoSomething;
2 :
  If b>1 then
    DoSomething;
else
  DoSomethingElse;
end;

When in doubt or to avoid confusion, you can enclose the last statement in an extra Begin..End block.

Remark Contrary to Turbo Pascal, duplicate case labels are not allowed in Free Pascal, so the following code will generate an error when compiling:

Var i : integer;
...
Case i of
 3 : DoSomething;
 1..5 : DoSomethingElse;
end;

The compiler will generate a Duplicate case label error when compiling this, because the 3 also appears (implicitly) in the range 1..5. This is similar to Delphi syntax.

The following are valid case statements:

Case C of
 'a' : WriteLn ('A pressed');
 'b' : WriteLn ('B pressed');
 'c' : WriteLn ('C pressed');
else
  WriteLn ('unknown letter pressed : ',C);
end;

Or

Case C of
 'a','e','i','o','u' : WriteLn ('vowel pressed');
 'y' : WriteLn ('This one depends on the language');
else
  WriteLn ('Consonant pressed');
end;

Case Number of
 1..10   : WriteLn ('Small number');
 11..100 : WriteLn ('Normal, medium number');
else
 WriteLn ('HUGE number');
end;

The else clause can contain multiple statements:

Case Number of
 1..10   : WriteLn ('Small number');
 11..100 : WriteLn ('Normal, medium number');
else
  WriteLn ('HUGE number');
  Writeln('How did we get this much ?');
end;

Free Pascal allows the use of strings as case labels, and in that case the case variable must also be a string. When using string types, the case variable and the various labels are compared in a case-sensitive way.

Case lowercase(OS) of
 'windows',
 'dos'   : WriteLn ('Microsoft platform);
 'macos',
 'darwin' : Writeln('Apple platform');
 'linux',
 'freebsd',
 'netbsd' : Writeln('Community platform');
else
  WriteLn ('Other platform');
end;

The case with strings is equivalent to a series of if then else statements, no optimizations are performed.

However, ranges are allowed, and are the equivalent of an

if (value>=beginrange) and (value<=endrange) then
  begin
  end;

Remark Note that in Delphi mode, the use of strings as case labels is not allowed.