Sommaire-
Traitement des expressions régulières
On s'intéresse à l'écriture des nombres conformes à la
syntaxe de la calculette standard des systèmes Unix, bc
,
et on veut créer des expressions régulières qui vérifient la
syntaxe de tels nombres. Par exemple, si j'écris -1.23^-5
cela dénote le nombre
Les expressions régulières peuvent être traitées par un programme Scheme, et les textes reconnus peuvent être décomposés en leurs parties élémentaires ;
ainsi, pour un nombre écrit selon la syntaxe de bc
, il sera
possible de séparer l'exposant de la mantisse (le nombre auquel est
appliqué l'exposant) pour ensuite les utiliser dans des expressions
Scheme ordinaires.
On rappelle qu'en mettant entre parenthèses une sous-expression d'une
expression régulière, il est possible de distinguer les parties du
texte reconnues par chaque sous-expression
régulière. Ces parties de texte sont placées, par la procédure
pregexp-match
à la ligne 8 du programme ci-dessous, dans une liste, dans l'ordre des parenthèses ouvrantes
auxquelles elles correspondent. Le premier élément de la liste (numéro
0) sera le texte entier reconnu par l'expression régulière, le second
élément (numéro 1) sera la partie de texte reconnue par la première
sous-expression entre parenthèses, et ainsi de suite. Par exemple,
soit le programme suivant :
- (module number-parser
- (main get-number))
- (define (get-number args)
- (let* ((number (cadr args))
- (regexp
- "^(+|-)?([0-9]*)?(\\.([0-9]*))?(\\^((+|-)?[0-9]+))?$")
- (number-elems (pregexp-match regexp number)))
- (print number-elems)))
Son invocation avec un nombre tel que décrit ci-dessus donnera :
./number-parser 123.8^-4 (123.8^-4 #f 123 .8 8 ^-4 -4 -)123.8^-4
;
#f
: en effet le groupe de la première paire de parenthèses (+|-)
reconnaît le signe du nombre, qui ne figure pas dans notre cas ;
123
, est la partie entière, reconnue par ([0-9]*)
;
(\\.([0-9]*))
(attention aux doubles barres obliques inversées !) est la partie décimale, précédée du point, .8
;
([0-9]*)
est la partie décimale ;
^-4
, reconnu par (\\^((+|-)?[0-9]+))
;
((+|-)?[0-9]+)
, est l'exposant muni de son signe ;
Question 1
On rappelle que la procédure string->number
permet de convertir une chaîne de caractères en nombre.
Modifiez le programme ci-dessus pour afficher, non plus la liste des sous-chaînes reconnues par des sous-expressions, mais le texte d'une expression Scheme qui dénote le nombre.
Réponse :
- (module number-parser
- (main get-number-string))
- (define (get-number-string args)
- (let ((number-string (cadr args)))
- (print (parse2number number-string))
- ))
- ;; On isole la procédure d'analyse proprement dite :
- (define (parse2number number-string)
- (let* (
- (regexp
- "^(+|-)?([0-9]*)?(\\.([0-9]*))?(\\^((+|-)?[0-9]+))?$")
- (number-elems (pregexp-match regexp number-string))
- ;; On localise les éléments qui seront utiles à la
- ;; construction du nombre et on leur donne des noms :
- (sign-num (cadr number-elems))
- (int-part (caddr number-elems))
- (point-part (cadddr number-elems))
- (exponent (caddr (cddddr number-elems)))
- ;; Construction du nombre :
- (number-list (append
- (if exponent (list 'expt) '())
- (list (string-append
- (if sign-num sign-num "")
- int-part
- (if point-part point-part "")))
- (if exponent (list exponent) '())))
- (the-number (if exponent number-list (car number-list))))
- the-number))