Repository navigation
Pseudocode 23
This is the first ever Pseudocode standard revision. Cheers!
Effective duration : university year 2023 – 2024
Use this information only for good; never for evil. Do not expose to fire. Do not operate heavy equipment after reading, may cause drowsiness. Do not read under the inuence of alcohol (although there have been several unconfirmed reports that alcohol actually improves the readability). (...) If you have trouble understanding a particular section, read it again and again and again… Sit up straight. Eat your vegatables. Do not mumble. Pascal standard (ISO 7185:1990)
- Spelling rules
- Whitespace
- Identifiers
- Program
- Comments
- Compiler directives
- Types
- Declarations
- Statements
- Expressions
- Parameters
Pseudocode is case-sensitive. Accents and diacritics are signficiant, except in reserved words (keywords and builtins). This means the builtin écrireÉcran can be spelled as écrireEcran or ecrireEcran, but not as écrireécran.
Whitespace is considered insignificant. This means means that extra spaces, tabs, and newlines (or any other Unicode whitespace character) do not affect the meaning of the code.
For isntance, the following statements are equivalent:
x : entier;and
x :
entier
;Identifiers are defined by the following PCRE2 regular expression: [\p{L}_][\p{L}_0-9]*
Explanation: an identifier consists of 1 or more Unicode letters, underscore or digits. The first character may not be a digit.
programme ⟨name⟩ c'estThe program is the most fundamental construct, as it is present in any Pseudocode file.
⟨name⟩ is an identifier indicating the name of the program.
The program starts after the c'est and continues until the end of the file.
Comments are used to document code and make it more readable. There are two types of comments: single-line and multi-line.
Comments do not affect the meaning of the program, but they separate tokens, effectively acting as whitespace.
Single-line comments start with // and continue until the end of the line.
// This is a single-line commentMulti-line comments start with /* and end with */. They can span multiple lines.
/* This is a multi-line
clown comment
*/Compiler directives are special instructions executed at compilation time.
#assert ⟨expr⟩ ⟨message⟩Static assertion. If ⟨expr⟩ is false, the program is halted and ⟨message⟩ is displayed. ⟨expr⟩ must be implicitly convertible to the booléen type. ⟨message⟩ is optional and must be implicitly convertible to thechaîne type.
#assert faux
#assert 1 == 1 "This should never fail"#eval expr ⟨expr⟩Shows a the value and the type of a compile-time expression.
#eval expr 1 + 1 // Prints "entier: 2"#eval type ⟨type⟩Shows information about a type.
#eval type entier // Prints "entier"Types define the kind of data that a variable can hold.
Primitive types are the most basic types. They are used to represent simple values, such as scalars, truth values and strings.
The entier type represents integers.
The réel type represents real numbers.
The booléen type represents boolean values. Truth values are expressed with the vrai (true) and faux (false) keywords.
The caractère type represents characters. The encoding is defined by the target language.
The chaîne type represents strings of runtime-known length.
The chaîne(N) type represents strings of compile-time-known length. N defines the maximum length of the string. The encoding is defined by the target language.
tableau[⟨length⟩] de ⟨item-type⟩Arrays are used to represent collections of values of the same type.
Arrays start at index 1.
- ⟨length⟩ is single expression or a comma-separated list of expressions that evaluate at compile-time to an
entiervalue. They define the length of each dimension in the array. - ⟨item-type⟩ is the type of the items in the array.
The multidimensional array syntax is just short-hand for arrays of arrays.
tableau[1, 2] de entierIs short-hand for:
tableau[1] de tableau[2] de entierstructure début
⟨composant⟩ : ⟨type⟩;
// …
finStructures are user-defined data types that group together different types of variables under a single name. This is particularly useful to handle related data together. Structures implement product types.
The contents of a structure consists of a list of variable declarations.
Examples (using type aliases):
type t_personne = structure début
nom, prenom : chaîne(50);
age : entier;
fin;
type t_classe = structure début
libelle : chaîne(20);
eleves : tableau[35] de t_personne;
fin;Declarations divide the program into named, reusable parts.
début
// statements…
finThe main program is the entry point of the program.
There must be exactly one main program.
constante ⟨type⟩ ⟨name⟩ := ⟨value⟩;Constants name values known at compile-time.
⟨value⟩ is a compile-time expression or an initializer.
constante réel PI := 3.14159;Initializers initialize variables or constants of composed (array or structure) types.
They mainly follow C's braced initialization syntax and rules.
constant tableau[10] de entier A = { 1,2,3,4,5,6,7,8,9,10 };
constante structure début
x: entier;
c: tableau [4] de caractère;
fin B := {
1
};procedure ⟨name⟩(⟨formal-parameters⟩) c'est début
// statements…
finProcedures group together and reuse statements that perform a specific task.
They can have zero or more formal parameters.
procedure sayHello(entF name : chaîne) c'est début
écrireÉcran("Hello ", name);
finfunction ⟨name⟩(⟨formal-parameters⟩) délivre ⟨type⟩ c'est début
// statements…
retourne ⟨value⟩;
finFunctions group together and reuse statements that perform a specific task and return a value.
Like procedures, functions can have zero or more formal parameters.
fonction add(entF a : entier, entF b : entier) délivre entier c'est début
retourne a + b;
finPrototypes pre-declare functions and procedures that are defined elsewhere. The syntax is reminiscent of C's, with the signature followed by a semicolon. Example:
procédure sayHello(entF name : chaîne);
fonction add(entF a : entier, entF b : entier) délivre entier;Unlike C though, parameter names may not be omitted.
A given function/procedure can be prototyped multiple times, given that all signatures be identical.
type ⟨name⟩ = ⟨type⟩;Type aliases give a name to a type, to add a level of abstraction and improve code semantics.
Example:
type t_pid = entier;
// Now t_pid is an alias for entierType aliases are commonly used to define complex array/structure types as they avoid repeating the type. Example:
type t_personne = structure début
nom : chaîne(50);
prenom : chaîne(50);
age : entier;
fin;
type t_fileAttente = tableau[50] de t_personne;Statements are the basic building blocks of a program. They are used to control the flow of execution, perform operations, and make decisions.
The no-op statement does nothing. It consists of a single semicolon ;.
Builtins are subroutines provided by the compiler.
Builtins related to input/output.
écrireÉcran(⟨arg1⟩, ⟨arg2⟩, …);The variadic écrireÉcran builtin prints the given arguments to the standard output, followed by a newline. Not all types are supported, depending on the target language.
It can also take zero arguments, in which case it just prints a newline.
lireClavier(⟨variable⟩);The lireClavier builtin reads a value from the standard input and assigns it to the given variable. Not all types are supported, depending on the target language.
assigner(⟨nomLog⟩, ⟨nomExt⟩);The assigner builtin procedure assigns a physical (exterior) file name to the provided logical file name.
ouvrirAjout(⟨nomLog⟩);The ouvrirAjout builtin procedure opens the provided file in append mode.
ouvrirÉcriture(⟨nomLog⟩);The ouvrirÉcriture builtin procedure opens the provided file in write mode.
ouvrirLecture(⟨nomLog⟩);The ouvrirLecture builtin procedure opens the provided file in read mode.
lire(⟨nomLog⟩, ⟨variable⟩);The lire builtin procedure reads a binary value from the file and assigns it to the provided variable.
écrire(⟨nomLog⟩, ⟨expression⟩);The écrire builtin procedure writes in binary the value of the provided expression to the file.
FdF(⟨nomLog⟩);The FdF builtin function tests the end-of-file indicator on the provided file and returns vrai if it is set, faux otherwise.
fermer(⟨nomLog⟩);The fermer builtin procedure closes the provided file.
⟨variable⟩ := ⟨expression⟩;Assignments change the value of a variable, which can be a local variable, an array element, or a structure component.
Any expression followed by a semicolon is a valid statement.
⟨name⟩ : ⟨type⟩;
⟨name1⟩, ⟨name2⟩ : ⟨type⟩;Declares one or more local variables.
Local variables can also have initializers.
⟨name⟩ : ⟨type⟩ := ⟨expression⟩;
⟨name1⟩, ⟨name2⟩ : ⟨type⟩ := ⟨expression⟩;When multiple variables are declared, they are all initialized to the same value.
An anonymous block défines a new scope. Syntax :
début
// instructions…
finControl flow statements are used to control the flow of execution in a program. They allow making decisions, repeating statements, and jumping to different parts of the code.
Loops allow you to repeat a block of code multiple times.
tant que ⟨condition⟩ faire
// statements…
finfaireThe tant que loop executes the statements inside the loop as long as ⟨condition⟩ is true.
⟨condition⟩ can be surrounded by parentheses.
⟨condition⟩ must be a boolean expression or implicitly convertible to boolean.
faire
// statements…
tant que ⟨condition⟩The faire loop executes the statements inside the loop at least once, and then repeats the loop as long as ⟨condition⟩ is true.
⟨condition⟩ can be surrounded by parentheses.
⟨condition⟩ must be a boolean expression or implicitly convertible to boolean.
répéter
// statements…
jusqu'à ⟨condition⟩The répéter loop executes the statements inside the loop at least once, and then repeats the loop as long as ⟨condition⟩ is false.
⟨condition⟩ can be surrounded by parentheses.
⟨condition⟩ must be a boolean expression or implicitly convertible to boolean.
pour ⟨variable⟩ de ⟨expr-min⟩ à ⟨expr-max⟩ faire [pas ⟨expr-step⟩]
// statements…
finfaireThe pour loop executes the statements inside the loop for each value of ⟨variable⟩ between ⟨expr-min⟩ and ⟨expr-max⟩.
⟨variable⟩, ⟨expr-min⟩, and ⟨expr-max⟩ must be integer expressions or implicitly convertible to integer.
⟨variable⟩ must be declared before the loop.
⟨expr-step⟩ is an optional integer expression. It defines the increment of the loop variant. When omitted, the effective value is 1.
Alternatives allow you to execute different blocks of code depending on a condition.
si ⟨condition⟩ alors
// statements…
sinonsi ⟨condition⟩ alors
// statements…
sinon
// statements…
finsiThe si statement executes the statements inside the alors block if ⟨condition⟩ is vrai.
⟨condition⟩ can be surrounded by parentheses.
⟨condition⟩ must be a boolean expression or implicitly convertible to boolean.
The sinonsi blocks are optional. They are executed if the previous si block is faux and the current sinonsi block's ⟨condition⟩ is vrai.
The sinon block is optional. It is executed if all previous si and sinonsi blocks are faux.
selon ⟨expression⟩ c'est
quand ⟨value⟩ =>
// statements…
quand ⟨value⟩ =>
// statements…
quand autre =>
// statements…
finselonThe selon statement executes the quand block whose ⟨value⟩ equals the value of ⟨expression⟩, or the quand autre block if none of the quand blocks match.
The type of ⟨expression⟩ must support the == operator.
Each case's ⟨value⟩ must be known at compile-time and of the same type as ⟨expression⟩.
Case fall-through is not supported, all cases implicitly break out of the selon.
Cases do not define their own scope, so beware of variable name collisions.
An expression is a combination of values, variables, operators, and functions that is evaluated to produce a result. Expressions are fundamental building blocks in programming and are used to perform calculations, make decisions, and manipulate data.
String literals are enclosed in double quotes ("). They can only span a single line.
They support escape sequences.
Character literals consist of a single character enclosed in single quotes (').
They too support escape sequences.
| Escape sequence | Meaning |
|---|---|
\a |
Alert (Beep, Bell) |
\b |
Backspace |
\e |
Escape character |
\f |
Formfeed (Page Break) |
\n |
Newline (Line Feed) |
\r |
Carriage Return |
\t |
Horizontal Tab |
\v |
Vertical Tab |
\\ |
Backslash |
\' |
Apostrophe or single quotation mark |
\" |
Double quotation mark |
\nnn |
The byte whose numerical value is given by nnn interpreted as an octal number |
\xhh… |
The byte whose numerical value is given by hh… interpreted as a hexadecimal number |
\uhhhh |
Unicode code point below 10000 hexadecimal |
\Uhhhhhhhh |
Unicode code point where h is a hexadecimal digit |
TL;DR: same as C, but no \? (since this language has no trigraphs).
Integers are whole numbers without a decimal point. Integer literals are expressed as a sequence of decimal digits.
Real literals are expressed as a sequence of decimal digits with an optional decimal point. The digits before the decimal point are optional.
Booleans are either vrai (true) or faux (false).
The following table lists the precedence and associativity of each operator. Operators are listed top to bottom, in descending precedence.
| Precedence | Operator | Description | Associativity |
|---|---|---|---|
| 1 |
()[].
|
Function/procedure call Array subscript Structure component access |
Left-to-right |
| 2 |
+ -NON(type)
|
Unary plus and minus Logical or bitwise negation Cast |
Right-to-left |
| 3 |
* / %
|
Multiplication, division, and remainder | Left-to-right |
| 4 |
+ -
|
Addition and subtraction | Left-to-right |
| 5 |
< <=> >=
|
For relational operators < and ≤ respectively For relational operators > and ≥ respectively |
Left-to-right |
| 6 |
== !=
|
For relational = and ≠ respectively | Left-to-right |
| 7 | XOR |
Logical or bitwise exclusive disjunction (exclusive OR) | Left-to-right |
| 8 | ET |
Logical or bitwise conjunction (AND) | Left-to-right |
| 9 | OU |
Logical or bitwise disjunction (OR) | Left-to-right |
When parsing an expression, an operator which is listed on some row will be bound tighter (as if by parentheses) to its arguments than any operator that is listed on a row further below it. For example, the expression a + b * c is parsed as a + (b * c), and not as (a + b) * c.
Operators that are in the same cell (there may be several rows of operators listed in a cell) are evaluated with the same precedence, in the given direction.
nomFonction(⟨arg1⟩, ⟨arg2⟩, …)Calls are used to invoke functions and procedures. They are expressions that evaluate to a value. When calling a procedure, the produced value is of type void and cannot be used for anything.
⟨arg1⟩, ⟨arg2⟩, … are effective parameters.
This is a graph of the allowed conversions between types.
flowchart LR
booléen -.faux → 0<br>vrai → 1.-> entier
entier -.0 → faux<br>≠0 → vrai.-> booléen
caractère -.impl-defined.-> entier
entier -.impl-defined.-> caractère
chaîneN["chaîne(<var>N</var>)"] --> chaîne
chaîneN ==Larger string (<var>n</var> > 0)==> chaîneN2["chaîne(<var>N</var> + <var>n</var>) "]
entier --> réel
réel -.round towards zero .->entier
nomFichierLog
arrays["<em>any array</em>"]
structures["<em>any structure</em>"]
| Link shape | Conversion kind |
|---|---|
| Solid | implicit |
| Dotted | explicit (with cast syntax) |
| Thick | assigment only |
When a conversion is impl-defined, the result depends on the rules of the target language.
When a conversion's result isn't specified, identity is assumed.
Formal parameters define data a function/procedure expects from the caller.
Syntax:
⟨formal-mode⟩ ⟨name⟩ : ⟨type⟩Effective parameters are the actual values passed to a function/procedure, matching its formal parameters.
Syntax:
⟨effective-mode⟩ ⟨name⟩| name | formal mode | effective mode | description |
|---|---|---|---|
| input | entF |
entE |
The value is copied from the caller. |
| output | sortF |
sortE |
The function/procedure initializes the value. The value is undefined before it is assigned. |
| input/output | entF/sortF |
entE/sortE |
The function/procedure may mutate the value on the caller's side. |