Abordons maintenant la création de langages de programmation dans talenha. Outre les langages de programmation, la création de DSL (Domain Specific Language) permet de construire plus rapidement du code.Par exemple, créer un langage de programmation qui effectue le design d'une page web à l'aide d'une notation spécifique pour construire la page web.
Ainsi, pour un opérateur tel que le '+', le type prédéfini est toujours 'operator'. Pour un séparateur tel que ',' alors le type prédéfini est toujours 'separator'.
Enfin, pour les éléments de groupe, le type prédéfini est toujours 'surrogate' et de plus, le terme ouvrant doit avoir la propriété 'surrogate' avec la valeur
En bref, cela signifie qu'une virgule ou une autre ponctuation est soit un séparateur soit un opérateur mais pas les deux à la fois.
Cependant tout nom de type peut être utilisé et l'on verra dans les règles grammaticales que l'on peut détecter n'importe quel nom de type.
Une séquence est une suite d'expressions séparées par une virgule. Chaque expression respecte une syntaxe particulière qui dépend du type d'expression choisi.
Ensuite, le code est ce qui est interprété si la règle est valide. Pour savoir ce qu'il y a dans le texte d'entrée en fonction des règles grammaticales, le code de chaque règle a une variable locale appelée input. Cette variable est une liste qui contient, pour chaque expression de la séquence, le texte d'entrée qui a été validé; et, en fait, le texte d'entrée est exprimé comme un objet splitter.
S'il n'existe aucun objet splitter qui corresponde au texte alors un objet de type 'string' est défini par défaut.
Création d'un transpiler
Le mot transpiler signifie convertir d'un langage à un autre. Dans la création de langage de programmation avec talenha, c'est exactement cela. A partir d'un découpage du texte d'entrée en morceaux et de règles grammaticales puis en programmant le résultat attendu, vous convertissez votre langage en des termes d'un autre langage comme par exemple, le HTML/CSS/JavaScript.Vous créez un nouveau transpiler dès que vous écrivez la commande suivante :create transpiler name { }
Le découpage du texte d'entrée
Avant de vérifier la grammaire du langage, il faut d'abord découper en petits morceaux bien séparés votre texte d'entrée pour distinguer les ponctuations, les termes, les opérateurs, les séparateurs. Ce découpage s'effectue à l'aide d'une série de commandes splitter.Splitter
Pour déclarer une commande splitter, il suffit d'écrire:splitter { type : "type d'objet", value : "la valeur texte à trouver dans le texte d'entrée", color : "la couleur à afficher dans l'éditeur", ... d'autres propriétés spécifiques }
Trois formats
Il y a 3 formats de découpage qui permettent de découper n'importe quel texte.- Utiliser la propriété 'value' et indiquer un texte comme un séparateur (,; ou .), un opérateur (+-☆/\\& ou |)
- Définir la propriété 'value' avec une liste de termes entre crochets comme ceci
[...]
. Par exemple, cela permet de découper les nombres - Définir la propriété 'value' avec une expression telle que
("début", "fin", [])
. Cela permet de découper des commentaires ou des chaînes de caractères entre guillemets ou entre apostrophe. En particulier, dans les crochets, on définit les situations d'échappements (\\\" par exemple pour les chaînes de caractères). L'opération de découpage retourne l'ensemble du texte avec les termes de début et de fin.
Propriétés spécifiques
Il y a plusieurs propriétés spécifiques que le programme de découpage appliquera en particulier.- Si la propriété 'remove' est présente et qu'elle est à true alors le morceau de texte n'apparaîtra pas au moment des règles grammaticales. Cela sert, par exemple, pour supprimer les espaces et les tabulations dans le texte.
- Si la propriété 'accept' est présente et qu'elle est à true alors le morceau de texte sera considéré comme non significatif. Le non significatif précise que le morceau de texte est optionnel; s'il est présent, il est absent excepté si on le demande dans les règles grammaticales.
- Si la propriété 'newContextOnly' est présente et qu'elle est à true alors le morceau de texte sera présent uniquement s'il n'est pas déjà dans un autre contexte de découpage. C'est par exemple, le cas du découpage des nombres où le terme 'ab2c' est dans un autre contexte de découpage tandis que 'a 2 b' découpera 'a', '2' et 'b' (à condition que l'espace fasse partie du découpage)
- La propriété 'recursive' s'applique pour la détection récursive des accolades (ou des crochets) qui peuvent contenir eux-mêmes des accolades (ou des crochets). Par exemple, du code entre accolades pouvant contenir des sous-blocs d'accolades sera découpé en un seul élément.
- Les notations
splitter @base
,splitter @space
,splitter @algorithmic
,splitter @language
etsplitter @misc
incluent automatiquement le découpage du langage talenha. En effet, vous pouvez créer un nouveau langage qui inclut le langage talenha et même qui l'étend.
splitter @spacedéfinit cette opération. De même, les opérateurs et les séparateurs du langage talenha sont ajoutés automatiquement lorsque l'on indique les commandes
splitter @baseet
splitter @algorithmic. Enfin,
splitter @languageet
splitter @miscajoutent les fonctionnalités complémentaires du langage talenha.
Les types prédéfinis
Pour découper un opérateur, un séparateur ou des éléments de groupe ouvrants/fermants tels que (), {}, [], <>, il y a des types prédéfinis qui permettront aux fonctions automatiques des règles grammaticales de fonctionner correctement.Ainsi, pour un opérateur tel que le '+', le type prédéfini est toujours 'operator'. Pour un séparateur tel que ',' alors le type prédéfini est toujours 'separator'.
Enfin, pour les éléments de groupe, le type prédéfini est toujours 'surrogate' et de plus, le terme ouvrant doit avoir la propriété 'surrogate' avec la valeur
"high"et le terme fermant doit avoir la propriété 'surrogate' avec la valeur
"low"pour que les fonctions automatiques des règles grammaticales s'appliquent correctement. Par exemple :
splitter { type : "surrogate", value : "(", surrogate : "high", color : "red" } splitter { type : "surrogate", value : ")", surrogate : "low", color : "red" }
Limitation
La propriété 'value' contient le morceau de texte qui est recherché dans le texte d'entrée de votre langage, c'est-à-dire ce que vous écrirez dans ce langage. A toute propriété 'value' est associé un unique objet, et toutes les propriétés données dans splitter seront transmises au programme d'analyse des règles grammaticales.En bref, cela signifie qu'une virgule ou une autre ponctuation est soit un séparateur soit un opérateur mais pas les deux à la fois.
Cependant tout nom de type peut être utilisé et l'on verra dans les règles grammaticales que l'on peut détecter n'importe quel nom de type.
Les règles grammaticales
Une règle grammaticale est définie par la commande :rule name [ ... séquence ... ] { ... code ... }Le nom de la règle doit être unique et ne pas contenir d'espaces ni de ponctuations.
Une séquence est une suite d'expressions séparées par une virgule. Chaque expression respecte une syntaxe particulière qui dépend du type d'expression choisi.
Ensuite, le code est ce qui est interprété si la règle est valide. Pour savoir ce qu'il y a dans le texte d'entrée en fonction des règles grammaticales, le code de chaque règle a une variable locale appelée input. Cette variable est une liste qui contient, pour chaque expression de la séquence, le texte d'entrée qui a été validé; et, en fait, le texte d'entrée est exprimé comme un objet splitter.
S'il n'existe aucun objet splitter qui corresponde au texte alors un objet de type 'string' est défini par défaut.
splitter { type : "string", value : contenu du texte inconnu }
Les expressions des règles grammaticales
Voici la liste des expressions possibles d'une séquence:- keyword()
- or()
- separator()
- operator()
- surrogate()
- not()
- is()
- until()
- if()
- node()
- concat()
- parse()
- repeat()
- [ ... séquence ... ]
- Le nom d'une règle entre guillemets
keyword
rule if [ keyword("if"), ... ] { ... }L'expression keyword vérifie que le terme 'if' a été découpé tel quel dans le texte d'entrée, c'est-à-dire que le terme n'est pas 'aif' ni 'ifa', ni 'aifa'.