2010-11-11 5 views
1

Je cherche des expressions rationnelles prédéfinies pour les éléments de ANSI C++.Expressions régulières pour trouver des éléments C++?

Je voudrais créer un programme qui prend headerfile (avec comprend, espaces de noms, des classes, etc.) en entrée et retourne la liste avec les noms de classe trouvés, méthodes, attributs, etc.

Il est difficile de google pour quelque chose comme cela, je finis toujours avec des tutoriels sur la façon d'utiliser Regex en C++. Peut-être que je ne fais que googler les mauvais termes? Peut-être que quelqu'un a déjà trouvé/utilisé/créé de telles regex.

+4

Même un analyseur pour C++ est difficile, et vous voulez utiliser une regex? : p (Quoi qu'il en soit, essayez 'gccxml'.) – kennytm

+0

Voulez-vous réellement créer le programme ou recherchez-vous simplement les résultats? Des ctags suffiraient-ils? – Cascabel

+0

Les brouillons 0x (et précédents) définissent la grammaire dans un langage de type regex. Si c'est ce dont vous avez vraiment besoin (http://tinyurl.com/meta-xy) et que vous êtes familier avec regex, ce ne serait pas difficile à convertir; Cependant, je ne pense pas que ce soit ce que vous essayez de faire. –

Répondre

5

Vous pourriez trouver le code pour ctags pratique. Il analysera le code et sortira les symboles à utiliser dans emacs et d'autres programmes. En fait, il pourrait faire tout le travail que vous essayez de faire vous-même.

+0

CTags semble être exactement ce que je cherchais ...Au lieu d'écrire mon propre programme qui cherche des éléments, je peux juste utiliser CTags ... – MOnsDaR

7

Ce type d'opération n'est pas possible avec une expression régulière. C++ n'est pas un langage régulier et ne peut donc pas être analysé de manière fiable avec une expression régulière. L'approche la plus sûre ici est d'utiliser un analyseur réel ici pour localiser les éléments C++.

Si 100% de précision n'est pas un objectif, une expression régulière fonctionnera car elle peut être conçue pour capturer la majorité des cas dans une base de code. L'exemple le plus simple serait la suivante

class\s+[a-z]\w+ 

Cependant, il correspondra à tort ce qui suit comme une classe

  • déclarations à terme
  • Toute chaîne littérale avec le texte comme « class foo »
  • paramètres de modèle
  • etc ...
0

Vous pouvez également trouver quelque chose d'intéressant dans ctags ou cscope comme déjà mentionné. J'ai également rencontré flisthere

0

J'écris un programme Python pour extraire des informations de classe essentielles à partir d'une grande arborescence source C++. Je vais avoir de la chance avec l'utilisation des regex. Heureusement, presque tout le code suit un style qui me permet de ne définir que quelques regex pour détecter les déclarations de classe, les méthodes, etc. La plupart des variables membres ont des noms comme "itsSomething_" ou "m_something". Je kludge dans hackwork codé en dur pour attraper quelque chose ne correspond pas au style.

class_decl_re = re.compile( r"^class +(\w+)\s*(:|\{)" ) 
close_decl_re = re.compile( r"^\};" ) 
method_decl_re = re.compile( r"(\w[ a-zA-Z_0-9\*\<\>]+) +(\w+)\(" ) 
var_decl1_re = re.compile( r"(\w[ a-zA-Z_0-9\*\<\>]+) +(its\w+);" ) 
var_decl2_re = re.compile( r"(\w[ a-zA-Z_0-9\*\<\>]+) +(m_\w+);" ) 
comment_pair_re = re.compile( r"/\*.*\*/") 

Ce travail est en cours, mais je vais vous montrer ce (peut-être bogué) (non, presque certainement bogué) snip de code pour montrer comment les expressions rationnelles sont utilisées:

# at this point, we're looking at one line from a .hpp file 
# from inside a class declaration. All initial whitespace has been 
# stripped. All // and /*...*/ comments have been removed. 
    is_static = (line[0:6]=="static") 
    if is_static: 
     line=line[6:] 

    is_virtual = (line[0:7]=="virtual") 
    if is_virtual: 
     line=line[7:] 

    # I believe "virtual static" is impossible, but if our goal 
    # is to detect such coding gaffes, this code can't do it. 

    mm = method_decl_re.match(line) 
    vm1 = var_decl1_re.match(line) 
    vm2 = var_decl2_re.match(line) 
    if mm: 
     meth_name = mm.group(2) 
     minfo = MethodInfo(meth_name, classinfo.name) # class to hold info about a method 
     minfo.rettype = mm.group(1)    # return type 
     minfo.is_static = is_static 
     if is_static: 
      if is_virtual: 
       classinfo.screwed_up=True 
      classinfo.class_methods[meth_name] = minfo 
     else: 
      minfo.is_polymorphic = is_virtual  
      classinfo.obj_methods[meth_name] = minfo 

    elif vm1 or vm2: 
     if vm1: # deal with vars named "itsXxxxx..." 
      vm=vm1 
      var_name = vm.group(2)[3:] 
      if var_name.endswith("_"): 
       var_name=var_name[:-1] 
     else: # deal with vars named "m_Xxxxx..." 
      vm=vm2 
      var_name = vm.group(2)[2:] # remove the m_ 
     datatype = vm.group(1) 
     vi = VarInfo(var_name, datatype) 
     vi.is_static = is_static 
     classinfo.vars[var_name] = vi 

I J'espère que c'est facile à comprendre et à traduire dans d'autres langues, au moins pour un point de départ pour toute personne assez folle pour essayer. À utiliser à vos risques et périls.