Pascal, in its original form, is a purely
procedural language and includes the traditional array of
ALGOL-like control structures with reserved words such as if, then, else, while, for, and case, ranging on a single statement or a begin-end statements block. Pascal also has data structuring constructs not included in the original
ALGOL 60 types, like
records, variants,
pointers,
enumerations, and
sets and procedure pointers. Such constructs were in part inherited or inspired from
Simula 67,
ALGOL 68,
Niklaus Wirth's own
ALGOL W and suggestions by
C. A. R. Hoare. Pascal programs start with the program
keyword with a list of external
file descriptors as parameters (not required in Turbo Pascal etc.); then follows the main
block bracketed by the begin and end keywords.
Semicolons separate
statements, and the
full stop (i.e., a period) ends the whole program (or
unit).
Letter case is ignored in Pascal source. Here is an example of the source code in use for a very simple
"Hello, World!" program: : program HelloWorld(output); begin WriteLn('Hello, World!') {No ";" is required after the last statement of a block - adding one adds a "null statement" to the program, which is ignored by the compiler.} end.
Data types A type declaration in Pascal is used to define a range of values which a variable of that type is capable of storing. It also defines a set of operations that are permissible to be performed on variables of that type. The predefined types are: The range of values allowed for the basic types (except Boolean) is implementation defined. Functions are provided for some data conversions. For conversion of real to integer, the following functions are available: round (using
rounding half away from zero) and trunc (rounds towards zero). The programmer has the freedom to define other commonly used data types (e.g. byte, string, etc.) in terms of the predefined types using Pascal's type declaration facility, for example : type byte = 0..255; signed_byte = -128..127; string = packed array[1..255] of char; Often-used types like byte and string are already defined in many implementations. Normally the system will use a
word to store the data. For instance, the type may be stored in a machine integer—32 bits perhaps—rather than an
8-bit value. Pascal does not contain language elements that allow the basic storage types to be defined more granularly. This capability was included in a number of Pascal extensions and follow-on languages, while others, like
Modula-2, expanded the built-in set to cover most machine data types like 16-bit integers. The keyword tells the compiler to use the most efficient method of storage for the structured data types: sets, arrays and records, rather than using one
word for each element. Packing may slow access on machines that do not offer easy access to parts of a word.
Subrange types Subranges of any
ordinal data type (any simple type except real) can also be made: : var x : 1..10; y : 'a'..'z';
Set types In contrast with other programming languages from its time, Pascal supports a set type: : var Set1 : set of 1..10; Set2 : set of 'a'..'z'; A set is a fundamental concept for modern mathematics, and they may be used in many algorithms. Such a feature is useful and may be faster than an equivalent construct in a language that does not support sets. For example, for many Pascal compilers: : if i in [5..10] then ... executes faster than: : if (i > 4) and (i Sets of non-contiguous values can be particularly useful, in terms of both performance and readability: : if i in [0..3, 7, 9, 12..15] then ... For these examples, which involve sets over small domains, the improved performance is usually achieved by the compiler representing set variables as
bit vectors. The set
operators can then be implemented efficiently as bitwise machine code operations.
Record types An example of a Pascal record type: : type car = record length: integer; width: integer end; An example of a variant record type: : type Shape = (Circle, Square, Triangle); Dimensions = record case Figure: Shape of Circle: (Diameter: real); Square: (Width: real); Triangle: (Side: real; Angle1, Angle2: 0..360) end; Variant records allow several fields of the record to overlap each other to save space.
Type declarations Types can be defined from other types using type declarations: : type x = integer; y = x; ... Further, complex types can be constructed from simple types: : type a = array[1..10] of integer; b = record x : integer; y : char {extra semicolon not strictly required} end; c = file of a; Further, complex types can be constructed from other complex types recursively: : const Jack = 11; Queen = 12; King = 13; Ace = 14; type valueType = 2..Ace; suitType = club, diamond, heart, spade; cardType = record suit: suitType; value: valueType; end; deckType = array [1..52] of cardType; person = record surname: packed array [1..20] of char; age: integer; end; table = record hands: array [1..3] of deckType; players: array [1..4] of person; end;
File type : type a = file of integer; b = record x : integer; y : char end; c = file of b; As shown in the example above, Pascal
files are sequences of components. Every file has a buffer variable which is denoted by
f^. The procedures
get (for reading) and
put (for writing) move the buffer variable to the next element. Read is introduced such that
read(f, x) is the same as
x := f^; get(f);. Write is introduced such that
write(f, x) is the same as
f^ := x; put(f); The type is predefined as file of char. While the buffer variable could be used for inspecting the next character to be used (check for a digit before reading an integer), this leads to serious problems with interactive programs in early implementations, but was solved later with the "lazy I/O" concept, which waits until the file buffer variable is actually accessed before performing file operations.
Pointer types Pascal supports
pointers: : type pNode = ^Node; Node = record a : integer; b : char; c : pNode end; var NodePtr : pNode; IntPtr : ^integer; Here the variable
NodePtr is a pointer to the data type
Node, a record. Pointers to not-yet-defined types can be declared (in the above example, pNode is a pointer to a Node, but Node is not yet defined when the pointer type is defined). This is a
forward declaration, an exception to the rule that things must be declared before they are used. To create a new record and assign the value
10 and character
A to the fields
a and
b in the record, and to initialise the pointer
c to the
null pointer ("NIL" in Pascal), the statements would be: : new(NodePtr); ... NodePtr^.a := 10; NodePtr^.b := 'A'; NodePtr^.c := nil; ... This could also be done using the with statement, as follows: new(NodePtr); ... with NodePtr^ do begin a := 10; b := 'A'; c := nil end; ... Inside of the scope of the
with statement, a and b refer to the subfields of the record pointer
NodePtr and not to the record Node or the pointer type pNode.
Linked lists,
stacks and
queues can be created by including a pointer type field (c) in the record. Unlike many languages that feature pointers, Pascal only allows pointers to reference dynamically created variables that are anonymous, and does not allow them to reference standard static or local variables. Pointers also must have an associated type, and a pointer to one type is not compatible with a pointer to another type (e.g. a pointer to a char is not compatible with a pointer to an integer). This helps eliminate the type security issues inherent with other pointer implementations, particularly those used for
PL/I or
C. It also removes some risks caused by
dangling pointers, but the ability to dynamically deallocate referenced space by using the
dispose function (which has the same effect as the
free library function found in
C) means that the risk of dangling pointers has not been eliminated as it has in languages such as Java and C#, which provide
automatic garbage collection (but which do not eliminate the related problem of
memory leaks). Some of these restrictions can be lifted in newer dialects.
Control structures Pascal is a
structured programming language, meaning that the flow of control is structured into standard
statements, usually without "
goto" commands. : while a <> b do WriteLn('Waiting'); if a > b then WriteLn('Condition met') {no semicolon allowed before else} else WriteLn('Condition not met'); for i := 1 to 10 do {no semicolon here as it would detach the next statement} WriteLn('Iteration: ', i); repeat a := a + 1 until a = 10; case i of 0 : Write('zero'); 1 : Write('one'); 2 : Write('two'); 3,4,5,6,7,8,9,10: Write('?') end;
Procedures and functions Pascal structures programs into procedures and functions. Generally, a procedure is used for its side effects, whereas a function is used for its return value. : program Printing(output); var i : integer; procedure PrintAnInteger(j : integer); begin ... end; function triple(x: integer): integer; begin triple := x * 3 end; begin { main program } ... PrintAnInteger(i); PrintAnInteger(triple(i)) end. Procedures and functions can be nested to any depth, and the "program" construct is the logical outermost block. By default, parameters are passed by value. If "var" precedes a parameter's name, it is passed by reference. Each procedure or function can have its own declarations of goto labels, constants, types, variables, and other procedures and functions, which must all be in that order. This ordering requirement was originally intended to allow efficient
single-pass compilation. However, in some dialects (such as
Delphi) the strict ordering requirement of declaration sections has been relaxed.
Semicolons as statement separators Pascal adopted many language syntax features from the
ALGOL language, including the use of a semicolon as a statement separator. This is in contrast to other languages, such as
PL/I and
C, which use the semicolon as a statement terminator. No semicolon is needed before the end keyword of a record type declaration, a block, or a
case statement; before the until keyword of a repeat statement; and before the else keyword of an
if statement. The presence of an extra semicolon was not permitted in early versions of Pascal. However, the addition of
ALGOL-like empty statements in the 1973
Revised Report and later changes to the language in ISO 7185:1983 now allow for optional semicolons in most of these cases. A semicolon is still not permitted immediately before the else keyword in an
if statement, because the else follows a single statement, not a statement sequence. In nested ifs, a semicolon cannot be used to avoid the
dangling else problem (where the inner if does not have an else, but the outer if does) by putatively terminating the nested if with a semicolon – this instead terminates both if clauses. Instead, an explicit begin...end block must be used. ==Resources==