Le langage de programmation Oberon-0

Afin d’éviter de nous perdre dans des généralités et des théories abstraites, nous construirons un compilateur spécifique et concret, et nous expliquerons les différents problèmes qui se surviennent au cours du projet. Pour ce faire, nous nous orientons vers un langage source spécifique.

Bien entendu, ce compilateur, et donc le langage, doit rester suffisamment simple pour rester dans le cadre de ce cours.

Pour rester dans le cadre de ce cours, nous devons bien entendu garder ce compilateur, et donc aussi le langage, suffisamment simple. D’autre part, nous souhaitons expliquer autant que possible les constructions fondamentales des langages et des techniques de compilation.

Ces considérations ont donné lieu aux conditions limites pour le choix du langage : il doit être simple et représentatif. Nous avons choisi un sous-ensemble du langage Oberon1, qui condense les caractéristiques essentielles de ses ancêtres Modula-22 et Pascal3.

On peut dire qu’Oberon est le dernier né de la tradition d’Algol 60 (Naur, 1960). Notre sous-ensemble est appelé Oberon-0, et il est suffisamment puissant pour enseigner et exercer les fondements des méthodes de programmation modernes.

En ce qui concerne les structures de programme, Oberon-0 est raisonnablement bien développé. L’instruction élémentaire est l’affectation. Les instructions composées intègrent les concepts de séquence d’instructions et d’exécution conditionnelle (if) et répétitive (while et repeat). Oberon-0 supporte également le concept important de sous-programme, représenté par la déclaration de procédure et l’appel de ces procédures. Tout comme Oberon, Oberon-0 permet le passage de paramètres par valeur et par référence.

Oberon-0 adopte une approche minimaliste en matière de types de données. Les types de données de base sont limités aux entiers et aux valeurs logiques, représentés par INTEGER et BOOLEAN. Cela permet de déclarer des constantes et des variables avec des valeurs entières, ainsi que de créer des expressions arithmétiques. Les comparaisons entre ces expressions produisent des valeurs booléennes, qui peuvent ensuite être manipulées à l’aide d’opérations logiques.

Afin de simplifier le langage, nous avons décidé de ne pas inclure les types de données plus complexes tels que les chaînes de caractères, les tableaux, les structures ou les pointeurs4.

Les procédures sont des unités fonctionnelles des instructions. Il est donc pertinent d’associer le concept de portée des noms (scope) à celui de procédure. Oberon-0 permet de déclarer des variables locales à une procédure, ce qui signifie que les identifiants de ces variables ne sont visibles qu’à l’intérieur de la procédure elle-même.

Ce bref aperçu d’Oberon-0 a pour but de fournir le contexte nécessaire pour comprendre la syntaxe suivante, définie en termes d’EBNF.

ident = letter {letter | digit}.
integer = digit {digit}.
number = integer.
factor = ident [ActualParameters] | number |
    "(" expression ")" | "~" factor.
term = factor {("*" | "DIV" | "MOD" | "&") factor}.
SimpleExpression = ["+"|"-"] term {("+"|"-" | "OR") term}.
expression = SimpleExpression
    [("=" | "#" | "<" | "<=" | ">" | ">=") SimpleExpression].
assignment = ident ":=" expression.
ActualParameters = "(" [expression {"," expression}] ")" .
ProcedureCall = ident [ActualParameters].
IfStatement = 
    "IF" expression "THEN" StatementSequence
    {"ELSIF" expression "THEN" StatementSequence}
    ["ELSE" StatementSequence] "END".
WhileStatement = "WHILE" expression "DO" StatementSequence "END".
RepeatStatement = "REPEAT" StatementSequence "UNTIL" expression.
statement = [assignment | ProcedureCall | IfStatement |
    WhileStatement | RepeatStatement].
StatementSequence = statement {";" statement}.
IdentList = ident {"," ident}.
type = ident.
FPSection = ["VAR"] IdentList ":" type.
FormalParameters = "(" [FPSection {";" FPSection}] ")".
ProcedureHeading = "PROCEDURE" ident ["*"] [FormalParameters].
ProcedureBody = declarations ["BEGIN" StatementSequence] "END" ident.
ProcedureDeclaration = ProcedureHeading ";" ProcedureBody.
declarations = 
    ["CONST" {ident "=" expression ";"}]
    ["VAR" {IdentList ":" type ";"}]
    {ProcedureDeclaration ";"}.
module = "MODULE" ident ";" declarations "END" ident "." .

Voici un exemple de module qui donne un aperçu du caractère du langage :

MODULE Samples;

  PROCEDURE Multiply*;
    VAR x, y, z: INTEGER;
  BEGIN OpenInput; ReadInt(x); ReadInt(y); z := 0;
    WHILE x > 0 DO
      IF x MOD 2 = 1 THEN z := z + y END ;
      y := 2*y; x := x DIV 2
    END ;
    WriteInt(x, 4); WriteInt(y, 4); WriteInt(z, 6); WriteLn
  END Multiply;

  PROCEDURE Divide*;
    VAR x, y, r, q, w: INTEGER;
  BEGIN OpenInput; ReadInt(x); ReadInt(y); r := x; q := 0; w := y;
    WHILE w <= r DO w := 2*w END ;
    WHILE w > y DO
      q := 2*q; w := w DIV 2;
      IF w <= r THEN r := r - w; q := q + 1 END
    END ;
    WriteInt(x.4); WriteInt(y, 4); WriteInt(q, 4); WriteInt(r, 4); WriteLn
  END Divide;

  PROCEDURE Sum*;
    VAR n, s: INTEGER;
  BEGIN OpenInput; s:= 0;
    WHILE ~eot() DO ReadInt(n); WriteInt(n, 4); s := s + n END ;
    WriteInt(s, 6); WriteLn
  END Sum;

END Samples.

  1. M. Reiser, N. Wirth. Programming in Oberon. Wokingham: Addison-Wesley, 1992. 

  2. N. Wirth. Programming in Modula-2. Heidelberg: Springer-Verlag, 1982. 

  3. N. Wirth. The programming language Pascal. Acta Informatica 1 (1971) 

  4. La version d’Oberon-0 décrite dans le livre de N. Wirth propose les structures sous la forme d’enregistrements (records) ainsi que des tableaux (arrays).