Bonjour,

je cherche à faire un petit parseur de code C qui retrouve les prototypes des fonctions.

Je me suis fait le code suivant :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
def findall ( exp,str ):
    '''Renvoie une liste de dict de toutes les occurrences de exp dans la chaîne str 
       (re.findall ne fait pas ce que je veux)'''
    res,pos = [],0
    while True :
        match = exp.search( str[pos:],re.DOTALL )
        if not match : return res
        pos += match.end()-1
        res += [ match.groupdict() ]
 
def find_all_proto ( source ):
    '''Renvoie tous les prototypes C de source'''
    regx = r'''(\W|\A)
               (?P<type>  (\w+ ( \* | \s+ )+ )+  )
               (?P<name>  \w+  )
               \s*\(
               (?P<param> .*? )
               \) \s* ;'''
    ex_proto = re.compile( regx,re.DOTALL+re.VERBOSE)
    return findall( ex_proto,source ) 
 
def test_find_proto ():
    s = '''void f1 ();
           void f2 ( void ) ; 
           void f3( int x );void f4 ( int x , char * s ); 
           void*f5 ( int x , char * s ); 
           void* f6 ( int x , char * s ); 
           void *f7 ( int x , char * s ); 
           void * f8 ( int x , char * s ); 
           int ** f9 ( int x , char * s ); 
           int * * f10 ( int x , char * s ); 
           int * ** f11 ( int x , char * s ); 
           const int * ** f12 ( int x , char * s ); 
           const int*const **f13 ( int x , char * s ); 
           const int f14 ( int x , char * s ); 
           static const int f15 ( int x , char * s ); 
        '''
    for p in find_all_proto( s ):
        print '%-20s : %3s : %s'%(p.get('type'),p.get('name'),p.get('param',''))
 
test_find_proto()
et j'obtiens ça :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
void                 :  f2 :  void 
void                 :  f4 :  int x , char * s 
void*                :  f6 :  int x , char * s 
void *               :  f8 :  int x , char * s 
int * *              : f10 :  int x , char * s 
const int * **       : f12 :  int x , char * s 
int*const **         : f13 :  int x , char * s 
int                  : f14 :  int x , char * s 
const int            : f15 :  int x , char * s
Comme vous pouvez le voir il me manque presque une fonction sur 2, à part les 13 et 15 dont il manque le premier mot.
Si je supprime la fin de l'expression régulière
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
    regx = r'''(\W|\A)
               (?P<type>  (\w+ ( \* | \s+ )+ )+  )
               (?P<name>  \w+  )
               \s*\('''
j'obtiens ça :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
void                 :  f2 : 
void                 :  f3 : 
void*                :  f5 : 
void*                :  f6 : 
void *               :  f7 : 
void *               :  f8 : 
int **               :  f9 : 
int * *              : f10 : 
int * **             : f11 : 
const int * **       : f12 : 
const int*const **   : f13 : 
const int            : f14 : 
static const int     : f15 :
Cette fois, j'ai bien toutes les fonctions et il ne manque aucun mot.
A part "f1" et "f4" qui manquent encore.

Donc, à vous les experts des reg exp : comment expliquer un tel comportement ?

Encore plus étrange :
Si j'ajoute une première ligne à mes prototypes de test, le résultat dépend du nombre de caractères :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
def test_find_proto ():
    s = '''zzzzz
           void f1 ();
           ....
j'ai bien "f1" mais je perds "f2" :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
void                 :  f1 : 
void                 :  f3 : 
void*                :  f5 : 
void*                :  f6 : 
void *               :  f7 : 
void *               :  f8 : 
...
Mais avec un 'z' de moins, je pers à nouveau "f1".

Si quelqu'un a une idée... moi je suis à sec !

Merci !