Skip to content

Pseudocode 23

Scover edited this page Dec 17, 2024 · 14 revisions

Pseudocode 23 (codename FVR-0)

Formal grammar

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)

Table of contents

Spelling rules

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

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

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.

Program

programme ⟨name⟩ c'est

The 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

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

Single-line comments start with // and continue until the end of the line.

// This is a single-line comment

Multi-line

Multi-line comments start with /* and end with */. They can span multiple lines.

/* This is a multi-line

clown comment
*/

Compiler directives

Compiler directives are special instructions executed at compilation time.

assert

#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.

Example

#assert faux
#assert 1 == 1 "This should never fail"

eval expr

#eval expr ⟨expr⟩

Shows a the value and the type of a compile-time expression.

Example

#eval expr 1 + 1 // Prints "entier: 2"

eval type

#eval type ⟨type⟩

Shows information about a type.

Example

#eval type entier // Prints "entier"

Types

Types define the kind of data that a variable can hold.

Primitives

Primitive types are the most basic types. They are used to represent simple values, such as scalars, truth values and strings.

entier

The entier type represents integers.

réel

The réel type represents real numbers.

booléen

The booléen type represents boolean values. Truth values are expressed with the vrai (true) and faux (false) keywords.

caractère

The caractère type represents characters. The encoding is defined by the target language.

chaîne

The chaîne type represents strings of runtime-known length.

chaîne(N)

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.

Arrays

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 entier value. They define the length of each dimension in the array.
  • ⟨item-type⟩ is the type of the items in the array.

Mulltidimensional arrays

The multidimensional array syntax is just short-hand for arrays of arrays.

tableau[1, 2] de entier

Is short-hand for:

tableau[1] de tableau[2] de entier

Structures

structure début
    ⟨composant⟩ : ⟨type⟩;
    // …
fin

Structures 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

Declarations divide the program into named, reusable parts.

Main program

début
    // statements…
fin

The main program is the entry point of the program.

There must be exactly one main program.

Constants

constante ⟨type⟩ ⟨name⟩ := ⟨value⟩;

Constants name values known at compile-time.

⟨value⟩ is a compile-time expression or an initializer.

Example

constante réel PI := 3.14159;

Initializers

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
};

Procedures

procedure ⟨name⟩(⟨formal-parameters⟩) c'est début
    // statements…
fin

Procedures group together and reuse statements that perform a specific task.

They can have zero or more formal parameters.

Example

procedure sayHello(entF name : chaîne) c'est début
    écrireÉcran("Hello ", name);
fin

Functions

function ⟨name⟩(⟨formal-parameters⟩) délivre ⟨type⟩ c'est début
    // statements…
    retourne ⟨value⟩;
fin

Functions group together and reuse statements that perform a specific task and return a value.

Like procedures, functions can have zero or more formal parameters.

Example

fonction add(entF a : entier, entF b : entier) délivre entier c'est début
    retourne a + b;
fin

Prototypes

Prototypes 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 aliases

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 entier

Type 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

Statements are the basic building blocks of a program. They are used to control the flow of execution, perform operations, and make decisions.

No-op

The no-op statement does nothing. It consists of a single semicolon ;.

Builtins

Builtins are subroutines provided by the compiler.

IO

Builtins related to input/output.

écrireÉcran
é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
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.

Files

assigner
assigner(⟨nomLog⟩, ⟨nomExt⟩);

The assigner builtin procedure assigns a physical (exterior) file name to the provided logical file name.

ouvrirAjout
ouvrirAjout(⟨nomLog⟩);

The ouvrirAjout builtin procedure opens the provided file in append mode.

ouvrirÉcriture
ouvrirÉcriture(⟨nomLog⟩);

The ouvrirÉcriture builtin procedure opens the provided file in write mode.

ouvrirLecture
ouvrirLecture(⟨nomLog⟩);

The ouvrirLecture builtin procedure opens the provided file in read mode.

lire
lire(⟨nomLog⟩, ⟨variable⟩);

The lire builtin procedure reads a binary value from the file and assigns it to the provided variable.

écrire
écrire(⟨nomLog⟩, ⟨expression⟩);

The écrire builtin procedure writes in binary the value of the provided expression to the file.

FdF
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
fermer(⟨nomLog⟩);

The fermer builtin procedure closes the provided file.

Assignments

⟨variable⟩ := ⟨expression⟩;

Assignments change the value of a variable, which can be a local variable, an array element, or a structure component.

Expression statements

Any expression followed by a semicolon is a valid statement.

Local variables

⟨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.

Anonymous block

An anonymous block défines a new scope. Syntax :

début
    // instructions…
fin

Control Flow

Control 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

Loops allow you to repeat a block of code multiple times.

While loop

tant que ⟨condition⟩ faire
    // statements…
finfaire

The 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.

Do … while loop

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.

Repeat loop

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.

For loop

pour ⟨variable⟩ de ⟨expr-min⟩ à ⟨expr-max⟩ faire [pas ⟨expr-step⟩]
    // statements…
finfaire

The 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

Alternatives allow you to execute different blocks of code depending on a condition.

Si

si ⟨condition⟩ alors
    // statements…
sinonsi ⟨condition⟩ alors
    // statements…
sinon
    // statements…
finsi

The 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

selon ⟨expression⟩ c'est
    quand ⟨value⟩ =>
        // statements…
    quand ⟨value⟩ =>
        // statements…
    quand autre =>
        // statements…
finselon

The 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.

Expressions

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.

Values

Strings

String literals are enclosed in double quotes ("). They can only span a single line.

They support escape sequences.

Characters

Character literals consist of a single character enclosed in single quotes (').

They too support escape sequences.

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

Integers are whole numbers without a decimal point. Integer literals are expressed as a sequence of decimal digits.

Reals

Real literals are expressed as a sequence of decimal digits with an optional decimal point. The digits before the decimal point are optional.

Booleans

Booleans are either vrai (true) or faux (false).

Operations

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.

Calls

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.

Conversions

This is a graph of the allowed conversions between types.

flowchart LR
booléen -.faux &rarr; 0<br>vrai &rarr; 1.-> entier
entier -.0 &rarr; faux<br>&ne;0 &rarr; 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>"]
Loading
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.

Parameters

Formal parameters

Formal parameters define data a function/procedure expects from the caller.

Syntax:

⟨formal-mode⟩ ⟨name⟩ : ⟨type⟩

Effective parameters

Effective parameters are the actual values passed to a function/procedure, matching its formal parameters.

Syntax:

⟨effective-mode⟩ ⟨name⟩

Parameter modes

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.

Clone this wiki locally