Section courante

A propos

Section administrative du site

Les premiers pas

Cette page est une introduction au langage de programmation SNOBOL. Elle décrit le format des instructions, certaines des opérations et certains des types de données gérés par le langage.

Un programme SNOBOL se compose d'une séquence d'instructions. Il existe quatre types d'instructions de base :

L'instruction end termine le programme.

Instruction d'affectation

Le type d'instruction le plus simple est l'instruction d'affectation. Elle se présente sous le format :

variable = valeur

On peut dire que l'instruction d'affectation a la signification suivante : «Soit la variable ayant la valeur donnée.» Par exemple, soit V ayant la valeur 5, ou :

  1. V = 5

La valeur peut être donnée par une expression, constituée, par exemple, d'opérations arithmétiques comme dans l'énoncé :

  1. W = 14 + (16 - 10)

attribuant la valeur 20 à la variable w. Des espaces sont requis autour des opérateurs arithmétiques tels que + et -. La valeur ne doit pas nécessairement être un entier, n'étant qu'un des types de données gérés par SNOBOL. Par exemple, la valeur peut être une chaîne de caractères, indiquée par des guillemets. Un exemple est l'instruction d'affectation :

  1. V = 'CHIEN'

affectant la chaîne de caractères CHIEN à la variable V. Différents types de données et d'opérations pouvant être effectuées sur celles-ci sont décrits plus loin.

En général, une variable est un nom tel que V, X ou ANS. Les variables apparaissant explicitement dans un programme doivent commencer par une lettre pouvant être suivie de n'importe quel nombre de lettres, de chiffres, de points et de traits de soulignement.

La valeur d'une variable peut être utilisée dans une instruction d'affectation. Ainsi :

  1. RESULT = ANS.1

attribue à la variable RESULT la valeur de ANS.1. (Les guillemets distinguent les chaînes de caractères littérales des variables.)

Les espaces sont obligatoires pour séparer les parties d'une instruction. Dans une instruction d'affectation, le signe égal doit être séparé de la variable de gauche et de la valeur de droite par au moins un espace.

Arithmétique

Entiers

Les opérations arithmétiques d'addition, de soustraction, de multiplication, de division et d'exponentielle d'entiers peuvent être utilisées dans des expressions. Les instructions :

  1. M = 4
  2. N = 5
  3. P = N * M / (N - 1)

attribuez la valeur 5 à P. Alors que des espaces sont nécessaires entre les opérateurs binaires et leurs opérandes, les opérateurs unaires tels que le signe moins doivent être adjacents à leurs opérandes. Un exemple est l'instruction :

  1. Q2 = -P / -N

attribuant la valeur 1 à Q2.

Les expressions arithmétiques peuvent être arbitrairement complexes. Lors de l'évaluation des expressions arithmétiques, l'ordre naturel de priorité des opérateurs s'applique. Les opérations unaires sont effectuées en premier, puis l'exponentielle (** ou !), puis la multiplication, suivie de la division, et enfin de l'addition et de la soustraction. Toutes les opérations arithmétiques s'associent à gauche, sauf l'exponentielle. Par conséquent :

  1. X = 2 ** 3 ** 2

est équivalent à :

  1. X2 = 2 ** (3 ** 2)

Les parenthèses peuvent être utilisées pour souligner ou modifier l'ordre d'évaluation d'une expression.

Dans les exemples ci-dessus, tous les opérandes sont des entiers et les résultats sont des entiers. Le quotient de deux entiers est également un entier. Le reste est ignoré. Ainsi :

  1. Q1 = 5/2
  2. Q2 = 5 / -2

donne à Q1 et Q2 les valeurs 2 et -2, respectivement.

Nombres réels

Les opérandes réels sont également autorisés dans les expressions arithmétiques. Les instructions :

  1. PI     = 3.14159
  2. CIRCUM = 2. * PI * 5.

attribue des valeurs réelles à PI et CIRCUM.

Si des nombres réels sont mélangés à des entiers dans des expressions arithmétiques, le résultat est un nombre réel. Par exemple, la valeur de :

  1. SUM = 16.4 + 2

est 18.4.

Chaînes de caractères

Les expressions impliquant des opérandes étant des chaînes de caractères sont également autorisées dans les instructions d'affectation. Par exemple, l'instruction d'affectation :

  1. SCREAM = 'AIDE'

attribue la chaîne de caractères HELP comme valeur de SCREAM.

La chaîne de caractères est spécifiée en l'entourant d'une paire de guillemets. N'importe quel caractère peut apparaître dans une chaîne de caractères. Une paire de guillemets doubles peut être utilisée à la place des guillemets simples. Cela permet d'utiliser des guillemets dans une chaîne de caractères comme dans les instructions :

  1. PLEA       = 'IL A CRIÉ : AU SECOURS.'
  2. QUOTE      = '"'
  3. APOSTROPHE = ","

Des guillemets simples sont utilisés dans les exemples donnés dans cette page lorsqu'un seul type de guillemet est suffisant.

La chaîne de caractères nulle

La chaîne de caractères nulle, étant une chaîne de longueur zéro, est fréquemment utilisée dans SNOBOL. À quelques exceptions près, expliquées plus loin, toutes les variables ont la chaîne de caractères nulle comme valeur initiale. Une variable peut également se voir attribuer la chaîne de caractères nulle par une instruction comme :

  1. NULL =

ou, plus brièvement :

  1. NULL =

La variable NULL est utilisée dans de nombreux exemples suivant pour représenter la chaîne de caractères nulle. La chaîne de caractères nulle est différente des chaînes de caractères suivantes, dont chacune a une longueur de un :

  1. '0'
  2. ' '

Chaînes de caractères dans les expressions arithmétiques

Les chaînes de caractères numériques peuvent être utilisées dans des expressions arithmétiques avec des nombres entiers et réels. Par exemple, à la suite des instructions :

  1. Z = '10'
  2. X = 5 * -Z + '10.6'     

X a la valeur -39,4. Les chaînes de caractères numériques représentant des entiers ne peuvent contenir que des chiffres et un signe de préfixe facultatif. Les chaînes de caractères numériques représentant des nombres réels doivent avoir au moins un chiffre avant la virgule décimale. Ainsi, les chaînes de caractères suivantes ne peuvent pas être utilisées dans des expressions arithmétiques :

  1. '1,253,465'
  2. '.364 E-03'

La chaîne de caractères nulle est équivalente à l'entier zéro dans les expressions arithmétiques.

Expressions à valeur de chaîne de caractères

La concaténation est l'opération de base permettant de combiner deux chaînes de caractères pour en former une troisième. Les instructions suivantes illustrent le format d'une expression impliquant une concaténation.

  1. TYPE   = 'SEMI'
  2. OBJECT = TYPE 'GROUPE'     

La valeur résultante de OBJECT est la chaîne de caractères SEMIGROUPE. Notez qu'il n'existe pas d'opérateur explicite pour la concaténation. La concaténation est indiquée en spécifiant deux opérandes de valeur chaîne de caractères séparés par au moins un espace.

  1. FIRST        = 'HIVER'
  2. SECOND       = 'ETE'
  3. TWO.SEASONS  = FIRST ',' SECOND

sont équivalents à :

  1. TWO.SEASONS = 'HIVER,ETE'

Les chaînes de caractères peuvent également être concaténées avec des nombres réels et des entiers comme dans :

  1. ROW  = 'K'
  2. NO.  = 22
  3. SEAT = ROW NO.

ce qui donne à SEAT la valeur K22.

Dans une expression impliquant une concaténation et des opérations arithmétiques, la concaténation a la priorité la plus basse. Ainsi :

  1. SEAT = ROW NO. + 4 / 2

est équivalent à :

  1. SEAT = ROW (NO. + (4 / 2))

ou :

  1. SEAT = 'K24'

Entrée et sortie de chaînes de caractères

Trois variables permettent de lire et d'écrire des données. Les variables OUTPUT et PUNCH servent à afficher et à perforer. Chaque fois qu'une chaîne de caractères, un entier ou une valeur réelle est attribué à l'une d'elles, une copie de la valeur est émise :

  1. OUTPUT = 'LES RÉSULTATS SONT :'

attribue LES RÉSULTATS SONT : à OUTPUT et l'affiche également.

  1. PUNCH = OUTPUT

provoque la perforation de la même ligne sur une carte. Les déclarations :

  1. OUTPUT = 
  2. PUNCH =

provoque l'impression d'une ligne vierge et le poinçonnage d'une carte vierge.

La variable <INPUT> est utilisée pour la lecture de chaînes de caractères. Chaque fois que la valeur de <INPUT> est requise dans une instruction, une autre carte est lue et la chaîne de 80 caractères qu'elle contient est affectée comme valeur de INPUT. Ainsi :

  1. PUNCH = INPUT

perfore une copie de la carte d'entrée.

Les cartes de données à lire apparaissent immédiatement après l'instruction end terminant le programme.

Déclarations de correspondance de motifs

L'opération d'examen des chaînes de caractères pour l'occurrence de sous-chaînes spécifiées (c'est-à-dire la correspondance de motifs) est fondamentale pour le langage SNOBOL. La correspondance de motifs peut être spécifiée dans deux types d'instructions :

L'instruction de correspondance de motifs se présente sous le format :

sujet motif

où les deux champs sont séparés par au moins un espace. Le sujet spécifie une chaîne de caractères à examiner et le motif peut être considéré comme spécifiant un ensemble de chaînes de caractères. L'instruction entraîne l'analyse de la chaîne de caractères du sujet à partir de la gauche pour rechercher l'occurrence d'une chaîne spécifiée par le motif.

Si :

  1. TRADE 'PROGRAMMEUR'

l'instruction :

  1. TRADE 'GRAM'

examine la valeur de TRADE pour une occurrence de GRAM. Si :

  1. PART = 'GRAM'

alors une déclaration équivalente est :

  1. TRADE PART

L'exemple suivant illustre une instruction de recherche de modèle dans laquelle le modèle est une expression de valeur de chaîne de caractères.

  1. ROW    =  'K'
  2. NO.    = 20
  3. 'K24 '  ROW NO. + 4

Le sujet est un littéral et la valeur de l'expression est la chaîne de caractères K2'1. Notez qu'il n'existe pas d'opérateur de correspondance de motif explicite entre le sujet et le motif. Les deux champs sont séparés par des espaces.

Si une concaténation est nécessaire dans le sujet, l'expression doit être placée entre parenthèses pour éviter toute ambiguïté. Un exemple est :

  1. TENS       = 2
  2. UNITS      = 5
  3. (TENS UNITS) 30

En revanche, un motif formé par concaténation n'a pas besoin de parenthèses. Les instructions suivantes sont équivalentes :

  1. TENS UNITS 30
  2.  
  3. TENS (UNITS 30)

Déclarations de remplacement

Une déclaration de remplacement se présente sous le format suivant :

subject pattern = object

où les champs sont séparés par au moins un espace. La recherche de correspondance de motifs est effectuée comme dans l'instruction de recherche de correspondance de motifs. Si l'opération de recherche de correspondance de motifs réussit, la chaîne d'objet est modifiée en remplaçant la sous-chaîne de caractères correspondante par l'objet. Par exemple, si :

  1. WORD = 'GIRD'

puis l'instruction de remplacement :

  1. WORD 'I' = 'OU'

provoque l'analyse de la chaîne sujet GIRD pour la chaîne I, puis, comme le modèle correspond, I est remplacé par OU. Par conséquent, WORD a comme valeur la chaîne de caractères GOURD. Si l'instruction est :

  1. WORD 'AB' = 'OU'

la valeur de WORD ne change pas car le modèle ne correspond pas.

Un autre exemple d'utilisation d'instructions de remplacement est donné dans la séquence d'instructions suivante :

  1. HAND   = 'AC4DAHKDKS'
  2. RANK   = 4
  3. SUIT   = 'D'
  4. HAND  RANK SUIT = 'AS'     

remplaçant la sous-chaîne 4D par la chaîne de caractères AS.

Une sous-chaîne de caractères correspondante est supprimée de la chaîne sujet si l'objet dans l'instruction de remplacement est la chaîne de caractères nulle. Ainsi :

  1. HAND  RANK SUIT =

supprime 4D de HAND en lui laissant la chaîne de caractères ACAHKDKS comme valeur.

Motifs

Les motifs des exemples précédents spécifient des chaînes de caractères simples. Il est également possible de spécifier des motifs plus complexes. Deux opérations sont disponibles pour construire de tels motifs :

L'alternance est indiquée par une expression dans le format :

P1 | P2

où les deux motifs P1 et P2 sont séparés du | par des espaces. La valeur de l'expression est une structure de motif correspondant à toute chaîne de caractères spécifiée par P1 ou P2. Par exemple, l'instruction :

  1. KEYWORD = 'COMPUTER' | 'PROGRAM'

attribue à KEYWORD une structure de modèle correspondant à l'une de ces deux chaînes de caractères. Par la suite, KEYWORD peut être utilisé partout où les modèles sont autorisés. Par exemple :

  1. KEYWORD = KEYWORD | 'ALGORITHM'

donne à KEYWORD une nouvelle valeur de modèle équivalente à la valeur attribuée en exécutant l'instruction :

  1. KEYWORD = KEYWORD | 'ALGORITHM'

En utilisant KEYWORD dans le champ de modèle, l'instruction :

  1. TEXT KEYWORD =

examine la valeur de TEXT à partir de la gauche et supprime la première occurrence de l'une des chaînes de caractères alternatives. Si :

  1. TEXT = 'PROGRAMMING ALGORITHMS FOR COMPUTERS'

le résultat de l'instruction de remplacement est comme si l'instruction suivante était exécutée :

  1. TEXT = 'PROGRAMMING ALGORITHMS FOR COMPUTERS'

La concaténation de deux motifs, P1 et P2, est spécifiée de la même manière que la concaténation de deux chaînes de caractères :

  1. P1 P2

Autrement dit, les deux modèles sont séparés par des espaces. La valeur de l'expression est un modèle correspondant à une chaîne de caractères composée de deux sous-chaînes de caractères, la première correspondant à P1, la seconde correspondant à P2. Par exemple, si :

  1. BASE      = 'BINARY' | 'DECIMAL' | 'HEX'
  2. SCALE     = 'FIXED' | 'FLOAT'
  3. ATTRIBUTE = SCALE BASE     

Et :

  1. DCL = 'AREAFIXEDDECIMAL'

alors la correspondance de modèle réussit dans l'instruction :

  1. DCL ATTRIBUTE

La concaténation a une priorité plus élevée que l'alternance. Ainsi :

  1. ATTRIBUTE = 'FIXED' | 'FLOAT' 'DECIMAL'

correspond à FIXED ou FLOATDECIMAL. L'ordre d'évaluation peut être modifié en utilisant des parenthèses.

  1. ATTRIBUTE = ('FIXED' | 'FLOAT') 'DECIMAL'

correspondent à FIXED ou FLOATDECIMAL. L'ordre d'évaluation peut être modifié en utilisant des parenthèses.

Affectation de valeur conditionnelle

Il est possible d'associer une variable à une composante d'un modèle de telle sorte que si le modèle correspond, la sous-chaîne de caractères correspondant au composante soit attribuée à la variable. L'opérateur «.» est l'opérateur d'affectation de valeur conditionnelle et il est utilisé dans une expression du format :

motif . variable

où l'opérateur est séparé de ses opérandes par des espaces. Par exemple :

  1. BASE = ('HEX' | ' DEC') . B1

affecte à BASE un modèle correspondant soit à HEX, soit à DEC. Si BASE est utilisé avec succès dans une correspondance de modèle, la valeur de B1 est définie sur la sous-chaîne correspondant à BASE.

L'opérateur s'associe à gauche et a une priorité plus élevée que la concaténation et l'alternance.

  1. A.OR.B = A | B . OUTPUT

est équivalent à :

  1. A.OR.B = A | (B . OUTPUT)

attribuant à A. OU .B un modèle correspondant à la valeur de A ou B. Si B correspond, la sous-chaîne de caractères correspondante est affichée.

Il existe également un opérateur $ pour l'affectation de valeur immédiate affectant une valeur à une variable si la composante associé du modèle correspond, que le modèle entier corresponde ou non.

Flux de contrôle

Un programme SNOBOL est une séquence d'instructions terminée par une instruction end. Les instructions sont exécutées séquentiellement, sauf indication contraire dans le programme. Des étiquettes et des goto sont fournis pour contrôler le flux du programme.

Une instruction peut commencer par une étiquette d'identification, permettant le transfert vers l'instruction. Par exemple, l'instruction d'affectation :

  1. START TEXT = INPUT

a pour étiquette START. Une étiquette se compose d'une lettre ou d'un chiffre suivi d'un nombre quelconque d'autres caractères jusqu'à un espace. Les espaces séparent l'étiquette du sujet. Une instruction sans étiquette doit commencer par au moins un espace. L'instruction de fin se distingue par l'étiquette END, indiquant la fin du programme.

Le transfert vers une instruction étiquetée est spécifié dans le champ goto pouvant apparaître à la fin d'une instruction et est séparé du reste de l'instruction par deux points. Deux types de transferts peuvent être spécifiés dans le champ goto : conditionnel et inconditionnel.

Un transfert conditionnel se compose d'une étiquette entre parenthèses précédée d'un F ou d'un S correspondant à l'échec ou au succès. Un exemple est l'instruction :

  1. TEXT  =  INPUT  :F(DONE)     

Cette instruction provoque la lecture d'un enregistrement et son affectation comme valeur de TEXT. Si, toutefois, il n'y a pas de données dans le fichier d'entrée, c'est-à-dire si une fin de fichier est rencontrée, aucune nouvelle valeur n'est affectée à TEXT. Ensuite, en raison de l'échec de lecture, le transfert est effectué vers l'instruction étiquetée DONE.

Une utilisation de la réussite goto est illustrée dans le programme suivant perforant une copie du fichier d'entrée :

  1. LOOP    PUNCH   =   INPUT   :S(LOOP)     
  2. END

La première instruction est exécutée de manière répétée jusqu'à ce que la fin du fichier soit atteinte. Le programme passe ensuite à l'instruction end, ce qui provoque l'arrêt du programme.

La réussite ou l'échec d'une correspondance de modèle peut également être utilisé pour contrôler le déroulement d'un programme par des goto conditionnels. Par exemple :

  1.        COLOR = 'RED' | 'GREEN' | 'BLUE'
  2. BRIGHT TEXT COLOR = :S(BRIGHT)F(BLAND)
  3. BLAND     

Toutes les occurrences des chaînes de caractères RED, GREEN et BLUE sont supprimées de la valeur de TEXT avant que le modèle ne soit plus compatible. Le contrôle passe alors à l'instruction intitulée BLAND. Les valeurs de réussite et d'échec peuvent être spécifiées dans un champ goto et peuvent apparaître dans n'importe quel ordre.

Un transfert inconditionnel est indiqué par l'absence d'un F ou d'un S avant les parenthèses l'entourant. Pour un exemple de transfert inconditionnel, considérez le programme suivant perforant et répertoriant un ensemble de cartes.

  1. LOOP   PUNCH  = INPUT    :F(END)
  2.        OUTPUT = PUNCH    :(LOOP)
  3. END     

Le champ goto dans la deuxième instruction spécifie un transfert inconditionnel.

Référence indirecte

Le référencement indirect est indiqué par l'opérateur unaire $. Par exemple, si :

  1. MONTH = 'APRIL'

alors $MONTH est équivalent à APRIL. C'est-à-dire, l'instruction :

  1. $MONTH = 'CRUEL'

est équivalent à :

  1. APRIL = 'CRUEL'

L'opérateur de référence indirecte peut également être appliqué à une expression entre parenthèses comme dans les instructions :

  1. WORD = 'RUN'
  2. $(WORD ':') = $(WORD ':') + 1

incrémentant la valeur de RUN: .

En général, l'opérateur unaire $ génère une variable étant la valeur de son opérande. L'expression :

  1. $( 'A' | 'B')

est erronée car la valeur de l'opérande de $ est un motif, pas une chaîne de caractères. Une référence indirecte dans un goto est démontrée par :

  1. N = N + 1 :($('PHASE' N))

Si, par exemple, l'instruction d'affectation définit N égal à 5', alors le transfert s'effectue vers l'instruction intitulée PHASE5.

Fonctions

De nombreuses procédures SNOBOL sont appelées par des fonctions intégrées au système, appelées fonctions primitives. Les opérations se produisant fréquemment sont implémentées sous forme de fonctions primitives pour des raisons d'efficacité. D'autres fonctions primitives sont utilisées pour appeler des opérations plus complexes étant fondamentales pour le langage, affectent les paramètres et les tables internes au système et effectuent des opérations ne pouvant pas être programmées dans le langage source par d'autres moyens. De plus, des fonctionnalités sont disponibles pour qu'un programmeur puisse définir ses propres fonctions dans le langage de programmation source.

Fonctions primitives

La fonction primitive SIZE possède un seul paramètre de chaîne de caractères et renvoie comme valeur un entier correspondant à la longueur (nombre de caractères) de la chaîne de caractères. Les instructions :

  1. APE   = 'SIMIAN'
  2. OUTPUT = SIZE(APE)

affiche le numéro 6.

Les paramètres de toutes les fonctions sont transmis par valeur, et une expression arbitrairement complexe peut être utilisée dans le paramètre. Ainsi, les instructions :

  1. N      = 100
  2. OUTPUT = SIZE('PART' N + 4)

affiche le nombre 7, car la valeur du paramètre est la chaîne PART104.

Le paramètre de SIZE est censé être une chaîne de caractères. Par conséquent, un appel de la forme :

  1. SIZE( 'APE' | 'MONKEY')     

est erronée car la valeur de l'argument est un motif.

DUPL est une autre fonction effectuant une opération fréquemment requise. DUPL (string, integer) renvoie comme valeur une chaîne de caractères composée d'un certain nombre de duplications du paramètre string. La valeur de :

  1. DUPL('/*', 5)

est /*/*/*/*/*. DUPL renvoie la chaîne de caractères nulle si le deuxième paramètre est nul et échoue s'il est négatif. L'instruction :

  1. OUTPUT   =   DUPL(' ',40 - SIZE(S))   S

affiche la chaîne de caractères S justifiée à droite dans la colonne 40 si sa longueur n'est pas supérieure à 40. Sinon, l'instruction échoue et S n'est pas affichée.

REPLACE est une fonction appelée avec trois paramètres de valeur de chaîne de caractères :

  1. REPLACE(TEXT,CH1,CH2)

renvoie comme valeur une chaîne de caractère étant la même que TEXT, sauf que chaque occurrence d'un caractère apparaissant dans CH 1 est remplacée par le caractère correspondant dans CH2. Par exemple, les instructions :

  1. STATEMENT = 'A(I,J) = A(I,J) + 3'
  2. OUTPUT    = REPLACE(STATEMENT, '()', '<>')

affichera la ligne :

A<I,J> = A<I,J> + 3

Si les deux derniers paramètres de l'appel de fonction n'ont pas la même longueur, la fonction échoue. L'échec de fonction, comme l'échec d'entrée, peut être utilisé dans un transfert conditionnel.

Il existe également plusieurs fonctions renvoyant des motifs comme valeurs. LEN est une telle fonction. LEN(entier) renvoie un motif correspondant à n'importe quelle chaîne de caractères de la longueur spécifiée par l'entier.

L'exemple suivant perfore une carte avec les 40 premiers caractères d'une carte lue :

  1. INPUT LEN(40) . PUNCH

Prédicats

Un prédicat est une fonction ou une opération renvoyant la chaîne de caractères nulle comme valeur si une condition donnée est satisfaite. Sinon, elle échoue.

LE est un exemple de prédicat utilisé pour comparer des nombres :

  1. LE(N1 ,N2)

renvoie la chaîne de caractères nulle comme valeur si N1 est un nombre inférieur ou égal à N2. N1 et N2 peuvent être des entiers ou des réels. Ainsi :

  1. PUNCH = LE(SIZE(TEXT),80) TEXT

perfore la chaîne de caractères TEXT si sa longueur n'est pas supérieure à 80. La valeur de chaîne de caractères nulle du prédicat n'affecte pas la chaîne de caractères étant perforée. Si le prédicat échoue, aucune affectation n'est effectuée sur PUNCH et aucune carte n'est perforée.

La réussite ou l'échec d'un prédicat peut être utilisé avec un goto conditionnel pour contrôler le flux d'un programme. Par exemple :

  1.         SUM    = 0
  2.         N      = 0
  3. ADD     N      = LT(N,50) N + 1    :F(DONE)
  4.         SUM    = SUM + N           :(ADD)
  5. DONE    OUTPUT = SUM

additionne les 50 premiers entiers. L'itération continue tant que N est inférieur à 50. Lorsque le prédicat échoue, le transfert conditionnel vers DONE est effectué et la chaîne de caractères 1275 est affichée.

Il existe plusieurs prédicats pour comparer des objets de données. Par exemple :

  1. DIFFER(ST1,ST2)

renvoie la chaîne de caractères nulle comme valeur si les valeurs des deux paramètres ne sont pas identiques. Ainsi :

  1. OUTPUT = DIFFER(FIRST,SECOND) FIRST SECOND

concatène les valeurs de FIRST et SECOND si elles ne sont pas identiques, puis les affiche. Le prédicat IDENT est l'inverse de DIFFER. IDENT échoue si les valeurs de ses paramètres ne sont pas identiques.

Pour toutes les fonctions, un paramètre omis est supposé être la chaîne de caractères nulle. Ainsi :

  1. PUNCH = DIFFER(TEXT) TEXT

frappe la valeur de TEXT si ce n'est pas la chaîne de caractères nulle.

LGT est un prédicat comparant lexicalement deux chaînes de caractères :

  1. LGT(ST1,ST2)

réussit si ST1 suit (est lexicalement supérieur à) ST2 dans l'ordre alphabétique. Les énoncés :

  1.        OUTPUT   = LGT(TEXT1,TEXT2) TEXT2         :S(SKIP)
  2.        OUTPUT   = TEXT1
  3.        OUTPUT   = TEXT2                          :(JUMP)
  4. SKIP   OUTPUT   = TEXT1
  5. JUMP

affichera les valeurs de TEXT1 et TEXT2 par ordre alphabétique.

Fonctions définies

Le langage de programmation SNOBOL offre au programmeur la possibilité de définir des fonctions dans le langage de programmation source. Cette fonctionnalité facilite l'organisation d'un programme et peut améliorer son efficacité.

Un programmeur peut définir une fonction en exécutant la fonction primitive DEFINE pour spécifier le nom de la fonction, les paramètres formels, les variables locales et le point d'entrée de la fonction. Le point d'entrée est l'étiquette de la première instruction SNOBOL constituant la procédure de la fonction.

Le premier paramètre de DEFINE est un prototype décrivant la forme de l'appel de fonction. Le deuxième paramètre est le point d'entrée. Par exemple, l'exécution de l'instruction :

  1. DEFINE('DELETE(STRING,CHAR)','D1')

définit une fonction DELETE ayant deux paramètres formels, STRING et CHAR, et un point d'entrée D1. Les instructions :

  1. D1 STRING CHAR  =    : S(D1)
  2.    DELETE   = STRING  :(RETURN)

forme une procédure supprimant toutes les occurrences de CHAR de la valeur de STRING. L'instruction affectant la valeur résultante à la variable DELETE illustre la convention SNOBOL pour renvoyer une valeur de fonction. Le nom de la fonction peut être utilisé comme variable dans la procédure de fonction. Sa valeur au retour de la procédure est la valeur de l'appel de fonction. Le retour d'une procédure s'effectue par transfert vers l'étiquette système RETURN.

Si le deuxième paramètre est omis de l'appel de DEFINE, le point d'entrée de la procédure est considéré comme étant le même que le nom de la fonction. Par exemple :

  1. DEFINE('DELETE(STRING,CHAR)')

pourrait avoir la procédure :

  1. DELETE STRING CHAR   =    :S(DELETE)
  2.        DELETE   =  STRING :(RETURN)

Un appel de la fonction est illustré dans les instructions suivantes :

  1. MAGIC  = 'ABRACADABRA'
  2. OUTPUT = DELETE (MAGIC, 'A')

affichant BRCDBR.

Les paramètres sont transmis par valeur et peuvent être des expressions arbitrairement complexes. Ainsi, l'instruction :

  1. TEXT = DELETE(DELETE(INPUT,'.'),' ')

supprime tous les points et espaces de la chaîne de caractères d'entrée.

Les fonctions peuvent également échouer dans certaines conditions. À titre d'exemple, considérons la version suivante de DELETE, échouant si STRING ne contient pas d'occurrence de CHAR.

  1. DELETE STRING  CHAR  =      :F(FRETURN)
  2. D2     STRING  CHAR  =      :S(D2)
  3.        DELETE  =   STRING   :(RETURN)

Le transfert vers l'étiquette système FRETURN indique l'échec de l'appel de fonction. Par conséquent :

  1. PUNCH = DELETE(INPUT, '*')

perfore une carte uniquement si la chaîne d'entrée contient un *.

Les paramètres d'une fonction et la valeur renvoyée peuvent être n'importe quel type d'objet de données. Considérons, par exemple, la fonction MAXNO où MAXNO(p, N) renvoie un motif correspondant à un maximum de N chaînes de caractères adjacentes correspondant au motif P. C'est-à-dire, si :

  1. PAT MAXNO('A' | 'B' | 'C' ,2)

puis dans la déclaration :

  1. 'EBCDIC' PAT 'D'

la correspondance du modèle réussit avec PAT correspondant à la chaîne de caractères BC.

MAXNO a la déclaration déterminante :

  1. DEFINE('MAXNO(P,N)')

et la procédure :

  1. MAXNO N     = GT(N,0) N - 1        :F(RETURN)
  2.       MAXNO = NULL | P MAXNO       :(MAXNO)

Considérez la fonction REVERSE inversant une chaîne de caractères. Elle contient l'instruction de définition suivante :

  1. DEFINE('REVERSE(STRING)', 'R1')

et la procédure :

  1. R1  ONECH  = LEN(1) . CH
  2. R2  STRING ONECH =        :F(RETURN)
  3.     REVERSE = CH REVERSE  :(R2)

Il existe deux variables, ONECH et CH, utilisées dans la définition de la fonction en plus du nom de la fonction et du paramètre formel. Il est prudent de protéger ces variables afin que leur utilisation en dehors de la fonction ne soit pas affectée lorsque la fonction est appelée. Pour ce faire, il suffit de les déclarer comme variables locales dans l'instruction de définition :

  1. DEFINE('REVERSE(STRING)ONECH,CH' ,'R1')

Lorsque la fonction est appelée, les valeurs actuelles du nom de la fonction, les arguments formels et les variables locales sont sauvegardées avant l'entrée dans la procédure. Ces valeurs sont restaurées au retour de la procédure. Cela donne au programmeur une liberté considérable dans la définition des fonctions. Par exemple, une fonction peut être récursive, c'est-à-dire inclure un appel de la fonction elle-même. Considérons le coefficient binomial c(n, m) pouvant être défini par les équations :

c(n,0) = 1
c(n,m) = n*c(n-1 ,m-1)/m pour m > 0

L'efficacité du calcul peut être améliorée en utilisant la relation :

c(n,m) = c(n,n-m)
pour m > n/2.

La fonction correspondante définie par le programmeur se compose de l'instruction de définition :

  1. DEFINE('C(N,M)')

et la procédure :

  1. C      M  =  LT(N - M,M) N - M
  2.        C  =  EQ (M, 0) 1                  :S(RETURN)
  3.        C  =  N * C(N - 1,M - 1) / M       :(RETURN)

COMB est un exemple d'une autre fonction définie de manière récursive. COMB(STR, N) répertorie toutes les combinaisons de N caractères de la chaîne de caractères STR. L'instruction et la procédure de définition sont les suivantes :

  1. DEFINE('COMB(STR,N,HEAD)CH')     

et :

  1. COMB  OUTPUT =    EQ(N,0) HEAD            :S(RETURN)
  2. C2    STR LE(N,SIZE(STR)) LEN(1) . CH =   :F(RETURN)
  3.       COMB(STR,N - 1,HEAD CH) :(C2)

Alors :

  1. COMB( 'ABCD', 3)

il affichera :

ABC
ABD
ACD
BCD

Notez que COMB est défini avec trois paramètres formels mais que seules deux valeurs sont fournies dans l'appel initial. La valeur manquante est considérée comme nulle.

Mots-clefs

Plusieurs paramètres et commutateurs internes au système SNOBOL sont accessibles au moyen de mots-clefs. Les mots-clefs sont spécifiés en préfixant certains identificateurs par une esperluette. Par exemple, si la valeur du mot-clef &DUMP est un entier différent de zéro lorsqu'un programme se termine, un vidage des variables naturelles est affiché. Ainsi, l'exécution de l'instruction :

  1. &DUMP = 1

indique qu'un vidage doit être produit.

Les chaînes de caractères lues par INPUT ont une longueur de 80 caractères. De telles chaînes contiennent souvent de nombreux espaces de fin indésirables. &TRIM est un mot clef contrôlant la gestion des espaces de fin lors de l'entrée de données. Si la valeur de &TRIM est différente de zéro, les espaces de fin sont supprimés. Ainsi :

  1. &TRIM = 1

provoque la suppression des espaces de fin. Si &TRIM est nul, les espaces de fin ne sont pas supprimés.

Tableaux

Les tableaux de variables peuvent être créés à l'aide de la fonction primitive ARRAY. Les paramètres de ARRAY décrivent le nombre de dimensions, les limites de chaque dimension et la valeur initiale de chaque variable du tableau. Ainsi :

  1. V = ARRAY(10,1.0)

crée et affecte à V un tableau unidimensionnel de dix variables, chacune initialisée à la valeur réelle 1.0. Les variables créées peuvent être référencées par des expressions de la forme V<I> où I = 1, ..., 10. L'instruction :

  1. N = ARRAY('3,5')

crée un tableau bidimensionnel de variables :

N<1,1>   N<1,2>   N<1,3>   N<1,4>  N<1,5>
<2,1>     .        .         .      .
<3,1>     .        .         .     N<3,5>

L'omission du deuxième paramètre fait que chacune des variables a la chaîne de caractères nulle comme valeur initiale. Les paramètres dans l'appel de ARRAY peuvent être des expressions. Ainsi :

  1. &TRIM = 1
  2. A = ARRAY(INPUT)

créer un tableau avec une dimensionnalité dépendante des données. Une référence de tableau, A<I>, se trouvant en dehors des limites du tableau provoque une erreur pouvant être utilisée pour contrôler le déroulement du programme. Les instructions :

  1.      &TRIM = 1
  2.      I     = 1
  3.      ST    = ARRAY(INPUT)
  4. MORE ST<I> = INPUT             :F(GO)
  5.      I     = I + 1             :(MORE)
  6. GO

générer un tableau ST et affecter des valeurs à chacune des variables. Lorsque des valeurs sont affectées à toutes les variables du tableau ou qu'une fin de fichier est rencontrée, le transfert vers GO est exécuté.

Tables

Des ensembles de paires d'objets de données associés peuvent être créés à l'aide de tables. Une table est similaire à un tableau unidimensionnel. Cependant, au lieu de référencer un élément avec un entier, n'importe quel objet de données peut être utilisé.

Une table est créée par la fonction primitive TABLE. Par exemple :

  1. T = TABLE()

crée un tableau et lui attribue la valeur T.

Des valeurs peuvent être attribuées aux éléments du tableau de la même manière que les éléments d'un tableau. En voici quelques exemples :

  1. T<'A'> = 5

et :

  1. T<WORD> = T<WORD> + 1

Les tables ont des longueurs variables et sont étendues de manière dynamique si nécessaire. Une certaine efficacité peut être obtenue en spécifiant une estimation de la taille d'une table au moment de sa création. TABLE (N) crée une table ayant initialement de la place pour N entrées.

Types de données définis par le programmeur

Les entiers, les nombres réels, les chaînes de caractères, les motifs, les tableaux et les tables sont des types d'objets de données intégrés au langage de programmation SNOBOL. Des fonctionnalités sont fournies dans le langage pour permettre à un programmeur de définir des types de données supplémentaires. Cela facilite la représentation des relations structurelles inhérentes aux données.

Par exemple, une liste chaînée linéaire simple est composée de noeuds, chacun contenant un champ de valeur et un champ de lien.

La fonction primitive DATA peut être utilisée pour définir le type de données NODE et les deux fonctions de champ, VALUE et LINK.

  1. DATA('NODE(VALUE,LINK)')

La déclaration :

  1. P = NODE('S ',)

crée un noeud avec le champ de valeur S et la chaîne de caractères nulle dans le champ de lien. La valeur de P est un objet de données avec deux champs pouvant être référencés au moyen des appels de fonction VALUE(p) et LINK(p). L'insertion d'un noeud avec la valeur T en tête de la liste est réalisée par l'instruction :

  1. P = NODE ('T',P)

L'instruction suivante supprime un noeud de la tête de la liste :

  1. P = LINK(P)

Format du programme

Une instruction dépassant une ligne peut être poursuivie sur plusieurs lignes successives en commençant les lignes de continuation par un point ou un signe plus. Voici un exemple :

  1.            OUTPUT = 'LE NOMBRE TOTAL D"OCCURRENCES EST '
  2. + SUM<N>

Les signes plus sont utilisés pour la continuation dans les exemples de cette page. Lorsque l'on continue une instruction au-delà d'une limite de ligne, l'instruction peut être coupée à chaque fois qu'un espace est requis.

Plusieurs instructions peuvent être placées sur une ligne en utilisant des points-virgules indiquant la fin des instructions. En voici un exemple :

  1. x = 2; Y = 3; Z  = 10

Une ligne commençant par un astérisque est traitée comme un commentaire et n'affecte pas le fonctionnement du programme.

Exemple de programme

Voici un exemple d'un programme SNOBOL complet illustrant l'utilisation de lignes de commentaires, de lignes de continuation et de l'instruction de fin. Le programme lit les cartes de données suivant l'instruction de fin :

  1. ************************************************************************
  2. *                                                                      *
  3. *         CE PROGRAMME COMPTE LE NOMBRE DE FOIS QUE CHAQUE             *
  4. *         LETTRE EST UTILISÉE DANS LE TEXTE D'ENTRÉE.                  *
  5. *                                                                      *
  6. ************************************************************************
  7.           &TRIM     =  1
  8.           CHAR      =  LEN(1) . CH
  9.           LETTERS   =  'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  10.           COUNT     =  TABLE(30)
  11. READ      OUTPUT    =  INPUT                       :F(DISPLAY)
  12.           TEXT      =  OUTPUT
  13. NEXT      TEXT    CHAR =                           :F(READ)
  14.           COUNT<CH> =  COUNT<CH> + 1               :(NEXT)
  15. DISPLAY   OUTPUT    =
  16. LOOP      LETTERS   CHAR =                         :F(END)
  17.           OUTPUT    = NE(COUNT<CH>)  CH ' SE PRODUIT ' COUNT<CH> ' FOIS'
  18. +                                                  :(LOOP)
  19. END

La sortie du programme suit, indiquant le texte lu et le nombre de lettres résultant : «Le monde du futur sera une lutte toujours plus exigeante contre les limites de notre intelligence»,..., N.Weiner.

A SE PRODUIT 5 FOIS
B SE PRODUIT 1 FOIS
C SE PRODUIT 1 FOIS
D SE PRODUIT 3 FOIS
E SE PRODUIT 15 FOIS
F SE PRODUIT 3 FOIS
G SE PRODUIT 5 FOIS
H SE PRODUIT 3 FOIS
I SE PRODUIT 9 FOIS
L SE PRODUIT 7 FOIS
M SE PRODUIT 3 FOIS
N SE PRODUIT 9 FOIS
0 SE PRODUIT 6 FOIS
R SE PRODUIT 7 FOIS
S SE PRODUIT 3 FOIS
T SE PRODUIT 9 FOIS
U SE PRODUIT 4 FOIS
V SE PRODUIT 1 FOIS
W SE PRODUIT 3 FOIS


Dernière mise à jour : Mardi, le 3 décembre 2024