parserClassConfig.cpp 6.53 KB
Newer Older
Pierre Aubert's avatar
Pierre Aubert committed
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167

/***************************************
	Auteur : Pierre Aubert
	Mail : aubertp7@gmail.com
	Licence : CeCILL-C
****************************************/

#include <iostream>
#include "string_utils.h"
#include "class_attribute_utils.h"
#include "parserClassConfig.h"
#include "saveClassConfig.h"

using namespace std;

///Affiche une erreur de token non attendu
/**	@param parser : file parser
 * 	@param token : token qui pose problème
*/
void errorUnexpectedToken(const PFileParser & parser, const std::string & token){
	cerr << "errorUnexpectedToken : '" << parser.getFileName() << "' line " << parser.getLine() << endl;
	cerr << "unexpected token '" << token << "'" << endl;
}

///Fonction qui met à jour un commentaire
/**	@param parser : file parser
 * 	@param currentComment : commentaire que l'on veut mettre à jour
 * 	@param token : token courant
 * 	@return true si on l'a mis à jour, false sinon
*/
bool updateCurrentComment(PFileParser & parser, std::string & currentComment, std::string & token){
	if(token == "/"){				//Si on trouve un début de commentaire
		token = parser.getNextToken();
		if(token == "/"){
			currentComment = "//" + eraseCharsInStr(parser.getUntilKey("\n"), "\n");
			return true;
		}else if(token == "*"){
			currentComment = "/*" + parser.getUntilKey("*/");
			return true;
		}else{
			errorUnexpectedToken(parser, token);
		}
	}
	return false;
}

///Parse a PClassConfig
/**	@param[out] config : PClassConfig
 * 	@param[out] parser : file parser
 * 	@param[out] token : current token
 * 	@param[out] currentComment : current commet
 * 	@return true on success, false otherwise
*/
bool parseClassConfigAttribut(PClassConfig & config,  PFileParser & parser, std::string & token, std::string & currentComment){
	std::string attribut(eraseCharsInStr(token + parser.getUntilKey(";"), ";\n"));
	std::list<std::string> listToken(cutStringOnSpacesList(attribut));
	std::string attributName(listToken.back());
	listToken.pop_back();
	std::string attributType("");
	for(std::list<std::string>::iterator it(listToken.begin()); it != listToken.end(); ++it){
		attributType += *it + " ";
	}
	attributType = eraseFirstLastChars(attributType, " \n\t");
	config.addAttribute(createClassAttribute(attributType, attributName, currentComment));
	return true;
}

///Parse the parents of the PClassConfig
/**	@param[out] config : PClassConfig
 * 	@param[out] parser : file parser
 * 	@param[out] token : current token
 * 	@return true on success, false otherwise
*/
bool parseParentOfClassConfig(PClassConfig & config, PFileParser & parser, std::string & token){
	if(token != "(") return true;
	token = parser.getNextToken();
	std::string parentDef(token);
	while(!parser.isEndOfFile() && token != ")"){
		token = parser.getNextToken();
		if(token != ")"){
			if(token == ","){
				config.addParentClass(parentDef);
				parentDef = "";
			}else{
				parentDef += token;
			}
		}
	}
	if(parentDef != "") config.addParentClass(parentDef);
// 	cout << "parseParentOfClassConfig : parent of class '"<<config.getName()<<"' : " << config.getListParentClass() << endl;
	return true;
}

///Parse a PClassConfig
/**	@param[out] listClassConfig : list of PClassConfig
 * 	@param[out] parser : file parser
 * 	@param[out] token : current token
 * 	@param[out] currentComment : current commet
 * 	@return true on success, false otherwise
*/
bool parsePClassConfig(std::list<PClassConfig> & listClassConfig, PFileParser & parser, std::string & token, std::string & currentComment){
	PClassConfig config;
	config.setName(token);
	config.setClassDocumentation(currentComment);
	currentComment = "";
	while(!parser.isEndOfFile() && token != "{" && token != "("){
		token = parser.getNextToken();
	}
	if(!parseParentOfClassConfig(config, parser, token)){
		cerr << "parsePClassConfig : file '" << parser.getFileName() << "' line " << parser.getLine() << endl;
		cerr << "\tmissing ')' : can't parse parents of the class '"<<config.getName()<<"'" << endl;
	}
	if(parser.isEndOfFile()){
		cerr << "parsePClassConfig : file '" << parser.getFileName() << "' line " << parser.getLine() << endl;
		cerr << "\tmissing '}'" << endl;
		return false;
	}
	bool searchingData(true);
	while(!parser.isEndOfFile() && searchingData){
		token = parser.getNextToken();
		if(parser.isChSeparator()){
			if(token == "}"){
				searchingData = false;
			}else updateCurrentComment(parser, currentComment, token);
		}else{		//Si ce n'est pas un séparateur, c'est que l'on a trouvé un nom, de PDataGroup ou de PDataVar ou PDataTable
			if(!parseClassConfigAttribut(config, parser, token, currentComment)){
				errorUnexpectedToken(parser, token);
				return false;
			}
		}
	}
	listClassConfig.push_back(config);
	return true;
}

///Parser list class config
/**	@param[out] listClassConfig : list of class config
 * 	@param listInclude : list of include
 * 	@param fileName : file name of the config
 * 	@return true on success, false otherwise
*/
bool parserClassConfig(std::list<PClassConfig> & listClassConfig, std::list<std::string> & listInclude, const std::string & fileName){
	if(fileName == "") return false;
	PFileParser  parser;
	if(!parser.open(fileName)) return false;
	std::string currentComment("");
	std::string token = parser.getNextToken();
	while(!parser.isEndOfFile()){
		if(token == "#"){
			token = parser.getNextToken();
			if(token == "include") listInclude.push_back(eraseCharsInStr(parser.getUntilKey("\n")," \t\n"));
		}else if(parser.isChSeparator()){
			updateCurrentComment(parser, currentComment, token);
		}else{		//Si ce n'est pas un séparateur, c'est que l'on a trouvé un nom, de PClassConfig
			if(!parsePClassConfig(listClassConfig, parser, token, currentComment)){
				errorUnexpectedToken(parser, token);
				return false;
			}
		}
		token = parser.getNextToken();
	}
	return true;
}

///Parser list class config
/**	@param baseFileNameOutput : base of the output files
 * 	@param fileName : file name of the config
Pierre Aubert's avatar
Pierre Aubert committed
168
 * 	@param enableDataStream : true to enable the serialization/deserialization with DataStream, false otherwise
Pierre Aubert's avatar
Pierre Aubert committed
169 170
 * 	@return true on success, false otherwise
*/
Pierre Aubert's avatar
Pierre Aubert committed
171
bool saveParserClassConfig(const std::string & baseFileNameOutput, const std::string & fileName, bool enableDataStream){
Pierre Aubert's avatar
Pierre Aubert committed
172 173 174 175 176 177 178 179 180 181 182 183 184
	std::list<std::string> listInclude;
	std::list<PClassConfig> listClassConfig;
	if(!parserClassConfig(listClassConfig, listInclude, fileName)){
		cerr << "saveParserClassConfig : can't load file '" << fileName << "'" << endl;
		return false;
	}
	if(!saveClassImplDecl(listClassConfig, baseFileNameOutput, listInclude)){
		cerr << "saveParserClassConfig : can't save files '" << baseFileNameOutput << "'[.h or .cpp]" << endl;
		return false;
	}
	return true;
}