Cours gratuits » Cours informatique » Cours programmation » Cours Oberon » Documentation Oberon en PDF

Documentation Oberon en PDF

Problème à signaler:

Télécharger



★★★★★★★★★★3.5 étoiles sur 5 basé sur 1 votes.
Votez ce document:

Documentation Oberon comment ça marche [Eng]

Partie 1 Introduction

Bien que ce manuel suppose que son lecteur est déjà familiarisé avec les notions de base de l'informatique et de la programmation, il peut être approprié de commencer par expliquer certains concepts et leur terminologie. Nous reconnaissons que - à de rares exceptions près - les programmes sont écrits - de façon plus appropriée: conçus - dans le but d'être interprétés par un ordinateur. L'ordinateur exécute alors un processus, c'est-à-dire une séquence d'actions, selon les spécifications données par ce programme. Le processus est également appelé un

calcul.

Le programme lui-même est un texte. Comme il spécifie un processus habituellement assez complexe, et doit le faire avec la plus grande précision et le plus grand soin pour tous les détails, la signification de ce texte doit être spécifiée très précisément. Une telle précision nécessite un formalisme exact. Ce formalisme est devenu connu comme un langage. Nous adoptons ce nom, bien qu'une langue soit normalement parlée et beaucoup moins précisément définie. Notre but ici est d'apprendre le formalisme ou la langue Oberon. Il a une longue tradition parmi les langages de programmation. Son ancêtre était Algol 60, suivi de Pascal et Modula-2.

Un programme spécifie généralement un processus qui amène son interpréteur, c'est-à-dire l'ordinateur, à lire des données (la soi-disant entrée) provenant de certaines sources et à faire varier ses actions ultérieures en fonction des données acceptées. Cela implique qu'un programme ne spécifie pas seulement un (unique) processus, mais une classe entière de calculs - généralement illimitée. Nous devons nous assurer que ces processus agissent selon les spécifications données (ou devrions-nous dire attentes?) Dans tous les cas de cette classe. Alors que nous pourrions vérifier que cette spécification est satisfaite dans le cas d'un calcul unique, ceci est impossible dans le cas général, car la classe de tous les processus autorisés est beaucoup trop grande. Le programmeur consciencieux assure l'exactitude de son programme par une conception et une analyse soignées. Un design soigné est l'essence de la programmation professionnelle.

La tâche de concevoir un programme est encore compliquée par le fait que le programme doit non seulement décrire toute une classe de calculs, mais doit souvent être interprété (interprété) par différents interprètes (ordinateurs). Auparavant, cela nécessitait la transcription manuelle du programme de sa forme source dans différents codes informatiques, en tenant compte de leurs diverses caractéristiques et limitations. Les difficultés ont été radicalement réduites, mais pas éliminées, par la création de langages de haut niveau avec des définitions formelles et la construction de traducteurs automatiques convertissant le programme en codes des différents ordinateurs.

En principe, le langage formel devrait être défini de manière abstraite, peut-être axiomatique, sans référence à un véritable ordinateur ou mécanisme d'interprétation. Si cela était réalisé, le programmeur devrait seulement comprendre le langage formel. Cependant, une telle généralité est coûteuse et souvent restrictive et, dans de nombreux cas, le programmeur doit toujours connaître les principales caractéristiques de son ou ses ordinateurs. Néanmoins, le programmeur qualifié fera aussi peu de référence à des caractéristiques informatiques spécifiques et s'appuiera exclusivement sur les règles du langage formel afin de garder son programme général et portable. Le langage Oberon assiste dans cette tâche en confinant les dépendances informatiques à des objets spécifiques, en permettant de les encapsuler dans de petites parties spécifiques d'un texte de programme.

De ce qui précède, il s'ensuit qu'un processus de traduction se situe entre la formulation du programme et son interprétation. Ce processus est appelé une compilation, car il condense le texte source du programme dans un code informatique cryptique. La qualité de cette compilation peut être cruciale pour l'efficacité de l'interprétation finale du programme. Nous soulignons le fait qu'il peut y avoir de nombreux compilateurs pour une langue donnée (même pour le même ordinateur). Certains peuvent être plus efficaces que d'autres. Nous reconnaissons que l'efficacité est une caractéristique des implémentations plutôt que du langage. Il est donc important de faire la distinction entre les concepts de langue et de mise en œuvre.

Nous résumons:

- Un programme est un morceau de texte.

- Le programme spécifie des calculs ou des processus.

- Un processus est effectué par un interprète, généralement un ordinateur, qui interprète (exécute) programme.

- La signification du programme est spécifiée par un formalisme appelé langage de programmation.

- Un programme spécifie une classe de calculs, les données d'entrée agissant comme paramètre de chaque processus individuel.

- Avant son exécution, un texte de programme est traduit en code informatique par un compilateur. Ce processus s'appelle une compilation.

La conception du programme consiste à s'assurer que tous les membres de cette catégorie de calculs agissent conformément aux spécifications. Ceci est fait par une vérification analytique minutieuse et par un test empirique sélectif des cas caractéristiques.

Les programmes devraient s'abstenir de faire référence aux caractéristiques d'interprètes spécifiques (ordinateurs) dans la mesure du possible. Seul le manque d'une telle référence assure que leur sens peut être dérivé des règles de la langue.

Un compilateur est un programme traduisant des programmes de leur forme source vers des codes informatiques spécifiques. Les programmes doivent être compilés avant d'être exécutés. La programmation au sens large comprend non seulement la formulation du programme, mais aussi la préparation concrète du texte, sa compilation, la correction des erreurs, ce que l'on appelle le débogage et la planification des tests. Le programmeur moderne utilise de nombreux outils pour ces tâches, y compris les éditeurs de texte, les compilateurs et les débogueurs. Il doit également être familier avec l'environnement de ces composants. Nous ne décrirons pas ces aspects, mais nous concentrerons sur le langage Oberon.

  1. Un premier exemple

Suivons les étapes de développement d'un programme simple et expliquons ainsi certains des concepts fondamentaux de la programmation et des facilités de base d'Oberon. La tâche doit être, donné deux nombres naturels x et y, pour calculer leur plus grand commun diviseur (gcd). Les connaissances mathématiques nécessaires pour ce problème sont les suivantes:

  1. si x est égal à y, x (ou y) est le résultat souhaité
  2. le gcd de deux nombres reste inchangé, si nous remplaçons le plus grand nombre par la différence des nombres, c'est-à-dire soustrayons le plus petit nombre du plus grand.

Exprimé en termes mathématiques, ces règles prennent la forme

  1. gcd (x, x) = x
  2. si x> y, gcd (x, y) = gcd (x-y, y)

La recette de base, appelée algorithme, est alors la suivante: Changer les nombres x et y selon la règle 2 de sorte que leur différence diminue. Répétez ceci jusqu'à ce qu'ils soient égaux. La Règle 2 garantit que les changements sont tels que gcd (x, y) reste toujours le même, et la règle 1 garantit que nous trouvons finalement le résultat.

Maintenant, nous devons mettre ces recommandations en termes d'Oberon. Une première tentative conduit à l'esquisse suivante. Notez que le symbole # signifie "inégale".

PENDANT x # y DO

"appliquer la règle 2, réduire la différence et maintenir x> 0 et y> 0" END

La phrase entre guillemets est un anglais simple. La deuxième version affine la première version en remplaçant l'anglais par des termes formels:

PENDANT x # y DO

SI x> y ALORS x: = x-y SINON y: = y-x FIN FIN

Ce morceau de texte n'est pas encore un programme complet, mais il montre déjà la caractéristique essentielle d'un langage de programmation structuré. La version 1 est une instruction et cette instruction contient une autre instruction subordonnée (entre guillemets). Dans la version 2, cela est élaboré, mais d'autres énoncés subordonnés émergent (exprimant le remplacement d'une valeur x par une autre valeur x-y). Cette hiérarchie d'instructions exprime la structure sous-jacente de l'algorithme. Il devient explicite en raison de la structure du langage, permettant l'imbrication des composants d'un programme. Il est donc important de connaître la structure du langage (syntaxe) en détail. Textuellement, nous exprimons l'imbrication ou la subordination par indentation appropriée. Bien que cela ne soit pas exigé par les règles de la langue, cela facilite considérablement la compréhension d'un texte.

Refléter la structure inhérente d'un algorithme par la structure textuelle du programme est une idée clé de la programmation structurée. Il est pratiquement impossible de reconnaître la signification d'un programme lorsque sa structure est supprimée, comme cela est fait par un compilateur lors de la production de code informatique. Et nous devrions garder à l'esprit qu'un programme est sans valeur, à moins qu'il existe sous une forme quelconque dans laquelle un humain peut le comprendre et gagner en confiance dans sa conception.

Nous allons maintenant dans le but de produire un programme complet à partir du fragment ci-dessus. Nous nous rendons compte que nous devons spécifier une action qui assigne des valeurs initiales aux variables x et y, ainsi qu'une action qui rend le résultat visible. À cette fin, nous devrions savoir sur les installations d'un ordinateur pour communiquer avec son utilisateur. Puisque nous ne souhaitons pas faire référence à un mécanisme spécifique, et particulièrement pas dans un cas aussi fréquent et important que la génération de la production, nous introduisons des abstractions de telles facilités de communication. Ces installations ne font pas directement partie de la langue, mais sont des procédures déclarées dans certains modules (bibliothèque), auxquels tous les programmes ont accès. Nous postulons des procédures de lecture et d'écriture comme montré dans l'exemple suivant, et supposons que les données sont ainsi lues à partir d'un clavier et écrites sur un affichage.

Textes.Scan (S); x: = S.i;

Textes.Scan (S); y: = S.i;

PENDANT x # y DO

SI x> y ALORS x: = x-y SINON y: = y-x FIN

FIN;

Texts.WriteInt (W, x, 6)

La procédure Scan scanne un texte d'entrée et lit un entier (non négatif) (S.i). La procédure WriteInt génère un entier tel que spécifié par son deuxième paramètre (x). Le troisième paramètre (6) indique le nombre de chiffres disponibles pour la représentation de cette valeur dans le texte de sortie. Les deux procédures sont extraites des Textes du module importé (bibliothèque) et utilisent un scanner S déclaré localement et un enregistreur W globalement déclaré, se connectant à une source d'entrée (le texte suivant la commande) et à un récepteur de sortie (le texte Log) importé de l'environnement Oberon. Les détails sont expliqués au chapitre 22 de ce tutoriel.

Dans la version suivante et finale, nous complétons notre texte pour qu'il devienne un véritable texte d'Oberon:

PROCÉDURE Gcd *;

VAR x, y: INTEGER; S: Textes.Scanner;

COMMENCER Textes.OpenScanner (S, Oberon.Par.text, Oberon.Par.pos);

Textes.Scan (S); x: = S.i; Texts.WriteString (W, "x ="); Texts.WriteInt (W, x, 6);

Textes.Scan (S); y: = S.i; Texts.WriteString (W, "y ="); Texts.WriteInt (W, y, 6);

PENDANT x # y DO

SI x> y ALORS x: = x-y SINON y: = y-x FIN

FIN;

Texts.WriteString (W, "gcd ="); Texts.WriteInt (W, x, 6); Textes.WriteLn (W);

Textes.Append (Oberon.Log, W.buf)

END Gcd;

Les ajouts essentiels à cette étape sont les déclarations. Dans Oberon, tous les noms d'objets présents dans un programme, tels que les variables et les constantes, doivent être déclarés. Une déclaration introduit l'identifiant de l'objet (nom), spécifie le type de l'objet (qu'il s'agisse d'une variable, d'une constante ou autre) et indique les propriétés générales invariantes, telles que le type d'une variable ou la valeur d'une constante .

Le texte entier est appelé une procédure, donné un nom, et a le format suivant (voir aussi Ch. 10):

Nom de la procédure;

<déclarations> COMMENCER

<statements> END name;

Dans cet exemple et les suivants, une propriété particulière du système Oberon devient apparente. Alors que dans les langues anciennes, les notions de programme et d'unité exécutable étaient identiques, nous distinguons soigneusement entre elles dans la terminologie Oberon: Ce qu'on appelait un programme s'appelle maintenant un module, une unité système incorporant typiquement des variables et des instructions exécutables résidant dans un système (voir aussi Ch. 19). Les compilateurs acceptent un module comme une unité de texte compilable. Une unité exécutable de programme nous appelons une procédure. Dans le système Oberon, toute procédure sans paramètre peut être utilisée comme commande, si son nom est marqué d'un astérisque. Il peut être activé en cliquant sur son nom visible n'importe où sur l'écran. Un module peut contenir une ou plusieurs commandes. En conséquence, les exemples précédents et suivants de «programmes» apparaissent sous la forme de procédures (commandes), et nous supposerons toujours qu'ils sont intégrés dans un module important deux modules de service Textes et Oberon et contenant la déclaration d'un écrivain W pour la sortie:

MODULE Motif;

Textes d'importation, Oberon; VAR W: Textes.Writer;

Commande PROCEDURE *; (* tel que Gcd *) BEGIN ... (* en utilisant W pour la sortie *) ... Texts.Append (Oberon.Log, W.buf) END commande;

BEGIN Textes, modèle OpenWriter (W) END.

Quelques autres commentaires concernant notre exemple Gcd sont en ordre. Comme déjà mentionné, les procédures WriteLn, WriteString, WriteInt et Scan ne font pas partie du langage Oberon lui-même. Ils sont définis dans un module appelé Texts qui est supposé disponible. Les modules souvent rencontrés Textes, Fichiers et Oberon seront définis et expliqués au chapitre 22 de ce livre. Ici, nous soulignons simplement qu'ils doivent être importés pour être connus dans un programme. Ceci est fait en incluant les noms de ces modules dans la liste d'importation dans l'en-tête du module d'importation.

La procédure WriteString génère une chaîne, c'est-à-dire une séquence de caractères (entre guillemets). La procédure WriteLn insère un saut de ligne dans le texte de sortie. Pour plus d'explications, nous renvoyons aux chapitres 22.3 et 22.4 de ce livre:

Et ceci conclut la discussion de notre premier exemple. Il a été gardé assez informel. Ceci est admissible parce que le but était d'expliquer un programme existant. Cependant, la programmation est en train de concevoir, créant de nouveaux programmes. A cet effet, seule une description précise et formelle de notre outil est adéquate. Dans le chapitre suivant, nous introduisons un formalisme pour la description précise de textes de programme «légaux» corrects. Ce formalisme permet de déterminer de manière rigoureuse si un texte écrit répond aux règles du langage.

  1. Une notation pour décrire la syntaxe d'Oberon

Un langage formel est un ensemble infini de séquences de symboles. Les membres de cet ensemble sont appelés phrases, et dans le cas d'un langage de programmation, ces phrases sont des programmes. Les symboles sont tirés d'un ensemble fini appelé le vocabulaire. Puisque l'ensemble des programmes est infini, il ne peut pas être énuméré, mais est plutôt défini par des règles pour leur composition. Les séquences de symboles qui sont composées selon ces règles sont dites être des programmes syntaxiquement corrects; l'ensemble des règles est la syntaxe de la langue.

Les programmes dans une langue formelle correspondent alors à des phrases grammaticalement correctes de langues parlées. Chaque phrase a une structure et se compose de parties distinctes, telles que le sujet, l'objet et le prédicat. De même, un programme se compose de parties, appelées entités syntaxiques, telles que des instructions, des expressions ou des déclarations. Si une construction A est constituée de B suivie de C, c'est-à-dire de la concaténation BC, alors nous appelons les facteurs syntaxiques B et C et nous décrivons A par la formule syntaxique

A = BC.

Si, d'autre part, un A se compose d'un B ou, en variante, d'un C, nous appelons les termes syntaxiques B et C et exprimons A comme

A = B | C.

Les parenthèses peuvent être utilisées pour regrouper les termes et les facteurs. Il est à noter que A, B et C désignent ici des entités syntaxiques du langage formel à décrire, alors que les symboles =, | , les parenthèses et la période sont des symboles de la syntaxe descriptive de la méta-notation. Ces derniers sont appelés symboles méta, et la méta-notation introduite ici est appelée formalisme étendu Backus-Naur (EBNF).

En plus de la concaténation et du choix, EBNF permet également d'exprimer l'option et la répétition. Si une construction A peut être un B ou rien (vide), ceci est exprimé comme

A = [B].

et si un A consiste en la concaténation d'un nombre quelconque de Bs (y compris aucun), cela est noté A = {B}.

C'est tout ce qu'il y a à EBNF! Quelques exemples montrent comment les ensembles de phrases sont définis par les formules EBNF:

(A | B) (C | D) AC AD BC BD

A [B] C ABC AC

A {BA} A ABA ABABA ABABABA ...

{A | B} C CAC BC AAC ABC BAC BAC ...

Évidemment, EBNF est lui-même un langage formel. Si cela convient à son but, il doit au moins pouvoir se décrire! Dans la définition suivante de EBNF dans EBNF, nous utilisons les noms suivants pour les entités:

déclaration: une équation syntaxique

expression: une liste de termes alternatifs

terme: une concaténation de facteurs

facteur: une seule entité syntaxique ou une expression entre parenthèses

La définition formelle de EBNF est maintenant donnée comme suit:

syntaxe = {instruction}.

statement = identifier "=" expression ".". expression = terme {"|" terme}.

terme = facteur {facteur}.

facteur = identifiant | chaîne | "(" expression ")" | "[" expression "]" | "{" expression "}".

Les identificateurs désignent des entités syntaxiques; les chaînes sont des séquences de symboles tirées du vocabulaire de la langue définie. Pour la dénotation des identifiants, nous adoptons les conventions largement utilisées pour les langages de programmation, à savoir:

Un identifiant est constitué d'une suite de lettres et de chiffres, le premier caractère devant être une lettre. Une chaîne se compose de n'importe quelle séquence de caractères entre guillemets (ou apostrophes).

Une déclaration formelle de ces règles en termes de EBNF est donnée dans le chapitre suivant. 4. Représentation des programmes Oberon

Le chapitre précédent a introduit un formalisme par lequel les structures des programmes bien formés seront définies par la suite. Il définit, cependant, simplement la manière dont les programmes sont composés comme des séquences de symboles, contrairement aux séquences de caractères. Cette «lacune» est tout à fait intentionnelle: la représentation des symboles (et donc des programmes) en termes de caractères est considérée comme trop dépendante des implémentations individuelles pour le niveau général d'abstraction approprié pour une définition de langage. La création d'un niveau intermédiaire de représentation par des séquences de symboles fournit un découplage utile entre le langage et la représentation finale du programme. Ce dernier dépend du jeu de caractères disponible. En conséquence, nous devons postuler un ensemble de règles régissant la représentation des symboles en tant que séquences de caractères. Les symboles du vocabulaire Oberon sont répartis dans les classes suivantes:

identifiants, nombres, chaînes, opérateurs et délimiteurs, et commentaires.

Les règles régissant leur représentation en termes de jeu de caractères ISO standard sont les suivantes:

  1. Les identificateurs sont des séquences de lettres et de chiffres. Le premier caractère doit être une lettre. Les lettres majuscules et minuscules sont considérées comme distinctes.

identifiant = lettre {lettre | chiffre}.

Des exemples d'identifiants bien formés sont

Alice probablement sauter BlackBird SR71 Des exemples de mots qui ne sont pas des identifiants sont

preuve sonore (espace vide n'est pas autorisé)

insonorisé (ni un trait d'union)

2N (le premier caractère doit être une lettre)

Miller (pas d'apostrophe autorisée)


55