Directory: | ./ |
---|---|
File: | src/parserClassConfig.cpp |
Date: | 2025-04-25 19:10:50 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 109 | 147 | 74.1% |
Branches: | 171 | 362 | 47.2% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | |||
2 | /*************************************** | ||
3 | Auteur : Pierre Aubert | ||
4 | Mail : pierre.aubert@lapp.in2p3.fr | ||
5 | Licence : CeCILL-C | ||
6 | ****************************************/ | ||
7 | |||
8 | #include <iostream> | ||
9 | #include "class_attribute_utils.h" | ||
10 | #include "parserClassConfig.h" | ||
11 | #include "saveClassConfigTest.h" | ||
12 | #include "saveClassConfig.h" | ||
13 | ///Affiche une erreur de token non attendu | ||
14 | /** @param parser : file parser | ||
15 | * @param token : token qui pose problème | ||
16 | */ | ||
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 | |||
22 | ///Get class name from parser | ||
23 | /** @param parser : PFileParser to be used | ||
24 | * @return class name | ||
25 | */ | ||
26 | 33 | PString getClassName(PFileParser & parser){ | |
27 |
1/1✓ Branch 2 taken 33 times.
|
33 | return parser.getStrComposedOf("_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"); |
28 | } | ||
29 | |||
30 | ///Fonction qui met à jour un commentaire | ||
31 | /** @param parser : file parser | ||
32 | * @param currentComment : commentaire que l'on veut mettre à jour | ||
33 | * @return true si on l'a mis à jour, false sinon | ||
34 | */ | ||
35 | 198 | bool updateCurrentComment(PFileParser & parser, PString & currentComment){ | |
36 |
3/3✓ Branch 2 taken 198 times.
✓ Branch 5 taken 95 times.
✓ Branch 6 taken 103 times.
|
198 | if(parser.isMatch("//")){ |
37 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 95 times.
|
95 | if(currentComment != ""){currentComment += "\n";} |
38 |
3/3✓ Branch 2 taken 95 times.
✓ Branch 5 taken 95 times.
✓ Branch 8 taken 95 times.
|
95 | currentComment += "//" + parser.getUntilKeyWithoutPatern("\n"); |
39 |
2/3✓ Branch 2 taken 103 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 103 times.
|
103 | }else if(parser.isMatch("/*")){ |
40 | ✗ | if(currentComment != ""){currentComment += "\n";} | |
41 | ✗ | currentComment += "/*" + parser.getUntilKey("*/"); | |
42 | }else{ | ||
43 | 103 | return false; | |
44 | } | ||
45 | 95 | return true; | |
46 | } | ||
47 | |||
48 | ///Update a template definition | ||
49 | /** @param parser : file parser | ||
50 | * @param currentTemplate : template to be updated | ||
51 | * @return true on success, false otherwise | ||
52 | */ | ||
53 | 33 | bool updateCurrentTemplate(PFileParser & parser, PVecString & currentTemplate){ | |
54 |
3/3✓ Branch 2 taken 33 times.
✓ Branch 5 taken 29 times.
✓ Branch 6 taken 4 times.
|
33 | if(!parser.isMatch("template")){return false;} |
55 |
2/3✓ Branch 2 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
|
4 | if(!parser.isMatch("<")){return false;} |
56 | |||
57 |
3/3✓ Branch 2 taken 4 times.
✓ Branch 5 taken 4 times.
✓ Branch 8 taken 4 times.
|
4 | currentTemplate = parser.getUntilKeyWithoutPaternRecurse(">", "<").split(','); |
58 | |||
59 | 4 | return true; | |
60 | } | ||
61 | |||
62 | ///Parse a PClassConfig | ||
63 | /** @param[out] config : PClassConfig | ||
64 | * @param[out] parser : file parser | ||
65 | * @param[out] currentComment : current commet | ||
66 | * @return true on success, false otherwise | ||
67 | */ | ||
68 | 66 | bool parseClassConfigAttribut(PClassConfig & config, PFileParser & parser, PString & currentComment){ | |
69 |
1/1✓ Branch 1 taken 66 times.
|
66 | parser.skipWhiteSpace(); |
70 |
4/4✓ Branch 1 taken 66 times.
✓ Branch 4 taken 66 times.
✓ Branch 7 taken 66 times.
✓ Branch 10 taken 66 times.
|
132 | PString attribut(parser.getUntilKeyWithoutPatern(";").eraseChar("\n")); |
71 |
2/2✓ Branch 1 taken 66 times.
✓ Branch 4 taken 66 times.
|
66 | PVecString listToken(attribut.split(" \n\t")); |
72 |
1/1✓ Branch 2 taken 66 times.
|
66 | PString attributName(listToken.back()); |
73 | 66 | listToken.pop_back(); | |
74 |
1/1✓ Branch 1 taken 66 times.
|
66 | PString attributType(""); |
75 |
2/2✓ Branch 3 taken 74 times.
✓ Branch 4 taken 66 times.
|
140 | for(PVecString::iterator it(listToken.begin()); it != listToken.end(); ++it){ |
76 |
2/2✓ Branch 2 taken 74 times.
✓ Branch 5 taken 74 times.
|
74 | attributType += *it + " "; |
77 | } | ||
78 |
3/3✓ Branch 1 taken 66 times.
✓ Branch 4 taken 66 times.
✓ Branch 7 taken 66 times.
|
66 | attributType = attributType.eraseFirstLastChar(" \n\t"); |
79 |
2/2✓ Branch 1 taken 66 times.
✓ Branch 4 taken 66 times.
|
66 | config.addAttribute(createClassAttribute(attributType, attributName, currentComment)); |
80 |
1/1✓ Branch 1 taken 66 times.
|
66 | currentComment = ""; |
81 | 66 | return true; | |
82 | 66 | } | |
83 | |||
84 | ///Parse the parents of the PClassConfig | ||
85 | /** @param[out] config : PClassConfig | ||
86 | * @param[out] parser : file parser | ||
87 | * @return true on success, false otherwise | ||
88 | */ | ||
89 | 27 | bool parseParentOfClassConfig(PClassConfig & config, PFileParser & parser){ | |
90 |
2/3✓ Branch 2 taken 27 times.
✓ Branch 5 taken 27 times.
✗ Branch 6 not taken.
|
27 | 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 | |||
108 | ///Parse enum attribute value | ||
109 | /** @param[out] config : PClassConfig | ||
110 | * @param[out] parser : file parser | ||
111 | * @param[out] currentComment : current commet | ||
112 | * @return true on success, false otherwise | ||
113 | */ | ||
114 | 4 | bool parseEnumValue(PClassConfig & config, PFileParser & parser, PString & currentComment){ | |
115 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 4 taken 4 times.
|
4 | PString enumValue(getClassName(parser)), value(""); |
116 |
3/4✓ Branch 1 taken 4 times.
✓ Branch 4 taken 4 times.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
|
4 | if(!parser.isMatch("=")){ |
117 |
3/3✓ Branch 1 taken 4 times.
✓ Branch 4 taken 4 times.
✓ Branch 7 taken 4 times.
|
4 | value = parser.getStrComposedOf("0123456789xu"); |
118 | } | ||
119 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 4 taken 4 times.
|
4 | PClassAttribute attr(createClassAttribute("int /* just to remember*/", enumValue, currentComment)); |
120 |
1/1✓ Branch 1 taken 4 times.
|
4 | attr.setDefaultValue(value); |
121 |
1/1✓ Branch 1 taken 4 times.
|
4 | config.addAttribute(attr); |
122 |
1/1✓ Branch 1 taken 4 times.
|
4 | currentComment = ""; |
123 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 4 taken 4 times.
|
4 | parser.isMatch(","); //We consume the comma if there is one |
124 | 4 | return true; | |
125 | 4 | } | |
126 | |||
127 | ///Parse an enum definition | ||
128 | /** @param[out] listClassConfig : list of PClassConfig | ||
129 | * @param[out] parser : file parser | ||
130 | * @param[out] currentComment : current comment | ||
131 | * @return true on success, false otherwise | ||
132 | */ | ||
133 | 29 | bool parseEnumConfig(std::vector<PClassConfig> & listClassConfig, PFileParser & parser, PString & currentComment){ | |
134 |
4/4✓ Branch 1 taken 29 times.
✓ Branch 4 taken 29 times.
✓ Branch 7 taken 27 times.
✓ Branch 8 taken 2 times.
|
29 | if(!parser.isMatchToken("enum")){return false;} |
135 |
1/1✓ Branch 1 taken 2 times.
|
2 | PClassConfig config; |
136 |
1/1✓ Branch 1 taken 2 times.
|
2 | config.setIsEnum(true); |
137 |
1/1✓ Branch 1 taken 2 times.
|
2 | PString enumName(getClassName(parser)); //Get the name of the enum |
138 |
4/4✓ Branch 1 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 7 taken 2 times.
✓ Branch 10 taken 2 times.
|
2 | std::cout << "parseEnumConfig : find enum : '"<<enumName<<"'" << std::endl; |
139 |
1/1✓ Branch 1 taken 2 times.
|
2 | config.setName(enumName); |
140 |
1/1✓ Branch 1 taken 2 times.
|
2 | config.setClassDocumentation(currentComment); |
141 |
1/1✓ Branch 1 taken 2 times.
|
2 | currentComment = ""; |
142 |
1/1✓ Branch 1 taken 2 times.
|
2 | parser.skipWhiteSpace(); |
143 |
3/4✓ Branch 1 taken 2 times.
✓ Branch 4 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
|
2 | if(!parser.isMatch("{")){ |
144 | ✗ | errorUnexpectedToken(parser, parser.getNextToken()); | |
145 | ✗ | std::cerr << "\tExpect '{' after enum name '"<<enumName<<"'" << std::endl; | |
146 | ✗ | return false; | |
147 | } | ||
148 | 2 | bool searchingData(true); | |
149 |
10/15✓ Branch 1 taken 6 times.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 6 times.
✓ Branch 11 taken 6 times.
✓ Branch 13 taken 4 times.
✓ Branch 14 taken 2 times.
✓ Branch 15 taken 6 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 4 times.
✓ Branch 19 taken 2 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
6 | while(!parser.isEndOfFile() && searchingData && !parser.isMatch("}")){ |
150 |
2/3✓ Branch 1 taken 4 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
4 | 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 |
2/3✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
|
4 | if(!parseEnumValue(config, parser, currentComment)){ |
153 | ✗ | errorUnexpectedToken(parser, parser.getNextToken()); | |
154 | ✗ | return false; | |
155 | } | ||
156 | } | ||
157 | } | ||
158 |
1/1✓ Branch 1 taken 2 times.
|
2 | listClassConfig.push_back(config); |
159 | 2 | return true; | |
160 | 2 | } | |
161 | |||
162 | ///Parse a PClassConfig | ||
163 | /** @param[out] listClassConfig : list of PClassConfig | ||
164 | * @param[out] parser : file parser | ||
165 | * @param[out] currentComment : current comment | ||
166 | * @param[out] listTemplate : list of the template to be used in the defined class | ||
167 | * @return true on success, false otherwise | ||
168 | */ | ||
169 | 27 | bool parsePClassConfig(std::vector<PClassConfig> & listClassConfig, PFileParser & parser, PString & currentComment, PVecString & listTemplate){ | |
170 |
1/1✓ Branch 1 taken 27 times.
|
27 | PClassConfig config; |
171 |
1/1✓ Branch 1 taken 27 times.
|
27 | PString className(getClassName(parser)); |
172 |
4/4✓ Branch 1 taken 27 times.
✓ Branch 4 taken 27 times.
✓ Branch 7 taken 27 times.
✓ Branch 10 taken 27 times.
|
27 | std::cout << "parsePClassConfig : find className : '"<<className<<"'" << std::endl; |
173 |
1/1✓ Branch 1 taken 27 times.
|
27 | config.setName(className); |
174 |
1/1✓ Branch 1 taken 27 times.
|
27 | config.setClassDocumentation(currentComment); |
175 |
1/1✓ Branch 1 taken 27 times.
|
27 | config.setListTemplate(listTemplate); |
176 |
1/1✓ Branch 1 taken 27 times.
|
27 | currentComment = ""; |
177 | 27 | listTemplate.clear(); | |
178 |
1/1✓ Branch 1 taken 27 times.
|
27 | parser.skipWhiteSpace(); |
179 | |||
180 |
2/3✓ Branch 1 taken 27 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 27 times.
|
27 | 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 |
2/3✓ Branch 1 taken 27 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 27 times.
|
27 | 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 |
3/4✓ Branch 1 taken 27 times.
✓ Branch 4 taken 27 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 27 times.
|
27 | if(!parser.isMatch("{")){ |
190 | ✗ | errorUnexpectedToken(parser, parser.getNextToken()); | |
191 | ✗ | std::cerr << "\tExpect '{' after class name '"<<className<<"'" << std::endl; | |
192 | ✗ | return false; | |
193 | } | ||
194 | |||
195 | 27 | bool searchingData(true); | |
196 |
10/15✓ Branch 1 taken 159 times.
✓ Branch 3 taken 159 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 159 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 159 times.
✓ Branch 11 taken 159 times.
✓ Branch 13 taken 132 times.
✓ Branch 14 taken 27 times.
✓ Branch 15 taken 159 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 132 times.
✓ Branch 19 taken 27 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
159 | while(!parser.isEndOfFile() && searchingData && !parser.isMatch("}")){ |
197 |
3/3✓ Branch 1 taken 132 times.
✓ Branch 3 taken 66 times.
✓ Branch 4 taken 66 times.
|
132 | 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 |
2/3✓ Branch 1 taken 66 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 66 times.
|
66 | if(!parseClassConfigAttribut(config, parser, currentComment)){ |
200 | ✗ | errorUnexpectedToken(parser, parser.getNextToken()); | |
201 | ✗ | return false; | |
202 | } | ||
203 | } | ||
204 | } | ||
205 |
1/1✓ Branch 1 taken 27 times.
|
27 | listClassConfig.push_back(config); |
206 | 27 | return true; | |
207 | 27 | } | |
208 | |||
209 | ///Parser list class config | ||
210 | /** @param[out] listClassConfig : list of class config | ||
211 | * @param listInclude : list of include | ||
212 | * @param fileName : file name of the config | ||
213 | * @return true on success, false otherwise | ||
214 | */ | ||
215 | 21 | bool parserClassConfig(std::vector<PClassConfig> & listClassConfig, PVecPath & listInclude, const PPath & fileName){ | |
216 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
|
21 | if(fileName == "") return false; |
217 |
1/1✓ Branch 1 taken 21 times.
|
21 | PFileParser parser; |
218 |
2/2✓ Branch 1 taken 21 times.
✓ Branch 4 taken 21 times.
|
21 | parser.setWhiteSpace(" \t\n"); |
219 |
2/2✓ Branch 1 taken 21 times.
✓ Branch 4 taken 21 times.
|
21 | parser.setSeparator("{};/*"); |
220 |
2/3✓ Branch 1 taken 21 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 21 times.
|
21 | if(!parser.open(fileName)) return false; |
221 |
1/1✓ Branch 1 taken 21 times.
|
21 | PString currentComment(""); |
222 | 21 | PVecString listTemplate; | |
223 |
3/3✓ Branch 1 taken 91 times.
✓ Branch 3 taken 70 times.
✓ Branch 4 taken 21 times.
|
91 | while(!parser.isEndOfFile()){ |
224 |
4/4✓ Branch 1 taken 70 times.
✓ Branch 4 taken 70 times.
✓ Branch 7 taken 8 times.
✓ Branch 8 taken 62 times.
|
70 | if(parser.isMatch("#")){ |
225 |
3/4✓ Branch 1 taken 8 times.
✓ Branch 4 taken 8 times.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
|
8 | if(parser.isMatch("include")){ |
226 |
6/6✓ Branch 1 taken 8 times.
✓ Branch 4 taken 8 times.
✓ Branch 7 taken 8 times.
✓ Branch 10 taken 8 times.
✓ Branch 13 taken 8 times.
✓ Branch 16 taken 8 times.
|
8 | listInclude.push_back(parser.getUntilKeyWithoutPatern("\n").eraseChar(" \t\n")); |
227 | } | ||
228 |
3/3✓ Branch 1 taken 62 times.
✓ Branch 3 taken 33 times.
✓ Branch 4 taken 29 times.
|
62 | }else if(updateCurrentComment(parser, currentComment)){} |
229 |
3/3✓ Branch 1 taken 33 times.
✓ Branch 3 taken 29 times.
✓ Branch 4 taken 4 times.
|
33 | else if(updateCurrentTemplate(parser, listTemplate)){} |
230 |
3/3✓ Branch 1 taken 29 times.
✓ Branch 3 taken 27 times.
✓ Branch 4 taken 2 times.
|
29 | 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 |
2/3✓ Branch 1 taken 27 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 27 times.
|
27 | if(!parsePClassConfig(listClassConfig, parser, currentComment, listTemplate)){ |
233 | ✗ | errorUnexpectedToken(parser, parser.getNextToken()); | |
234 | ✗ | return false; | |
235 | } | ||
236 | } | ||
237 |
1/1✓ Branch 1 taken 70 times.
|
70 | parser.skipWhiteSpace(); |
238 | } | ||
239 | 21 | return true; | |
240 | 21 | } | |
241 | |||
242 | |||
243 | ///Parser list class config | ||
244 | /** @param baseFileNameOutput : base of the output files | ||
245 | * @param fileName : file name of the config | ||
246 | * @param enableDataStream : true to enable the serialization/deserialization with data | ||
247 | * @param enableTypeStream : true to test phoenix_getTypeName function | ||
248 | * @param enableUnitTest : true to enable unit tests | ||
249 | * @param testParentDir : parent directory of tests | ||
250 | * @param libName : name of the generated library to link with | ||
251 | * @return true on success, false otherwise | ||
252 | */ | ||
253 | 16 | bool saveParserClassConfig(const PPath & baseFileNameOutput, const PPath & fileName, bool enableDataStream, bool enableTypeStream, bool enableUnitTest, const PPath & testParentDir, const PString & libName){ | |
254 | 16 | PVecPath listInclude; | |
255 | 16 | std::vector<PClassConfig> listClassConfig; | |
256 |
2/3✓ Branch 1 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
|
16 | if(!parserClassConfig(listClassConfig, listInclude, fileName)){ |
257 | ✗ | std::cerr << "saveParserClassConfig : can't load file '" << fileName << "'" << std::endl; | |
258 | ✗ | return false; | |
259 | } | ||
260 |
2/3✓ Branch 1 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
|
16 | 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 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
|
16 | if(enableUnitTest){ |
265 |
3/3✓ Branch 1 taken 11 times.
✓ Branch 4 taken 11 times.
✓ Branch 7 taken 11 times.
|
22 | PPath unitTestDir(testParentDir / PPath("TESTS")); |
266 |
3/4✓ Branch 1 taken 11 times.
✓ Branch 4 taken 11 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 11 times.
|
11 | 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 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | } |
271 | |||
272 | 16 | return true; | |
273 | 16 | } | |
274 | |||
275 |