parserClassConfig.cpp 6.49 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

/***************************************
	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;
}

25 26 27 28 29 30 31 32
///Get class name from parser
/**	@param parser : PFileParser to be used
 * 	@return class name
*/
std::string getClassName(PFileParser & parser){
	return parser.getStrComposedOf("_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
}

Pierre Aubert's avatar
Pierre Aubert committed
33 34 35 36 37
///Fonction qui met à jour un commentaire
/**	@param parser : file parser
 * 	@param currentComment : commentaire que l'on veut mettre à jour
 * 	@return true si on l'a mis à jour, false sinon
*/
38 39 40 41 42 43 44
bool updateCurrentComment(PFileParser & parser, std::string & currentComment){
	if(parser.isMatch("//")){
		currentComment = "//" + parser.getUntilKeyWithoutPatern("\n");
	}else if(parser.isMatch("/*")){
		currentComment = "/*" + parser.getUntilKey("*/");
	}else{
		return false;
Pierre Aubert's avatar
Pierre Aubert committed
45
	}
46
	return true;
Pierre Aubert's avatar
Pierre Aubert committed
47 48 49 50 51 52 53 54
}

///Parse a PClassConfig
/**	@param[out] config : PClassConfig
 * 	@param[out] parser : file parser
 * 	@param[out] currentComment : current commet
 * 	@return true on success, false otherwise
*/
55 56 57
bool parseClassConfigAttribut(PClassConfig & config,  PFileParser & parser, std::string & currentComment){
	parser.skipWhiteSpace();
	std::string attribut(eraseCharsInStr(parser.getUntilKeyWithoutPatern(";"), "\n"));
Pierre Aubert's avatar
Pierre Aubert committed
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
	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
 * 	@return true on success, false otherwise
*/
75 76 77 78 79 80 81 82 83 84 85 86 87 88
bool parseParentOfClassConfig(PClassConfig & config, PFileParser & parser){
	if(!parser.isMatch("(")) return true;
	
	while(!parser.isEndOfFile() && parser.isMatch(")")){
		std::string parentDef(getClassName(parser));
		if(parentDef == ""){
			break;
		}
		config.addParentClass(parentDef);
		if(parser.isMatch(")")){break;}
		
		if(!parser.isMatch(",")){
			errorUnexpectedToken(parser, parser.getNextToken());
			return false;
Pierre Aubert's avatar
Pierre Aubert committed
89 90 91 92 93 94 95 96 97 98 99
		}
	}
	return true;
}

///Parse a PClassConfig
/**	@param[out] listClassConfig : list of PClassConfig
 * 	@param[out] parser : file parser
 * 	@param[out] currentComment : current commet
 * 	@return true on success, false otherwise
*/
100
bool parsePClassConfig(std::list<PClassConfig> & listClassConfig, PFileParser & parser, std::string & currentComment){
Pierre Aubert's avatar
Pierre Aubert committed
101
	PClassConfig config;
102 103 104
	std::string className(getClassName(parser));
	std::cout << "parsePClassConfig : find className : '"<<className<<"'" << std::endl;
	config.setName(className);
Pierre Aubert's avatar
Pierre Aubert committed
105 106
	config.setClassDocumentation(currentComment);
	currentComment = "";
107 108 109
	parser.skipWhiteSpace();
	
	if(!parseParentOfClassConfig(config, parser)){
Pierre Aubert's avatar
Pierre Aubert committed
110 111 112 113 114 115 116 117
		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;
	}
118 119 120 121 122 123
	if(!parser.isMatch("{")){
		errorUnexpectedToken(parser, parser.getNextToken());
		std::cerr << "\tExpect '{' after class name '"<<className<<"'" << std::endl;
		return false;
	}
	
Pierre Aubert's avatar
Pierre Aubert committed
124 125
	bool searchingData(true);
	while(!parser.isEndOfFile() && searchingData){
126
		if(parser.isMatchRewind("}")){
Pierre Aubert's avatar
Pierre Aubert committed
127
				searchingData = false;
128 129 130 131
		}else if(updateCurrentComment(parser, currentComment)){}
		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, currentComment)){
				errorUnexpectedToken(parser, parser.getNextToken());
Pierre Aubert's avatar
Pierre Aubert committed
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
				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;
149 150
	parser.setWhiteSpace(" \t\n");
	parser.setSeparator("{};/*");
Pierre Aubert's avatar
Pierre Aubert committed
151 152
	if(!parser.open(fileName)) return false;
	std::string currentComment("");
153 154 155 156 157 158 159 160 161
	while(!parser.isEndOfFile() && !parser.isMatch("}")){
		if(parser.isMatch("#")){
			if(parser.isMatch("include")){
				listInclude.push_back(eraseCharsInStr(parser.getUntilKeyWithoutPatern("\n")," \t\n"));
			}
		}else if(updateCurrentComment(parser, currentComment)){}
		else{		//Si ce n'est pas un séparateur, c'est que l'on a trouvé un nom, de PClassConfig
			if(!parsePClassConfig(listClassConfig, parser, currentComment)){
				errorUnexpectedToken(parser, parser.getNextToken());
Pierre Aubert's avatar
Pierre Aubert committed
162 163 164
				return false;
			}
		}
165
		parser.skipWhiteSpace();
Pierre Aubert's avatar
Pierre Aubert committed
166 167 168 169 170 171 172
	}
	return true;
}

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