Pascal Syntax v102
Pascal Syntax v102
FOR mikroPascal
2
Whitespace
Spaces (blanks), horizontal and vertical tabs and newline characters are together called
whitespaces. Whitespaces are used as separators to indicate where tokens start and
end. For example, the two following sequences
var i : char;
j : word;
and
var
i : char;
j : word;
are lexically equivalent and parse identically giving the nine tokens each:
var
i
:
char
;
j
:
word
;
Whitespace in Strings
Whitespace may occur within string literals. In this case it is not used as a parser, but is con-
strued as a common character, i.e. represents part of the string alone. For example, the follow-
ing string
parses into four tokens, including the string literal as a single token:
some_string
:=
'mikro foo'
;
3
Tokens
A token is the smallest element of the Pascal programming language which is recognized
by the compiler. The parser analyzes the program code from left to right and creates the
longest possible tokens from the sequence of input characters.
Keywords
Keywords or reserved words are tokens with fixed meaning which cannot be used as
identifiers. In addition to standard mikroPascal keywords, there is a set of predefined
identifiers (of constants and variables) referred to as reserved words. They describe spe-
cific microcontroller and cannot be redefined. Here is a list of the mikroPascal keywords
in alphabetical order:
Comments
Comments are part of the program used for clarifying program operation or for providing
more information about it. They are exclusively intended for the programmer’s use and
are removed from the program before parsing. There are single-line and multi-line com-
ments in mikroPascal. Multi-line comments are enclosed in braces or (* and *) as in
example below:
{ Text within left and right brace
makes a comment which may span multiple lines. }
(* Comment can be
written in this way too. *)
Identifiers
Identifiers are arbitrary names used for designating the basic language objects (labels, types,
constants, variables, procedures and functions). Identifiers may contain all the letters of alpha-
bet (both upper case and lower case), the underscore character ‘_’ and digits (0 to 9). The first
character of an identifier must be a letter or an underscore. mikroPascal is not case sensitive,
so that Sum, sum, and suM are recognized as equivalent identifiers. Although identifier names
are arbitrary (within the rules stated), some errors may occur if the same name is used for more
than one identifier within the same scope. Here are some valid identifiers:
temperature_V1
Pressure
no_hit
dat2string
SUM3
_vtext
Literals
Literals are tokens representing fixed numerical or character values. The compiler deter-
mines data type of a literal on the basis of its format (the way it is represented in the
code) and its numerical value.
5
Integer Literals
Integral literals can be written in decimal, hexadecimal or binary notation.
11 // decimal literal
$11 // hex literal equal to decimal 17
0x11 // hex literal equal to decimal 17
%11 // binary literal equal to decimal 3
The allowed range for constant values is determined by the longint type for signed con-
stants and dword type for unsigned constants.
Decimal integer;
Decimal point;
Decimal fraction; and
e or E and a signed integer exponent (optional).
Character Literals
Character literals are ASCII characters, enclosed in single quotation marks. Character literals
may be assigned to variables of integral and string type, array of characters and array of bytes.
A variable of integral type will be assigned the ASCII value of the corresponding character lit-
eral. Note that double quotation marks ("") have no special meaning in mikroPascal.
6
String Literals
String literal represents a sequence of ASCII characters written in one line and enclosed
in single quotation marks. As mentioned before, string literals may contain whitespaces.
The parser does not “go into” string literals, but treats them as single tokens. The length
of a string literal depends on the number of characters it consists of. There is a final null
character (ASCII zero) at the end of each string literal. It is not included in the string’s total
length. A string literal with nothing in between the quotation single marks (null string) is
stored as one single null character. String literals can be assigned to string variables, array
of char or array of byte. Here are several string literals:
'Hello world!' // message, 12 chars long
'Temperature is stable' // message, 21 chars long
' ' // two spaces, 2 chars long
'C' // letter, 1 char long
'' // null string, 0 chars long
Punctuators
mikroPascal uses the following punctuators (also known as separators):
[ ] - square brackets;
( ) - parentheses;
, - comma;
; - semicolon;
: - colon
. - dot
Square brackets
Brackets [ ] are used for indicating single and multidimensional array’s indices:
Parentheses
Parentheses ( ) are used for grouping expressions, isolating conditional expressions and
for indicating function calls and function declarations:
d := c * (a + b); // Group expressions
if (d = z) then ... // Conditional expressions
func(); // Function call, no parameters
function func2(n : word); // Function declaration with parameters
Comma
Commas ‘,’ are used for the purpose of separating parameters in function calls, identi-
fiers in declarations and elements of initializer:
Lcd_Out(1, 1, txt);
var i, j, k : byte;
const MONTHS : array[1..12] of byte = (31,28,31,30,31,30,31,31,30,31,30,31);
7
Semicolon
Every statement in mikroPascal must be terminated by a semicolon ‘;’. The only excep-
tion is the last (outermost) end statement in the program which is terminated by a dot,
as well as the statement preceding the else keyword. The semicolon is also used for
denoting the place in assembly blocks where comments start.
Colon
A colon (:) is used in declarations for separating variable and constant identifiers from
type identifiers. For example:
var
i, j : byte;
k : word;
Dot
A dot (.) is used to indicate access to a record field. It can also be used for accessing
individual bits of registers in mikroPascal. For example:
person.surname := 'Smith';
Program Organization
Similar to other programming languages, mikroPascal provides a set of strictly defined
rules to be observed when writing programs. In other words, all the programs written in
mikroPascal have a clear and well-organized structure. Some of the program examples
are given in text below. Every project written in mikroPascal consists of a project file and
one or more units (files with the .mpas extension). The project file provides information
on the project itself, whereas units contains program code.
Main Unit
Every project in mikroPascal requires a single main unit. It is identified by the program
keyword placed at the beginning of the unit, thus instructing the compiler from where to
start the process of compiling. After an empty project is successfully created in Project
Wizard, the main unit will be automatically displayed in the Code Editor window. It con-
tains the basic structure of the program written in mikroPascal. Nothing may precede the
program keyword, except comments. The uses clause may optionally be placed after
the program name. All global identifiers of constants, variables, labels and routines are
declared before the begin keyword.
8
//********************************************************
//* Global declarations:
//********************************************************
{constant declarations}
const ...
{variable declarations}
var ...
{label declarations}
label ...
{procedure declarations}
procedure procedure_name
{local declarations}
begin
...
end;
{function declarations}
function function_name
{local declarations}
begin
...
end;
//********************************************************
//* Program body:
//********************************************************
begin
{write your code here}
end.
Other units
Other units allow you to:
break large programs into encapsulated parts that can be edited separately;
create libraries that can be used in different projects; and
distribute libraries to other developers without disclosing the source code.
9
Every unit is stored in its own file and compiled separately. Compiled units are linked
together for the purpose of creating an executable code. To build a project, the compiler
needs all the units either as program code files or object files (files created by compiling
units). All units start with the unit keyword. Apart from the comments, nothing may pre-
cede the unit keyword. The uses clause may follow the unit name.
{ procedure prototypes }
procedure procedure_name(...);
{ function prototypes }
function function_name(...);
//********************************************************
//* Implementation:
//********************************************************
implementation
{ constant declarations }
const ...
{ variable declarations }
var ...
{ label declarations }
label ...
{ procedure declarations }
procedure procedure_name
{ local declarations }
begin
...
end;
{ function declarations }
function function_name
{ local declarations }
begin
...
end;
end.
10
Uses Clause
mikroPascal includes units by means of the uses clause. It consists of the uses reserved
word and one or more comma-delimited unit names, followed by a semicolon. Unit name
does not include extension. Every unit may include at most one uses clause which must
be placed immediately after the unit name. Here is an example:
unit MyUnit;
uses utils, strings, Unit2;
...
After reaching the unit name, the compiler checks if the project contains files with the
given name and .mcl and .mpas extensions in the order and places specified in the
Search Paths option.
If both .mpas and .mcl files are found, the compiler will check their dates and include
a file of later date in the project. If the .mpas file is of later date, the compiler will
recompile it and generate new .mcl file by copying the old one;
If only .mpas file is found, the compiler will recompile it and generate the .mcl file;
Interface Section
A part of the unit above the implementation keyword is referred to as interface section.
It contains global declarations of constants, variables and labels for the project. Routines
cannot be defined in this section. Instead, the section contains declarations of routines,
defined in the implementation section, which are to be visible beyond the unit. Routine
declarations must completely match definitions thereof.
Implementation Section
The Implementation section contains private routine declarations and definitions and
allows code encapsulation. Everything declared below the implementation keyword is
for private use only, i.e. has the scope limited to that unit and thus can be used in any
block or routine defined within that unit. Any identifier declared within this section of the
unit cannot be used beyond that unit, only in routines defined after declaration of the
given identifier.
11
Scope
The scope of an identifier represents the part of the program in which the identifier can
be used. There are different categories of scope depending on how and where identifiers
are declared:
Visibility
Similar to scope, the visibility of an identifier represents the part of the program in which
the identifier can be used. Scope and visibility usually coincide, though there are some
situations in which an object referred to by an identifier becomes temporarily hidden by
its duplicate (an identifier with the same name, but different scope). In this case, the
object still exists, but cannot be accessed by its original identifier until the scope of the
duplicate identifier ends. The visibility cannot exceed the scope, but the scope can
exceed the visibility.
Types
mikroPascal is strictly typed language, which means that each variable and constant
must have its type defined before the process of compiling starts. Type checking may
prevent objects from being illegally assigned or accessed.
mikroPascal supports standard (predefined) data types such as signed and unsigned
integers of various sizes, arrays, strings, pointers etc. Besides, the user can define new
data types using the type directive. For example:
var mynumber:MyType2;
12
Simple Types
Simple types represent types that cannot be broken down into more basic elements.
Here is an overview of simple types in mikroPascal:
Arrays
An array represents a finite and arranged set of variables of the same type called ele-
ments. Type of elements is called the base type. The value of an element can be
accessed by its index which is unique for each element so that different elements may
contain the same value.
Array Declaration
Arrays are declared in the following way:
array[index_start .. index_end] of element_type
Each element of an array is numbered from the first index (index_start) to the last one
(index_end). The index_start specifier can be omitted along with dots, and thus, it
defaults to zero. The element_type specifier represents the type of array elements (the
base type). Each element of an array can be accessed by specifying array name followed
by the element index enclosed in square brackets. Here are a few examples:
var
weekdays : array[1..7] of byte;
samples : array[50] of word;
begin
// Now we can access elements of array variables, for example:
samples[0] := 1;
if samples[37] = 0 then ...
13
Constant Arrays
Constant array is initialized by assigning it a comma-delimited sequence of values
enclosed in parentheses. For example:
The number of assigned values must not exceed the specified array length, but can be
less. In this case, the trailing “excess” elements will be assigned zeroes.
Multi-dimensional Arrays
An array is one-dimensional if it is of scalar type. One-dimensional arrays are sometimes
referred to as vectors. Multidimensional arrays are created by declaring arrays of array
type. Here is an example of a 2-dimensional array:
var
m: array[50] of array[20] of byte;// 2-dimensional array of size 50x20
n: array[4] of array[2] of array[7] of byte; // 3-dimensional array of size 4x2x7
begin
...
func(m);
end.
Strings
A string represents a sequence of characters, and is equivalent to an array of char. It is
declared in the following way:
string_name string[length]
14
The string_name specifier represents a string name and must be valid identifier. The
string_length specifier represents the number of characters the string consists of. At the
end of each string, there is a final null character (ASCII code 0) which is not included in
string’s total length. A null string ('') represents an array containing a single null character.
Strings can be assigned to variables of string type, array of char and array of byte. For
example:
var
msg1 : string[20];
msg2 : string[19];
begin
msg1 := 'This is the first message';
msg2 := 'This is the second message';
msg1 := msg2;
String Splicing
var s : string[5];
//...
s := 'mik';
{
s[0] is char literal 'm'
s[1] is char literal 'i'
s[2] is char literal 'k'
s[3] is zero
s[4] is undefined
s[5] is undefined
}
mikroPascal allows you to splice strings by means of the plus operator ‘+’. This kind of con-
catenation may apply to string variables, string literals, character variables and character liter-
als. Non-printing characters can be represented by means of a non-quoted hash sign and a
number representing the ASCII code thereof (e.g. #13 for CR). For example:
mikroPascal includes the String Library which facilitates string related operations.
15
Pointers
A pointer is a variable which holds memory address of an object. While variable directly
accesses some memory address, the pointer can be thought of as a reference to that
address. To declare a pointer, it is necessary to add a carat prefix (^) before its type. For
example, to declare a pointer to an object of integer type, it is necessary to write:
^integer;
A pointer can be assigned to another pointer. It makes both pointers point to the same
memory location. Modifying the object pointed to by one pointer causes another object
pointed to by another pointer to be automatically changed since they share the same
memory location.
@ Operator
The @ operator returns the address of a variable or routine, i.e. directs a pointer to its
operand. The following rules apply to this operator:
If variable X is of array type, the @ operator will return the pointer to its first basic ele-
ment, except when the left side of the statement in which X is used is array pointer. In
this case, the @ operator will return the pointer to the array, not to its first basic element:
program example;
var w_ : word;
ptr_b : ^byte;
ptr_arr : ^array[10] of byte;
arr : array[10] of byte;
begin
ptr_b := @arr; // @ operator will return ^byte
w_ := @arr; // @ operator will return ^byte
ptr_arr := @arr; // @ operator will return ^array[10] of byte
end.
Function Pointers
mikroPascal allows the use of function pointers. This example illustrates how to define and
use function pointers. We will first define procedural type and function pointer, then call the
function by means of the pointer.
// Function definition
// Function prototype should match type definition.
function Func1(p1, p2: byte; p3: word): word;
begin
result := p1 and p2 or p3; // return value
end;
// main program:
begin
// MyPtr now points to Func1
MyPtr := @Func1;
// Call function Func1 via pointer
Sample := MyPtr^(1, 2, 3);
// MyPtr now points to Func2
MyPtr := @Func2;
// Call function Func2 via pointer
Sample := MyPtr^(1, 2, 3);
// MyPtr now points to Func3
MyPtr := @Func3;
// Call function Func3 via pointer
Sample := MyPtr^(1, 2, 3);
end.
17
Records
A record represents a heterogeneous set of elements. Each element is called a field.
Record declaration specifies the name and type of each field. For example:
The recordTypeName specifier represents a record name which must be valid identifi-
er, specifiers fieldList1..fieldListn represent lists of comma-delimited record field iden-
tifiers, whereas specifiers type1.. typen represent types of appropriate record fields. The
scope of a field identifier is limited to the record in which it occurs, so that it is not nec-
essary to take care of naming conflicts between field identifiers and other variables. Note
that in mikroPascal the record can be declared as a new type only.
For example, the following declaration creates a record called TDot:
type TDot = record
x, y : real;
end;
Each TDot contains two fields: x and y coordinates. Memory is not allocated until an
object of record type is defined as in the following example:
var m, n: TDot;
Accessing Fields
Record fields may be accessed by means of the dot (.) operator. If we declare variables
circle1 and circle2 of the previously defined type TCircle,
circle1.radius := 3.7;
circle1.center.x := 0;
circle1.center.y := 0;
18
Type Conversions
Conversion of an object of one type is the process of changing its type into another type.
mikroPascal supports both implicit and explicit conversions of basic types.
Implicit Conversion
The compiler automatically performs implicit conversion in the following situations:
Promotion
When operands are of different types, implicit conversion promotes a less complex to a
more complex type as follows:
bit byte/char
byte/char word
short integer
short longint
integer longint
integral real
Higher bytes of an extended unsigned operand are filled with zeroes. Higher bytes of an
extended signed operand are filled with a bit sign. If the number is negative, higher bytes
are filled with ones, otherwise with zeroes. For example:
var a : byte; b : word;
...
a := $FF;
b := a; // a is promoted to word, b to $00FF
Clipping
In assignment statements and statements requiring an expression of particular type, the
correct value will be stored in destination only if the result of expression doesn’t exceed
the destination range. Otherwise, excess data, i.e. higher bytes will simply be clipped
(lost).
var i : byte; j : word;
...
j := $FF0F;
i := j; // i becomes $0F, higher byte $FF is lost
19
Explicit Conversion
Explicit conversion can be executed upon any expression by specifying desired type
(byte, word, short, integer, longint, dword or real) before the expression to be con-
verted. The expression must be enclosed in parentheses. A special case represents con-
version between signed and unsigned types. Such explicit conversion does not affect
binary representation of data. For example:
var a : byte; b : short;
...
b := -1;
a := byte(b); // a is 255, not 1
// This is because binary representation remains
// 11111111; it's just interpreted differently now
Explicit conversion cannot be performed upon the operand to the left of the assignment
operator:
c := a + b; // equals 113
c := word(a + b); // equals 369
cc := a + b; // equals 369
Note: Conversion of floating point data into integral data (in assignment statements or via
explicit typecast) produces correct results only if the float value does not exceed the scope
of destination integral type.
20
Variables
A variable is an object the value of which can be changed during the runtime. Every vari-
able is declared under unique name which must be a valid identifier. Variables can be
declared in the file and routine declaration sections. Each variable needs to be declared
before it is used in the program. Global variables (visible in all files) are declared in the
the main unit declaration sections. It is necessary to specify data type for each variable.
The basic syntax of the variable declaration is:
var i, j, k : byte;
counter, temp : word;
samples : array[100] of word;
Constants
A constant is an object the value of which cannot be changed during the runtime. RAM
memory is not used for their storage. Constants are declared in the file and routine dec-
laration sections as follows:
Every constant is declared under unique name (specifier constant_name) which must
be a valid identifier. Constant names are usually written in uppercase. When declaring a
constant, it is necessary to specify its value matching the given type. Specifying the type
is optional. In the absence of type, the compiler assumes a simple type with the smallest
scope that can accommodate the constant value. mikroPascal allows shortened version
of the syntax comprising of the const keyword followed by multiple constant declara-
tions. For example:
const
MAX : longint = 10000;
MIN = 1000; // compiler will assume word type
SWITCH = 'n'; // compiler will assume char type
MSG = 'Hello'; // compiler will assume string type
MONTHS : array[1..12] of byte =
(31,28,31,30,31,30,31,31,30,31,30,31);
21
Labels
Labels serve as targets for jump statements. Mark a desired statement with a label like this:
label_identifier : statement
Every label must be declared before it is used. Similar to variables and constants, labels
are declared in the file and routine declaration sections. For the purpose of declaring a
label, the label keyword is used:
A signed label and jump statements referring to that label must belong to the same block,
i.e. no jump to or from the procedure or function can be executed. A label can be declared
only once within the block.
Functions
Functions are declared as follows:
The function_name specifier represents a function name and can be any valid identifi-
er. The parameter_list specifier within parenthesis represents a list of formal parameters
declared similar to variable declaration. In order to pass a parameter by address to a
function, it is necessary to add the var keyword at the beginning of parameter declara-
tion. Local declarations are optional declarations of variables, constants and labels and
refer to the given function only. A function body represents a sequence of statements to
be executed upon calling the function.
The return_type specifier represents the type of a function return value which can be of
complex type. The example on the following page illustrates how to define and use a
function returning a complex type.
22
begin
result.CenterX := x;
result.CenterY := y;
result.Radius := r;
end;
begin
// Get a Record via function call
MyCircle := DefineCircle(100, 200, 30);
Calling function
A function is called by specifying its name followed by actual parameters placed in the
same order as their matching formal parameters. The compiler is able to make mis-
matching parameters to get appropriate type according to implicit conversion rules. If
there is a function call in an expression, the function return value will be used as an
operand in that expression. Here’s a simple function which calculates xn on the basis of
input parameters x and n (n > 0):
function power(x, n : byte) : longint;
var i : byte;
begin
i := 0; result := 1;
if n > 0 then
for i := 1 to n do result := result*x;
end;
Procedures
Procedures are declared as follows:
procedure procedure_name(parameter_list);
{local declarations}
begin
{procedure body}
end;
The procedure_name specifier represents a procedure name and can be any valid iden-
tifier. The parameter_list specifier within parentheses represents a list of formal param-
eters which are declared similar to variables.
Calling procedure
A procedure is called by specifying its name followed by actual parameters placed in the
same order as their matching formal parameters.
24
Operators
Operators are tokens denoting operations to be performed upon operands in an expres-
sion. If the order of execution is not explicitly determined using parentheses, it will be
determined by the operator precedence. There are 4 precedence categories in
mikroPascal. Operators in the same category have equal precedence. Each category
has associativity rules, either left-to-right () or right-to-left (). In the absence of paren-
theses, these rules resolve grouping of expressions with operators of equal precedence.
Arithmetic Operators
Arithmetic operators are used for performing computing operations. Operands of char
type are bytes and can be used as unsigned operands in arithmetic operations therefore.
All arithmetic operators associate from left to right.
Division by Zero
If a zero (0) is used explicitly as the second operand in the division operation (x div 0),
the compiler will report an error and will not generate a code. In case of implicit division
where the second operand is an object the value of which is 0 (x div y, where y=0), the
result will be undefined.
Relational Operators
Relational operators are used in logic operations. All relational operators return TRUE or
FALSE and associate from left to right.
Operator Operation
= equal
<> not equal
> greater than
< less than
>= greater than or equal
<= less than or equal
Bitwise Operators
Bitwise operators are used for modifying individual bits of an operand. Bitwise operators
associate from left to right. The only exception is the bitwise complement operator not
which associates from right to left.
26
Operator Operation
AND operator compares pairs of bits and generates 1 if both bits are
and
1, otherwise it generates 0.
OR operator compares pairs of bits and generates 1 if either or both
or
bits are 1, otherwise it generates 0.
XOR operator compares pairs of bits and generates 1 if the bits are
xor
complementary, otherwise it generates 0.
not Bitwise complement (unary) inverts each bit.
Shift left operator moves bits to the left, discards the leftmost bit and
shl
assigns 0 to the rightmost bit.
Shift right operator moves bits to the right and discards the
shr rightmost bit. If the object is unsigned, the leftmost bit is assigned 0.
Otherwise, it is assigned a bit sign.
Expressions
An expression is a sequence of operators, operands and punctuators that returns a
value. Primary expressions include literals, constants, variables and function calls. These
can be used for creating more complex expressions by means of operators. The way
operands and subexpressions are grouped does not necessarily represent the order in
which they are evaluated in mikroPascal.
Statements
Statements define operations within a program. Every statement needs to be terminated
by a semicolon ‘;’. In the absence of jump and selection statements, statements are exe-
cuted sequentially in the order of appearance in the program code.
Assignment Statements
Assignment statements look as follows:
var_name := some_expression;
The statement evaluates the expression and assigns its value to a variable. All implicit
conversion rules apply. The var_name specifier can be any declared variable, whereas
some_expression represents an expression the value of which matches the given vari-
able. Do not confuse the assignment operator ‘:=’ with relational operator ‘=’ used for
testing equality.
Compound Statements
A compound statement or a block is a set of statements enclosed within the begin and
end keywords:
begin
statements
end;
end.
In mikroPascal, the end. statement (the closing statement of every program) acts as an endless loop.
28
Conditional Statements
Conditional or selection statements make selection from alternative courses of program
execution by testing certain values.
If Statement
If statement is a conditional statement. The syntax of the if statement looks as follows:
Nested if statements
Nested if statements require additional attention. A general rule is that they are parsed
starting from the innermost if statement (the most nested) and each else statement is
bound to the nearest available if on its left:
if expression1 then
if expression2 then statement1
else statement2
if expression1 then
begin
if expression2 then statement1
else statement2
end
To make the compiler to interpret the same block in another way, it is necessary to explic-
itly group the statements by means of begin-end blocks:
if expression1 then
begin
if expression2 then statement1
end
else statement2
29
Case Statement
The case statement is a conditional statement of multiple branching. It consists of a con-
trol statement (selector) and a list of possible values of that expression. The syntax of the
case statement is:
case selector of
value_1 : statement_1
...
value_n : statement_n
[else default_statement]
end;
case operator of
'*' : result := n1 * n2;
'/' : result := n1 / n2;
'+' : result := n1 + n2;
'-' : result := n1 - n2
else result := 0;
end;
Possible values of the control statement can also be grouped so that a few values refer
to a single statement. It is just necessary to name all the values and separate them by
commas:
case reg of
0: opmode := 0;
1,2,3,4: opmode := 1;
5,6,7: opmode := 2;
end;
Iteration Statements
Iteration statements enable a set of statements to be looped. Statements break and con-
tinue can be used for controlling the flow of loop execution. The break statement terminates
the loop in which it exists, while continue starts new iteration of the loop.
For Statement
The for statement implements an iterative loop when the number of iterations is speci-
fied. The syntax of the for statement is as follows:
for counter := initial_value to final_value do some_statement
// or
for counter := initial_value downto final_value do some_statement
The counter specifier is a variable which increments (or decrements if the downto option is used)
with each iteration of the loop. Before the first iteration, the counter is set to initial value
(initial_value) and will increment (or decrement) until it reaches the final value (final_value). The
given statement (some_statement) will be executed with each iteration. It can be any state-
ment which doesn’t change the value of the counter variable. The initial_value and final_value
should be expressions compatible with the counter variable, whereas the some_statement can
be any statement that does not change the counter value. Here is an example of calculating
scalar product of two vectors, a and b, of length n, using the for statement:
s := 0;
for i := 0 to (n-1) do s := s + a[i] * b[i];
Endless Loop
The for statement results in an endless loop if the final_value equals or exceeds the
range of the counter variable. Here is an example of an endless loop, as the counter
variable can never reach the value 300:
var counter : byte;
...
for counter := 0 to 300 do ...
Another way of creating an endless loop in mikroPascal is by means of the while statement.
While Statement
The while statement implements an iterative loop when the number of iterations is not
specified. It is necessary to check the iteration condition before loop execution. The syn-
tax of the while statement is as follows:
while some_expression do some_statement
Repeat Statement
The repeat statement implements an iterative loop when the number of iterations is not
specified. The statement is executed repeatedly until the expression evaluates true. The
syntax of the repeat statement is as follows:
s := 0; i := 0;
...
repeat
s := s + a[i] * b[i];
i := i + 1;
until i = n;
Jump Statements
mikroPascal supports the following jump statements: break, continue, exit and goto.
Break Statement
Sometimes it is necessary to stop the loop from within its body. The break statement
within loop is used to pass control to the first statement following the respective loop. For
example:
Continue Statement
The continue statement within the loop is used for starting new iteration of the loop.
Statements following the continue statement will not be executed.
Exit Statement
The exit statement allows you to break out of a routine (function or procedure). It pass-
es the control to the first statement following the routine call.
Here is a simple example:
procedure Proc1();
var error: byte;
begin
...
if error = TRUE then exit;
... // some code which won't be executed if error is true
end;
Goto Statement
The goto statement is used for executing an unconditional jump to appropriate part of
the program. The syntax of the goto statement is:
goto label_name;
This statement executes a jump to the label_name label. The goto statement may occur
before or after the label declaration. The label declaration and goto statement must
belong to the same routine. Accordingly, it is not possible to jump into or out of a proce-
dure or function. The goto statement can be used for breaking out of any level of nest-
ed structures. It is not advisable to jump into a loop or other structured statement, as it
may give unexpected results. The use of the goto statement is generally discouraged as
practically every algorithm can be realized without it, resulting in legible structured pro-
grams. However, the goto statement is useful for breaking out of deeply nested control
structures:
for (...) do
begin
for (...) do
begin
...
if (disaster) then goto Error;
...
end;
end;
.
.
.
Error: // error handling code
33
asm Statement
mikroPascal allows embedding assembly instruction in the program code by means of
the asm statement. Assembly instructions may be grouped together using the asm key-
word:
asm
block of assembly instructions
end;
Directives
Directives are words of special significance which provide additional possibilities when
compiling and showing results.
Compiler Directives
mikroPascal treats comments starting with a ‘$’ sign immediately following an opening
brace as compiler directives. Such directives, among other things, enable the program
code to be conditionally compiled, i.e. it selects particular sections of the code to be com-
piled. All compiler directives must be completed within the file in which they have begun.
{$DEFINE Extended_format}
The $UNDEFINE directive is used for undefining (“clearing”) previously defined flag.
34
Directives $IFDEF..$ELSE
Conditional compilation is carried out using the $IFDEF directive. It tests whether a flag
is currently defined or not (using the $DEFINE directive). The $IFDEF directive is termi-
nated by the $ENDIF directive and may have an optional $ELSE clause:
{$IFDEF flag}
<block of code>
{$ELSE}
<alternate block of code>
{$ENDIF}
First, $IFDEF checks if the flag is defined or not. If so, only <block of code> will be com-
piled. Otherwise, <alternate block of code> will be compiled. $ENDIF ends the condi-
tional compilation sequence. The result of the preceding scenario is that only one sec-
tion of the code (possibly empty) will be compiled. This section may contain additional
(nested) conditional clauses. Each $IFDEF directive must be terminated with $ENDIF.
Here is an example:
{$IFDEF resolution10}
// <code specific to 10-bit resolution>
{$ELSE}
{$IFDEF resolution12}
// <code specific to 12-bit resolution>
{$ELSE}
// <default code>
{$ENDIF}
{$ENDIF}
Directive $I
The $I directive is a compiler directive used for inserting given file into the program at the
place from where the directive was called. Here is an example:
{$I filename.txt}
Predefined Flags
mikroPascal has predefined flags which can be used for compiling program code for dif-
ferent hardware platforms.
35
Linker Directives
mikroPascal uses internal algorithm for the purpose of distributing objects within memo-
ry. If it is necessary to have a variable or a routine at some specific predefined address,
linker directives absolute, org and orgall must be used.
Directive absolute
The absolute directive specifies the starting variable address in RAM. For multi-byte
variables, the higher bytes will be stored at adjacent, consecutive locations starting from
the given location. This directive is appended to variable declaration:
Directive org
The org directive specifies the starting address of a routine in ROM. It is appended to
the routine declaration. For example:
Constant aggregates (records, arrays) can also be allocated at the specified address in
ROM by means of the org directive.
Directive orgall
The orgall directive is used for specifying the starting address of a routine in ROM from
where placing of all routines and constants starts. For example:
begin
orgall(0x200) // All routines and constants in the program will be
// stored above the 0x200 address, including origin routine as well.
...
end.
If you want to learn more about our products, please visit our website: www.mikroe.com
If you are experiencing some problems with any of our products or just need additional information, please place
your ticket at www.mikroe.com/en/support
If you have any question, comment or business proposal, do not hesitate to contact us: office@mikroe.com