PhoenixGenerator  2.0.0
Set of tools to generate code
parserClassConfig.cpp
Go to the documentation of this file.
1 
2 /***************************************
3  Auteur : Pierre Aubert
4  Mail : pierre.aubert@lapp.in2p3.fr
5  Licence : CeCILL-C
6 ****************************************/
7 
8 #include <iostream>
10 #include "parserClassConfig.h"
11 #include "saveClassConfigTest.h"
12 #include "saveClassConfig.h"
14 
17 void errorUnexpectedToken(const PFileParser & parser, const PString & token){
18  std::cerr << "errorUnexpectedToken : '" << parser.getFileName() << "' line " << parser.getLine() << std::endl;
19  std::cerr << "unexpected token '" << token << "'" << std::endl;
20 }
21 
23 
27  return parser.getStrComposedOf("_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
28 }
29 
31 
35 bool updateCurrentComment(PFileParser & parser, PString & currentComment){
36  if(parser.isMatch("//")){
37  if(currentComment != ""){currentComment += "\n";}
38  currentComment += "//" + parser.getUntilKeyWithoutPatern("\n");
39  }else if(parser.isMatch("/*")){
40  if(currentComment != ""){currentComment += "\n";}
41  currentComment += "/*" + parser.getUntilKey("*/");
42  }else{
43  return false;
44  }
45  return true;
46 }
47 
49 
53 bool updateCurrentTemplate(PFileParser & parser, PVecString & currentTemplate){
54  if(!parser.isMatch("template")){return false;}
55  if(!parser.isMatch("<")){return false;}
56 
57  currentTemplate = parser.getUntilKeyWithoutPaternRecurse(">", "<").split(',');
58 
59  return true;
60 }
61 
63 
68 bool parseClassConfigAttribut(PClassConfig & config, PFileParser & parser, PString & currentComment){
69  parser.skipWhiteSpace();
70  PString attribut(parser.getUntilKeyWithoutPatern(";").eraseChar("\n"));
71  PVecString listToken(attribut.split(" \n\t"));
72  PString attributName(listToken.back());
73  listToken.pop_back();
74  PString attributType("");
75  for(PVecString::iterator it(listToken.begin()); it != listToken.end(); ++it){
76  attributType += *it + " ";
77  }
78  attributType = attributType.eraseFirstLastChar(" \n\t");
79  config.addAttribute(createClassAttribute(attributType, attributName, currentComment));
80  currentComment = "";
81  return true;
82 }
83 
85 
90  if(!parser.isMatch("(")) return true;
91 
92  while(!parser.isEndOfFile() && parser.isMatch(")")){
93  PString parentDef(getClassName(parser));
94  if(parentDef == ""){
95  break;
96  }
97  config.addParentClass(parentDef);
98  if(parser.isMatch(")")){break;}
99 
100  if(!parser.isMatch(",")){
101  errorUnexpectedToken(parser, parser.getNextToken());
102  return false;
103  }
104  }
105  return true;
106 }
107 
109 
114 bool parseEnumValue(PClassConfig & config, PFileParser & parser, PString & currentComment){
115  PString enumValue(getClassName(parser)), value("");
116  if(!parser.isMatch("=")){
117  value = parser.getStrComposedOf("0123456789xu");
118  }
119  PClassAttribute attr(createClassAttribute("int /* just to remember*/", enumValue, currentComment));
120  attr.setDefaultValue(value);
121  config.addAttribute(attr);
122  currentComment = "";
123  parser.isMatch(","); //We consume the comma if there is one
124  return true;
125 }
126 
128 
133 bool parseEnumConfig(std::vector<PClassConfig> & listClassConfig, PFileParser & parser, PString & currentComment){
134  if(!parser.isMatchToken("enum")){return false;}
135  PClassConfig config;
136  config.setIsEnum(true);
137  PString enumName(getClassName(parser)); //Get the name of the enum
138  std::cout << "parseEnumConfig : find enum : '"<<enumName<<"'" << std::endl;
139  config.setName(enumName);
140  config.setClassDocumentation(currentComment);
141  currentComment = "";
142  parser.skipWhiteSpace();
143  if(!parser.isMatch("{")){
144  errorUnexpectedToken(parser, parser.getNextToken());
145  std::cerr << "\tExpect '{' after enum name '"<<enumName<<"'" << std::endl;
146  return false;
147  }
148  bool searchingData(true);
149  while(!parser.isEndOfFile() && searchingData && !parser.isMatch("}")){
150  if(updateCurrentComment(parser, currentComment)){}
151  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
152  if(!parseEnumValue(config, parser, currentComment)){
153  errorUnexpectedToken(parser, parser.getNextToken());
154  return false;
155  }
156  }
157  }
158  listClassConfig.push_back(config);
159  return true;
160 }
161 
163 
169 bool parsePClassConfig(std::vector<PClassConfig> & listClassConfig, PFileParser & parser, PString & currentComment, PVecString & listTemplate){
170  PClassConfig config;
171  PString className(getClassName(parser));
172  std::cout << "parsePClassConfig : find className : '"<<className<<"'" << std::endl;
173  config.setName(className);
174  config.setClassDocumentation(currentComment);
175  config.setListTemplate(listTemplate);
176  currentComment = "";
177  listTemplate.clear();
178  parser.skipWhiteSpace();
179 
180  if(!parseParentOfClassConfig(config, parser)){
181  std::cerr << "parsePClassConfig : file '" << parser.getFileName() << "' line " << parser.getLine() << std::endl;
182  std::cerr << "\tmissing ')' : can't parse parents of the class '"<<config.getName()<<"'" << std::endl;
183  }
184  if(parser.isEndOfFile()){
185  std::cerr << "parsePClassConfig : file '" << parser.getFileName() << "' line " << parser.getLine() << std::endl;
186  std::cerr << "\tmissing '}'" << std::endl;
187  return false;
188  }
189  if(!parser.isMatch("{")){
190  errorUnexpectedToken(parser, parser.getNextToken());
191  std::cerr << "\tExpect '{' after class name '"<<className<<"'" << std::endl;
192  return false;
193  }
194 
195  bool searchingData(true);
196  while(!parser.isEndOfFile() && searchingData && !parser.isMatch("}")){
197  if(updateCurrentComment(parser, currentComment)){}
198  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
199  if(!parseClassConfigAttribut(config, parser, currentComment)){
200  errorUnexpectedToken(parser, parser.getNextToken());
201  return false;
202  }
203  }
204  }
205  listClassConfig.push_back(config);
206  return true;
207 }
208 
210 
215 bool parserClassConfig(std::vector<PClassConfig> & listClassConfig, PVecPath & listInclude, const PPath & fileName){
216  if(fileName == "") return false;
217  PFileParser parser;
218  parser.setWhiteSpace(" \t\n");
219  parser.setSeparator("{};/*");
220  if(!parser.open(fileName)) return false;
221  PString currentComment("");
222  PVecString listTemplate;
223  while(!parser.isEndOfFile()){
224  if(parser.isMatch("#")){
225  if(parser.isMatch("include")){
226  listInclude.push_back(parser.getUntilKeyWithoutPatern("\n").eraseChar(" \t\n"));
227  }
228  }else if(updateCurrentComment(parser, currentComment)){}
229  else if(updateCurrentTemplate(parser, listTemplate)){}
230  else if(parseEnumConfig(listClassConfig, parser, currentComment)){}
231  else{ //Si ce n'est pas un séparateur, c'est que l'on a trouvé un nom, de PClassConfig
232  if(!parsePClassConfig(listClassConfig, parser, currentComment, listTemplate)){
233  errorUnexpectedToken(parser, parser.getNextToken());
234  return false;
235  }
236  }
237  parser.skipWhiteSpace();
238  }
239  return true;
240 }
241 
242 
244 
253 bool saveParserClassConfig(const PPath & baseFileNameOutput, const PPath & fileName, bool enableDataStream, bool enableTypeStream, bool enableUnitTest, const PPath & testParentDir, const PString & libName){
254  PVecPath listInclude;
255  std::vector<PClassConfig> listClassConfig;
256  if(!parserClassConfig(listClassConfig, listInclude, fileName)){
257  std::cerr << "saveParserClassConfig : can't load file '" << fileName << "'" << std::endl;
258  return false;
259  }
260  if(!saveClassImplDecl( listClassConfig, baseFileNameOutput, listInclude, enableDataStream, enableTypeStream)){
261  std::cerr << "saveParserClassConfig : can't save files '" << baseFileNameOutput << "'[.h or .cpp]" << std::endl;
262  return false;
263  }
264  if(enableUnitTest){
265  PPath unitTestDir(testParentDir / PPath("TESTS"));
266  if(!saveClassTest(unitTestDir, libName, listClassConfig, baseFileNameOutput.getFileName(), enableDataStream, enableTypeStream)){
267  std::cerr << "saveParserClassConfig : can't save unit tests in directory'" << unitTestDir << "'" << std::endl;
268  return false;
269  }
270  }
271 
272  return true;
273 }
274 
std::vector< PPath > PVecPath
Definition: PPath.h:75
std::vector< PString > PVecString
Definition: PString.h:96
Describes a class attribute.
void setDefaultValue(const PString &defaultValue)
Sets the defaultValue of the PClassAttribute.
Class to describe a basic class.
Definition: PClassConfig.h:14
void addAttribute(const PClassAttribute &attribute)
Adds an attribute to the class.
void setClassDocumentation(const PString &classDocumentation)
Sets the class documentation.
void setIsEnum(bool isEnum)
Set if the current PClassConfig is an enum.
const PString & getName() const
Returns the class name.
void setName(const PString &name)
Sets the class name.
void addParentClass(const PString &parentClass)
Add a parent class to the PClassConfig.
void setListTemplate(const PVecString &listTemplate)
Sets the list of template of the class.
classe qui permet de parser des fichiers texte en renvoyant les tokens les uns après les autres
Definition: PFileParser.h:20
void setSeparator(const PString &separator)
Initialise la liste des caractères séparateurs.
Definition: PFileParser.cpp:43
size_t getLine() const
Fonction qui renvoie le numéro de la ligne courante.
bool open(const PPath &fileName)
Fonction qui ouvre le fichier que l'on va parser.
Definition: PFileParser.cpp:24
PString getNextToken()
Get the next token.
PString getUntilKeyWithoutPatern(const PString &patern)
Renvoie la chaine de caractère du caractère courant jusqu'à patern exclu.
PString getUntilKeyWithoutPaternRecurse(const PString &patern, const PString &beginPatern, const PString &allowedCharAfterBegin)
Get the string until end sequence and take account recursive patern (embeded strings)
PString getStrComposedOf(const PString &charset)
Get string composed of the characters in the string charset.
void setWhiteSpace(const PString &whiteSpace)
Initialise la liste des caractères blancs.
Definition: PFileParser.cpp:35
bool isMatchToken(const PString &patern)
Says if the patern match with the current caracters of the PFileParser but treats the string as a tok...
bool isMatch(const PString &patern)
Says if the patern match with the current caracters of the PFileParser.
PString getUntilKey(const PString &patern)
Renvoie la chaine de caractère du caractère courant jusqu'à patern comprise.
PPath getFileName() const
Fonction qui renvoie le nom du fichier que l'on a ouvert.
void skipWhiteSpace()
Skip the white space if there is at the current caracter position.
bool isEndOfFile() const
Dit si on est à la fin du fichier.
Definition: PFileParser.cpp:88
Path of a directory or a file.
Definition: PPath.h:17
PPath getFileName() const
Get the name of the file, from last char to /.
Definition: PPath.cpp:172
Extends the std::string.
Definition: PString.h:16
PString eraseChar(char ch) const
Erase char ch of current string.
Definition: PString.cpp:478
std::vector< PString > split(char separator) const
Cut a PString on the given separator char.
Definition: PString.cpp:420
PString eraseFirstLastChar(const PString &vecChar) const
Erase first and last char in a string.
Definition: PString.cpp:545
PClassAttribute createClassAttribute(const PString &type, const PString &name, const PString &documentation)
Creates a PClassAttribute.
bool updateCurrentComment(PFileParser &parser, PString &currentComment)
Fonction qui met à jour un commentaire.
bool parseEnumValue(PClassConfig &config, PFileParser &parser, PString &currentComment)
Parse enum attribute value.
bool parseEnumConfig(std::vector< PClassConfig > &listClassConfig, PFileParser &parser, PString &currentComment)
Parse an enum definition.
bool saveParserClassConfig(const PPath &baseFileNameOutput, const PPath &fileName, bool enableDataStream, bool enableTypeStream, bool enableUnitTest, const PPath &testParentDir, const PString &libName)
Parser list class config.
bool parseClassConfigAttribut(PClassConfig &config, PFileParser &parser, PString &currentComment)
Parse a PClassConfig.
bool parsePClassConfig(std::vector< PClassConfig > &listClassConfig, PFileParser &parser, PString &currentComment, PVecString &listTemplate)
Parse a PClassConfig.
bool parserClassConfig(std::vector< PClassConfig > &listClassConfig, PVecPath &listInclude, const PPath &fileName)
Parser list class config.
bool updateCurrentTemplate(PFileParser &parser, PVecString &currentTemplate)
Update a template definition.
bool parseParentOfClassConfig(PClassConfig &config, PFileParser &parser)
Parse the parents of the PClassConfig.
PString getClassName(PFileParser &parser)
Get class name from parser.
void errorUnexpectedToken(const PFileParser &parser, const PString &token)
Affiche une erreur de token non attendu.
bool saveClassTest(const PPath &outputTestDir, const PString &libName, const PClassConfig &classConfig, const PPath &baseFileName, bool enableDataStream, bool enableTypeStream)
Save the unit test of the generated PClassConfig.
bool saveClassImplDecl(const std::vector< PClassConfig > &classConfig, const PPath &baseFileName, const PVecPath &listInclude, bool enableDataStream, bool enableTypeStream)
Creates header file.