Je ne veux pas faire tout l'exercice à ta place!
Voici un petit bout du parser.
Il traite un 'begin' implicite.
Il doit être, en gros, le premier appel à qui l'on passe:
- le nom de la fonction
- la liste des expressions du corps de la fonction
- #t
Les fonctions retournent #t si c'est récursif terminal et #f si c'est récursif non terminal.
Le paramètre 'term' est très important!Code:
1
2
3
4
5
6
7
8
9
10 (define (trec-body fun body term) (if (null? body) #t (if (null? (cdr body)) ;; Last expression of body (trec-expr fun (car body) (and term #t)) (and ;; Some non-last expression (trec-expr fun (car body) (and term #f)) ;; Continue with the other expressions (trec-body fun (cdr body) term)))))
Lorsqu'il est #t, il indique qu'on est dans un bout d'arbre ignorable (c'est-à-dire une imbrication de 'if' ou une dernière instruction).
Lorsqu'il est #f, il indique qu'on est "sous" une fonction non-ignorable (comme '+' par exemple).
Il détermine ce qu'on doit retourner si on rencontre la fonction au cours du parsing.
Plus précisément, la fonction qui retourne effectivement des valeurs et détermine si c'est récursif-terminal ou non ressemble à ceci:
Elle devrait aussi traiter les lambda...Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 (define (trec-expr fun expr term) (cond ((not (pair? expr)) #t) ((eq? fun (car expr)) ;; Found a call to 'fun' (if (not term) #f ;; No need to continue ;; Checks 'fun's args, but with 'term' set to false (trec-body fun (cdr expr) #f))) ;; This is not a call to fun. Go inside. (else (case (car expr) ((if) (trec-if fun (cdr expr) term)) ((cond) (trec-cond fun (cdr expr) term)) ;; Idem for every special form like: ;; apply case cond define do fluid-let lambda let let* letrec named-lambda etc. ((let) (trec-let fun (cdr expr) term)) ... (else ;; This is a normal function (like '+' 'cons' etc.) ;; Checks its args, with 'term' set to false (trec-body fun (cdr expr) #f))))))