2011-07-04 4 views
2

Je travaille avec une base de code C++. En ce moment j'utilise un code C++ appelant le script lua pour regarder à travers la base de code entière et, je l'espère, retourner une liste de toutes les chaînes qui sont utilisées dans le programme.Motif Lua correspondant à l'extraction de chaînes codées en dur dans la base de code

Les chaînes en question sont toujours précédées d'une macro JUCE appelée TRANS. Voici quelques exemples qui devraient extraire une chaîne

TRANS("Normal") 
TRANS ("With spaces") 
TRANS("") 
TRANS("multiple"" ""quotations") 
TRANS(")") 
TRANS("spans \ 
multiple \ 
lines") 

Et je suis sûr que vous pouvez imaginer d'autres varients de cordes possibles qui pourraient se produire dans une grande base de code. Je suis en train de créer un outil automatique pour générer des fichiers au format JUCE afin d'automatiser le processus autant que possible.

Je suis arrivé à ce stade, en l'état, pour trouver des chaînes de caractères. J'ai converti le code source dans une chaîne de lua

path = ... 

--Open file and read source into string 
file = io.open(path, "r") 
str = file:read("*all") 

et appelé

for word in string.gmatch(string, 'TRANS%s*%b()') do print(word) end 

qui trouve un modèle qui commence par TRANS, a des parenthèses équilibrée. Cela me donnera la macro complète, y compris les supports, mais à partir de là, j'ai pensé qu'il serait assez facile de séparer la graisse dont je n'ai pas besoin et de garder la valeur réelle de la chaîne. Toutefois, cela ne fonctionne pas pour les chaînes qui provoquent un déséquilibre des parenthèses. TRANS(")") retournera par exemple TRANS("), au lieu de TRANS("(")

Je révisé mon modèle à

for word in string.gmatch(string, 'TRANS%s*(%s*%b""%s*') do print(word) end 

où, le motif doit commencer par un TRANS, puis 0 ou plusieurs espaces. Il devrait alors avoir un caractère (suivi de zéro ou plus d'espaces) Maintenant que nous sommes à l'intérieur des parenthèses, nous devrions avoir un nombre équilibré de marques "", suivies d'un autre ou plusieurs espaces, et finalement terminées par a). Malheureusement, cela ne retourne pas une seule valeur lorsqu'il est utilisé. Mais ... je pense que même si ça a marché comme je m'y attendais ... Il peut y avoir un \" à l'intérieur, ce qui provoque le déséquilibre du support.

Un conseil sur l'extraction de ces chaînes? Devrais-je continuer à essayer de trouver une séquence de correspondance de motifs? ou devrais-je essayer un algorithme direct ... Savez-vous pourquoi mon deuxième motif n'a renvoyé aucune chaîne? Tout autre conseil! Je ne cherche pas à couvrir 100% de toutes les possibilités, mais être proche de 100% serait génial. Merci! : D

Répondre

0

Dans le second cas, vous avez oublié d'échapper les parenthèses. Essayez

for word in string.gmatch(str, 'TRANS%s*%(%s*(%b"")%s*%)') do print(word) end 
+0

Ahh, je ne savais pas que vous aviez besoin d'un caractère d'échappement pour (marques) Et j'aime la façon dont votre réponse donne la chaîne dans un format encore meilleur que celui que j'avais auparavant ... Malheureusement cela échoue encore pour les chaînes comme TRANS ("\" ") ou toute chaîne avec la citation ... –

+0

@Colton, je ne pense pas que vous serez en mesure de 100% ou même près de lui avec des modèles Lua. Vous avez besoin d'un vrai lexer qui comprend C règles de chaîne.Je suggère d'utiliser le préprocesseur C ('cpp' ou' gcc -E') avec une définition de 'TRANS' qui facilite le post-traitement du résultat. J'ai fait un test rapide avec '#define TRANS (x) BEGIN x END' et cela fonctionne bien sur vos exemples. – lhf

+0

Je ne suis pas exactement sûr de ce que vous entendez par votre réponse. Je suis conscient de ce qu'est une macro de préprocesseur C, car c'est ce que TRANS est, mais je ne sais pas ce que vous obtenez avec ce test rapide #define. Pourriez-vous entrer dans plus de détails? :) –

1

J'aime les motifs Lua autant que n'importe qui, mais vous apportez un couteau pour une bagarre. C'est l'un de ces problèmes où vous ne voulez vraiment pas coder la solution comme des expressions régulières. Pour traiter correctement les doubles marques et les barres obliques inversées, vous voulez un vrai analyseur, et LPEG gérera bien vos besoins.

+0

Comment LPEG me donnera-t-il un avantage sur les modèles de Lua typiques? Il y a beaucoup à lire, pouvez-vous me donner des fonctions spécifiques qui pourraient vous intéresser? Aussi, êtes-vous sûr que les modèles ne suffiront pas? Je n'ai pas besoin de couvrir 100% de toutes les conditions aux limites, je crois ... Ce n'est pas important pour l'utilisation de l'outil sur lequel je travaille. En ce moment je me demande si cela pourrait être une meilleure idée d'essayer d'accomplir cela par étapes plutôt que par un seul motif ... –

+0

LPEG est un système d'analyse complète. Vous devez écrire une grammaire qui correspond à vos instances de macro TRANS, la parenthèse équilibrée et la syntaxe complète d'un littéral de chaîne C, y compris les balises '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' votre texte source, et sortez ce que vous avez besoin de savoir.C'est un gros paquet, mais ça vaut le coup.Pensez-y comme vous donnant tout ce que LEX et YACC fournissent et plus encore. – RBerteig