Je n'ai pas une réponse à ta question exactement, mais j'ai peut-être des pistes. Au passage, il y a aussi l'associativité qu'il faut définir.
Je connais deux langages qui permettent de définir des opérateurs et ils fonctionnent tous les deux différemment :
- D'un côté, il y a Ocaml pour lequel un opérateur hérite de la priorité de l'opérateur correspondant à son premier caractère. Du coup, +
, +.
, +:
et ++
ont la même priorité (et associativité). C'est implicite, ce qui permet d'éviter d'éviter de devoir le spécifier soit-même. En revanche, il n'est plus possible de faire des opérateurs "symétriques" (ou palindromes) tels que :+:
, <+>
ou .+.
parce que la priorité ne serait pas celle que l'on attend.
- De l'autre côté, il y a Haskell qui définit une priorité par défaut (la plus haute) et qui permet de spécifier soit-même la priorité avec infixl 5 ++
par exemple. Cela permet plus de liberté, mais a l’inconvénient de forcer l'utilisateur à indiquer lui-même la priorité et de connaître la priorité des autres opérateurs.
Les deux solutions ont aussi un autre inconvénient : celui d'avoir un nombre fini de priorités possibles. C'est-à-dire que (pour le Haskell) il n'est pas possible de définir un opérateur ayant une priorité entre +
(6) et *
(7).
Une dernière chose : tu laisses la possibilité à l'utilisateur de définir des opérateur ayant un nom exactement comme une variable. Cela risque de te poser des problèmes pour le compilateur : en effet, tu ne peux plus vérifier durant l'analyse syntaxique que l'utilisateur n'a pas écrit quelque chose équivalent à 5 + * 8 *
, qui n'a que très peu de chances d'être syntaxiquement correct. Pour cela, il te faut des informations de l'analyse sémantique, qui est sensé se faire après, notamment parce qu'il est difficile de donner du sens à quelque chose qui n'est pas forcément syntaxiquement correcte.
Le Haskell résout le problème en permettant l'utilisation de n'importe quel variable en tant qu'opérateur avec `
. Par exemple, `plus`
est un opérateur infixe. Au passage, on peut définir la priorité de ce genre d'opérateur de la même manière que pour les opérateurs habituels infixl 5 `plus`
.
Pour ton langage, on pourrait imaginer quelque chose comme :
| operatorl<5> +(Lhs:A, Rhs: A) -> A! {
Lhs + Rhs;
}
|
qui permettrait de définir la priorité (et l'associativité) d'un opérateur. Si tu veux aller plus loin et permettre n'importe quel priorité sans nécessiter que l'utilisateur connaisse celle des opérateurs usuels, on pourrait imaginer quelque chose comme operator<+>
qui indique un opérateur de même priorité que +
ou operator<+,*>
qui indique un opérateur dont la priorité est entre +
et *
.
Cependant, tu risques d'avoir du mal à bien définir le comportement d'un code qui contient ce genre de chose
| operator<+,*> +.
operator<+,*> *.
operator<+.,*> ++
// on a + < +. < ++ < *
// et + < *. < *
// donc on a une ambiguïté bien plus difficile à résoudre que celle que l'on a avec uniquement les deux premiers opérateurs
|