2017-08-08 1 views
0

J'écris du code qui remplace un ancien fichier C. Le fichier c d'origine lirait un fichier, puis couperait le contenu et les placerait dans deux nouveaux fichiers, un fichier .c et un fichier .h. Je fais la même chose, mais en C#. J'ai tout compris, à l'exception de la façon de réduire une fonction afin que seuls le nom de la fonction et les paramètres soient placés dans le fichier .h. Voici un exemple de deux des fonctions:Ajustement d'une fonction à partir d'un fichier afin que les seuls caractères restants soient le nom et les paramètres de la fonction

void 
M_SCP_Msg_ClearNVMemory(
    Marshal_dataFunc* _argDataFunc_, Marshal_dataFuncArg _argDataFuncArg_, void const* _argSrc_) 
{ 
    SCP_Msg_ClearNVMemory const* _src_ = (SCP_Msg_ClearNVMemory const*)_argSrc_; 

M_uint8_t(_argDataFunc_, _argDataFuncArg_, &_src_->operation); 

} 

void 
MA_SCP_Msg_ClearNVMemory(
    Marshal_dataFunc* argDataFunc, Marshal_dataFuncArg argDataFuncArg, 
    void const* argSrc, unsigned argNSrcElem) 
{ 

SCP_Msg_ClearNVMemory const* src = (SCP_Msg_ClearNVMemory const*)argSrc; 

for (; argNSrcElem > 0; --argNSrcElem) 
{ 
    M_SCP_Msg_ClearNVMemory(argDataFunc, argDataFuncArg, src++); 
} 
} 

Ce serait le résultat attendu:

extern void M_SCP_Msg_ClearNVMemory(
    Marshal_dataFunc* argDataFunc, Marshal_dataFuncArg argDataFuncArg, void const* argSrc); 

extern void MA_SCP_Msg_ClearNVMemory(
    Marshal_dataFunc* argDataFunc, Marshal_dataFuncArg argDataFuncArg, 
    void const* argSrc, unsigned argNSrcElem); 

Actuellement, les lignes du fichier d'origine sont lus comme des chaînes qui sont affectés par une streamreader, puis cette chaîne est ensuite écrite sur un streamwriter, donc je pensais que parcourir et trouver toutes les chaînes contenant des fonctions serait un bon point de départ, et une fois que j'ai ces chaînes, je pourrais les éditer d'une manière ou d'une autre. C'est ce que j'ai jusqu'ici, finList étant la liste des chaînes et fin étant la chaîne que j'écrirai dans le fichier de sortie.

List<string> finList = new List<string>(); 
finList.AddRange(fin.Split('\n')); 
    for (int x = 0; x < finList.Count; x++) 
     { 
      if (finList[x] == "void" || finList[x] == "_Bool" || finList[x] == "bool" || finList[x] == "unsigned") 
       { 
        finList[x] = im not sure what to do here 
        fin = string.Empty; 
       } 
     } 

     for (int x = 0; x < finList.Count; x++) 
     { 
      fin += finList[x]; 
     } 

Toute direction ou aide serait grandement appréciée. Je suis relativement nouveau à C# et C, alors s'il vous plaît soyez patient si je n'utilise pas les termes corrects pour quoi que ce soit. Je pense que terminer la chaîne/la ligne de la fonction au ")" est ce qui fait le plus de sens, mais je ne sais pas comment faire cela. Merci d'avance!

+0

Si vous voulez une solution robuste, vous devez écrire un analyseur C et extraire toutes les définitions de fonctions. Même si vous corrigez le bogue dans votre code, il échouera sur les fonctions commentées, et plus tard sur tous les autres types de casse. Est-ce que tu dois écrire ça en C#? Utilisez un langage de script! Ils ont été faits pour ça. –

+0

Je suis d'accord, écrire un script semblait être une solution beaucoup plus simple, mais le projet l'exige en C#, c'est supposé être un moyen d'apprendre à traduire C en C#. Mais merci pour l'entrée. Je n'avais même pas pensé à la question des commentaires. – John

+0

Et vous avez probablement oublié les chaînes entre guillemets et vous faites des suppositions invalides sur le formatage du code. Vous voulez analyser le code C et cela nécessite un analyseur pour le code C et ces analyseurs nécessitent des milliers de lignes de code, quelle que soit la langue que vous utilisez. La réponse à votre question est la suivante: Saisissez une grammaire et un fichier lexer pour C et générez un compilateur! Tout le reste est juste un hack avec des hypothèses illégales. –

Répondre

0

solution rapide et sale serait quelque chose comme ceci:

int bracketLevel = 0; 
int squareBracketLevel = 0; 
var methods = new List<string>(); 
var isMethodMode = true; // track if we are in method definition or in method body 
var isMethod = false; // if we have seen parenthesis in definition 
var builder = new StringBuilder(); 

for (int i = 0; i < fin.Length; i++) 
{ 
    if (isMethodMode) 
    { 
     switch (fin[i]) 
     { 
      case '(': 
       isMethod = true; 
       builder.Append(fin[i]); 
       bracketLevel++; 
       break; 
      case ')': 
       builder.Append(fin[i]); 
       bracketLevel--; 
       break; 
      case '{': 
       if (bracketLevel > 0) continue; 
       if (isMethod) 
       { 
        methods.Add(builder.ToString().Trim()); 
        builder.Clear(); 
        isMethod = false; 
       } 
       isMethodMode = false; 
       squareBracketLevel++; 
       break; 
      default: 
       builder.Append(fin[i]); 
       break; 
     } 
    } 
    else 
    { 
     switch (fin[i]) 
     { 
      case '{': 
       squareBracketLevel++; 
       break; 
      case '}': 
       squareBracketLevel--; 
       if (squareBracketLevel == 0) 
       { 
        isMethodMode = true; 
       } 
       break; 
     } 
    } 
} 

variable contient fin fichier chargé C. Bien que cela fonctionne pour votre exemple, il y a deux hypothèses:

  1. code C est valide (pas entre parenthèses mal assortis)
  2. Aucun commentaire n'a été qui contiendrait entre parenthèses (ce commentée des fonctions comme on l'a déjà noté dans les commentaires)
  3. bloc de corps ne contient pas d'accolades constantes chaîne

Si ces hypothèses ne sont pas pour vous, alors vous devrez jeter un coup d'oeil dans les générateurs d'analyseur qui parser le fichier C et générer arbre de syntaxe abstraite pour vous à partir de laquelle vous pouvez extraire l'information désirée. Un exemple est ANTLR. La grammaire C est également disponible au C.g4.