Élodie Gamot — 30 juin 2022
Améliorer l'analyse syntaxique
Peut-être avez-vous déjà eu à étudier la fonction mathématique f(x)=xcos(x)
et son élégant tracé ?
Si vous avez tenté de la tracer sur la calculatrice avant la sortie de la version 19 de notre logiciel, vous avez sans doute rencontré quelques difficultés, en l’occurrence un écran vide et des valeurs “undef”. De quoi provoquer des interrogations !
Pour comprendre ce problème, et surtout comprendre sa résolution, nous devons d’abord nous interroger sur le processus d’analyse suivi par la calculatrice lorsque l’on presse le bouton exe à la fin d’un calcul.
Comprendre le parseur
Dans l’article Développer c’est renoncer !, Léa nous expliquait comment la calculatrice procède une fois que l’utilisateur presse exe.
Tout d’abord, la calculatrice essaye de comprendre ce que vous avez écrit.
Si vous écrivez 13+2
, la calculatrice commence par identifier les différents termes utilisés dans le calcul : le nombre 13
, le symbole +
, et le nombre 2
. Elle applique ensuite des règles de grammaire, exactement comme vous le faites actuellement en lisant cette phrase. Ainsi, un nombre suivi du symbole +
puis d’un autre nombre s’analyse comme une addition entre ceux-ci.
Le procédé qui consiste à parcourir le contenu d’un texte ou d’un fichier en l’analysant pour vérifier sa syntaxe ou en extraire des éléments s’appelle le parsing.
Léa nous expliquait aussi que, lorsque l’on introduit des variables et des fonctions, les choses se compliquent un peu.
Si l’on entre, par exemple, abba(1+2)
:
- Est-ce la fonction
abba
appliquée à1+2
? - Est-ce la variable
abba
multipliée par1+2
? - Est-ce la variable
a
multipliée par la variableb
, multipliée par la variableb
, multipliée par la variablea
, multipliée par1+2
? - Est-ce la variable
abb
multipliée par la fonctiona
appliquée à1+2
?
Avant la version 19, notre parseur, qui analyse les données entrées dans la calculatrice, suivait une règle : toujours créer le nom de variable le plus long possible et, si ce nom est suivi de parenthèses, le comprendre comme un nom de fonction.
Si la règle était simple, elle nécessitait cependant que l’utilisateur écrive très explicitement le signe de la mutiplication.
C’est d’ailleurs pour cette raison que vous vous êtes peut-être trouvé en difficulté en voulant tracer f(x)=xcos(x)
!
En effet, sans la multiplication explicite, le parseur recherche le nom de variable le plus long possible : xcos
. Cependant, comme xcos
n’est pas défini, on se retrouve avec une variable inconnue xcos
multipliée par la variable x
, d’où xcos*(x)
. Et bien sûr, comme xcos
n’est pas défini, la fonction ne l’est pas non plus.
Une première solution
Lorsque l’on est face à un problème, il est important d’envisager plusieurs méthodes de résolution.
Initialement, nous avions songé à faire précéder automatiquement toutes les fonctions de type sin()
, cos()
, ln()
, par le symbole de la multiplication dès lors que l’on pressait la touche correspondante (e.g. *sin()
). Malheureusement, cette solution ne fonctionnait pas lorsque l’on devait écrire les fonctions en toutes lettres, ce qui est par exemple le cas lorsque l’on utilise le clavier de son ordinateur sur le simulateur.
Une meilleure solution : améliorer le parseur !
Pour trouver une solution plus efficace, il nous fallait procéder à des ajustements au niveau du parseur et revoir notre algorithme d’analyse.
La multiplication implicite par défaut
Tout d’abord, par défaut, on considère que ab
signifie a*b
. C’est-à-dire que, à moins que ab
ne soit défini comme une variable ou une fonction, on suppose qu’il existe une multiplication implicite.
Pour éviter des conséquences fâcheuses dans l’application Solveur, il est toujours possible de résoudre des équations en utilisant des variables de type chaîne de caractères, mais en utilisant des guillemets : "apple"+"pear"=12
.
Analyser de droite à gauche
Quand on analyse une chaîne de caractères abc
, on commence par considérer abc
, puis bc
, et enfin c
jusqu’à ce qu’on parvienne, soit à une fonction ou une variable déjà définie, soit à un simple caractère. On répète ensuite cet algorithme avec les caractères restants.
Reprenons notre fonction de départ : f(x) = xcos(x)
Comment la calculatrice va-t-elle analyser notre entrée ?
Prenons d’autres exemples.
On définit les symboles suivants : a
, b
, ab
, azfoo
et foobar
. Les cos()
et acos()
sont des fonctions prédéfinies.
-
Comment la calculatrice va-t-elle analyser
abfoobar(x)
?Même si
a
etb
sont aussi définis, le parseur va commencer par lire la chaîneab
. Si vous souhaitez mutipliera
parb
, il vous faudra utiliser le symbole de la multiplication :a*b
-
Comment la calculatrice va-t-elle analyser
acos(x)
?Dans cet exemple aussi,
a
etcos
sont déjà définis. Cependant, le parseur va tout d’abord lire la chaîne de caractères en entier,acos
, qui est une fonction prédéfinie. Si vous souhaitez multipliera
parcos
, il vous faudra là encore utiliser explicitement le symbole de la multiplication :a*cos
-
Comment la calculatrice va-t-elle analyser
azfoobar(x)
?Dans ce dernier exemple, on peut se demander pourquoi le symbole
azfoo
n’est pas utilisé. L’algorithme d’analyse va en fait éliminer un maximum de caractères en commençant par la gauche. Certes, on aurait pu commencer de l’autre côté, mais grâce à ce comportement on privilégie les fonctions aux symboles. Et cela nous permet d’obtenira*z*foobar(x)
plutôt queazfoo×b×a×r×(x)
.Explorez la calculatrice ! Testez notre nouveau parseur et n’hésitez pas à nous suggérer des améliorations !
Élodie Gamot — Responsable pédagogique
Elodie, c'est la professeure de maths que tout le monde rêverait d'avoir et maintenant nous l'avons chez NumWorks ! Passionnée et passionnante, elle aime raconter des histoires… et pas seulement à propos des mathématiques !