1.2.1 Syntaxe Scheme dans LilyPond

L’installation de LilyPond comprenant l’interpréteur Guile, les fichiers source LilyPond peuvent contenir du Scheme. Vous disposez de plusieurs méthodes pour inclure du Scheme dans vos fichiers LilyPond.

La méthode la plus simple consiste à insérer un hash (le caractère #, improprement appelé dièse) avant l’expression Scheme.

Rappelons-nous qu’un fichier source LilyPond est structuré en jetons et expressions, tout comme le langage humain est structuré en mots et phrases. LilyPond dispose d’un analyseur lexical (appelé lexer) qui sait identifier les jetons – nombres, chaînes, éléments Scheme, hauteurs, etc. – ainsi que d’un analyseur syntaxique (appelé parser) – voir Grammaire de LilyPond. Dès lors que le programme sait quelle règle grammaticale particulière doit s’appliquer, il exécute les consignes qui lui sont associées.

Le recours à un hash pour mettre en exergue du Scheme est tout à fait approprié. Dès qu’il rencontre un #, l’analyseur lexical passe le relais au lecteur Scheme qui va alors déchiffrer l’intégralité de l’expression Scheme – ce peut être un identificateur, une expression bornée par des parenthèses ou bien d’autres choses encore. Une fois cette expression lue, elle est enregistrée en tant que valeur d’un élément grammatical SCM_TOKEN. Puisque l’analyseur syntaxique sait comment traiter ce jeton, il charge Guile d’évaluer l’expression Scheme. Dans la mesure où le parser requiert une lecture en avance de la part du lexer pour prendre une décision, cette distinction entre lecture et évaluation – lexer et parser – révèle toute sa pertinence lorsqu’il s’agit d’exécuter conjointement des expressions LilyPond et des expressions Scheme. C’est la raison pour laquelle nous vous recommandons, dans toute la mesure du possible, d’utiliser un signe hash lorsque vous faites appel à Scheme.

Une autre manière de faire appel à l’interpréteur Scheme à partir de LilyPond consiste à introduire une expression Scheme par un caractère dollar au lieu d’un caractère dièse – un $ au lieu d’un #. En pareil cas, LilyPond évalue le code dès sa lecture par l’analyseur lexical, vérifie le type d’expression Scheme qui en résulte et détermine un type de jeton (l’un des xxx_IDENTIFIER de la grammaire) qui lui correspond, puis en fait une copie qui servira à traiter la valeur de ce jeton. Lorsque la valeur de l’expression est void, autrement dit une valeur Guile *unspecified* (pour non spécifiée), aucune information n’est transmise à l’analyseur grammatical.

C’est, en réalité, la manière dont LilyPond opère lorsque vous rappelez une variable ou une fonction par son nom – au travers d’un \nom –, à la seule différence que sa finalité est déterminée par l’analyseur lexical de LilyPond sans consultation du lecteur Scheme ; le nom de la variable rappelée doit donc être en corrélation avec le mode LilyPond actif à ce moment là.

L’immédiateté de l’opérateur $ peut entraîner des effets indésirables dont nous reparlerons à la rubrique Saisie de variables et Scheme ; aussi est-il préférable d’utiliser un # dès que l’analyseur grammatical le supporte. Dans le cadre d’une expression musicale, une expression qui aura été créée à l’aide d’un # sera interprétée comme étant de la musique. Elle ne sera cependant pas recopiée avant utilisation. Si la structure qui l’abrite devait être réutilisée, un appel expicite à ly:music-deep-copy pourrait être requis.

Les opérateurs $@ et #@ agissent comme des « colleurs de liste » : leur fonction consiste à insérer tous les éléments d’une liste dans le contexte environnant.

Examinons à présent du vrai code Scheme. Nous pouvons définir des procédures Scheme au milieu d’un fichier source LilyPond :

#(define (moyenne a b c) (/ (+ a b c) 3))

Pour mémoire, vous noterez que les commentaires LilyPond (% ou %{…%}) ne peuvent s’utiliser dans du code Scheme, même si celui-ci se trouve au sein d’un fichier LilyPond. Ceci tient au fait que l’expression Scheme est lue par l’interpréteur Guile, et en aucune façon par l’analyseur lexical de LilyPond. Voici comment introduire des commentaires dans votre code Scheme :

; ceci n'est qu'une simple ligne de commentaire

#!
  Ceci constitue un bloc de commentaire (non imbricable)
  dans le style Guile.
  En fait, les Schemeurs les utilisent très rarement,
  et vous n'en trouverez jamais dans le code source
  de LilyPond.
!#

Dans la suite de notre propos, nous partons du principe que les données sont incluses dans un fichier musical, aussi toutes les expressions Scheme seront introduites par un #.

Toutes les expressions Scheme de haut niveau incluses dans un fichier LilyPond peuvent se combiner en une expression Scheme unique à l’aide de la clause begin :

#(begin
  (define foo 0)
  (define bar 1))

LilyPond — Extension des fonctionnalités v2.23.82 (branche de développement).