2010-02-03 19 views
2

J'ai un problème intéressant. Disons que j'ai fichier avec des lignes remplies comme ceci:en utilisant boost :: iostreams pour lire des données spécialement conçues, puis en fonction de cet objet de création et l'ajouter à la liste

name1[xp,y,z321](a,b,c){text};//comment 
#comment 
name2(aaaa); 

aussi je (simplifié) Classe:

class something { 
public: 
something(const std::string& name); 
addOptionalParam(const std::string& value); 
addMandatoryParam(const std::string& value); 
setData((const std::string& value); 
}; 
nom

correspond au nom d'un param constructeur de la classe. Les choses listées entre [] entre parenthèses sont optionnelles, in() obligatoires et tout ce qui se trouve entre {} doit être passé en chaîne.

Pour la première ligne, il faut appeler constructeur avec "nom1" comme nom; 3 fois appelez addOptionalParam, une fois pour chaque élément séparé par deux points; aussi 3 fois addMandatoryParam et setData avec "text".

Je peux travailler comment faire les commentaires, mais tout le reste est mutilée pour moi ...

Maintenant, je besoin de bons conseils comment (ou si) cela est possible, si je peux wor comment fais cela pour des objets simples, je peux travailler sur la façon de gérer tous les détails extra sanglants comme la correction sémantique et tout ça.

Répondre

5

Votre description est un peu confuse (par exemple, vous mentionnez "séparé par deux points", mais je ne vois pas de deux-points dans l'entrée). Je suppose que ce que vous avez l'intention est que les éléments entre crochets sont des paramètres facultatifs, entre parenthèses sont des paramètres obligatoires, et dans les accolades est le 'données'.

Dans ce cas, il semble que votre grammaire est quelque chose comme ceci:

func: name optionalParams '(' paramList ')' '{' data '}' 

paramList: param | 
      paramlist ',' param 

optionalParams: // empty 
       | '[' paramList ']' 

name: WORD 
param: WORD 
data: WORD 

Ceci est assez simple grammaire que l'Esprit ne fonctionnera probablement très bien avec elle. L'esprit tend à mener à des temps de compilation vraiment longs pour des grammaires plus grandes, mais cette grammaire est suffisamment petite pour que le temps de compilation soit assez raisonnable.

L'alternative évidente serait d'écrire un analyseur de descente à la place (comme un analyseur de descente récursif, mais dans ce cas, la récursivité ne sera pas nécessaire). Dans ce cas, vous devez écrire une fonction pour chaque niveau de la grammaire, la lire en entrée appropriée et renvoyer une structure (par exemple un vecteur) contenant les données lues. Par exemple, le optionalParams est probablement le plus difficile à analyser (tout simplement parce qu'il est facultatif):

typedef std::string param; 

std::vector<param> read_optional_params(std::istream &in) { 
    std::vector<param> ret; 

    char ch = in.peek(); 
    if (ch == '[') { 
     in >> ch; 
     param temp; 
     while (in >> temp && temp != "]") 
      ret.push_back(temp); 
      if ((ch=in.peek) == ',') 
       in >> ch; 
    } 
    return ret;  
} 

Au niveau supérieur, vous auriez quelque chose comme:

function read_func(std::istream &in) { 
    std::string name = read_name(in); 
    std::vector<param> optional_params = read_optional_params(in); 
    std::vector<param> mandatory_params = read_mandatory_params(in); 
    std::string data = read_data(in); 

    if (in.fail()) { 
     // malformed input 
    } 

    function func = function(name); 
    for (int i=0; i<optional_params.size(); i++) 
     func.addOptionalParam(optional_params[i]); 
    for (int i=0; i<mandatory_params.size(); i++) 
     func.addMandatoryParam(mandatoryParams[i]); 
    func.setData(data); 
    return func; 
} 
+0

+1 Pour considérer une grammaire et l'analyser. –

-1

Wow, wow simplement Je n'ai jamais su que cela serait fait dans d'autres thermies que la lecture d'un fichier, et venant directement de la connaissance marginale de Boost, je ne savais pas qu'il y avait quelque chose comme boost :: spirit. Cependant, maintenant que je parcours la documentation, je trouve très difficile à suivre, la plupart du temps c'est comme "use real_p" et il n'y a pas d'infos sur les namespaces, donc c'est assez compliqué de trouver un item donné ... accomplir je suis vraiment étonné.

Je voudrais étendre des informations sur la grammaire (mais je ne suis pas près de déchiffrer comment faire exactement en termes de code):

nom: peut être une chaîne qui ne commence pas avec le chiffre, doesn param: peut être un entier, un double ou une chaîne contenant uniquement des caractères 'az'
data: tout ce qui se trouve entre accolades (même si possible, ligne breaks), donc {{{{{} devrait donner '{{{{{{} {} {} {} devrait échouer (grammaticalement)
'; ': devrait agir comme séparateur, et une fin définie, donc c'est un must-have

D'autres choses sont des commentaires car je ne peux pas voir dans les exemples comment les implémenter.

Merci pour l'aide, j'aime voir où ça va.

+0

Vous devriez avoir mis à jour votre question avec de nouvelles informations ou demandé dans les commentaires pour clarification. La réponse devrait être utilisée pour répondre. –