PhoenixYml  1.2.2
Yml parser for Phoenix
Loading...
Searching...
No Matches
parser_yml.cpp
Go to the documentation of this file.
1/***************************************
2 Auteur : Pierre Aubert
3 Mail : pierre.aubert@lapp.in2p3.fr
4 Licence : CeCILL-C
5****************************************/
6
7#include "PFileParser.h"
8#include "vec_value_utils.h"
9
10#include "parser_yml.h"
11
27
29
32 PYmlParserData data;
33 data.isRun = true;
34 data.compactMode = false;
35 data.currentLine = 1lu;
36 data.currentText = "";
37 data.currentlyParsedKeyValue = NULL;
38 return data;
39}
40
41bool parse_yml_all(VecValue & parent, PFileParser & parser, PYmlParserData & data);
42
44
47 data.isRun = false;
48}
49
51
54 return data.isRun;
55}
56
58
61void parse_yml_updateIndentation(std::vector<size_t> & vecIndentation, size_t currentIndentation){
62 if(currentIndentation == 0lu || vecIndentation.size() == 0lu){ //If there is no indentation
63 vecIndentation.clear();
64 vecIndentation.push_back(currentIndentation);
65 return;
66 }
67 std::vector<size_t> vecOutIndentation;
68 std::vector<size_t>::const_iterator it(vecIndentation.begin());
69 bool isCurrentLower(true);
70 while(isCurrentLower && it != vecIndentation.end()){ //Get previous indentation until the current one
71 isCurrentLower = *it < currentIndentation;
72 if(isCurrentLower){
73 vecOutIndentation.push_back(*it);
74 }
75 ++it;
76 }
77 vecOutIndentation.push_back(currentIndentation); //Add the current indentation
78 vecIndentation = vecOutIndentation;
79}
80
82
85void parse_yml_incrementCurrentChar(PFileParser & parser, PYmlParserData & data){
86 //If nothing is known I need to save the current char in the MACRO TEXT
87 char ch = parser.getCurrentCh();
88 data.currentText += ch;
89 parser.getNextChar();
90}
91
93
96 PString value(data.currentText.eraseFirstLastChar(" \t\n"));
97
98 if(data.currentlyParsedKeyValue != NULL && value != ""){
100 }
101 data.currentText = "";
102}
103
105
109bool parse_yml_key(PString & key, size_t & keyIndentation, PFileParser & parser){
110 parser.pushPosition();
111 PString possibleKey(parser.getStrComposedOf("_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"));
112 if(possibleKey != "" && parser.isMatch(":")){
113 key = possibleKey;
114 keyIndentation = parser.getColumn() - possibleKey.size() - 1lu;
115 return true;
116 }
117 parser.popPosition();
118 return false;
119}
120
122
125bool parse_yml_string(PString & str, PFileParser & parser){
126 if(parser.isMatch("\"")){
127 str = "\"" + parser.getUntilKey("\"");
128 }else if(parser.isMatch("'")){
129 str = "'" + parser.getUntilKey("'");
130 }else{
131 return false;
132 }
133 return true;
134}
135
137
140void parse_yml_dicoSetValue(VecValue * vecVal, const PString & value){
141 if(vecVal == NULL){return;}
142 vecVal->setValue(value);
144}
145
147
150bool parse_yml_stringValue(PFileParser & parser, PYmlParserData & data){
151 if(parser.isMatch("\'")){
152 PString str("\'" + parser.getUntilKey("\'"));
154 }else if(parser.isMatch("\"")){
155 PString str("\"" + parser.getUntilKey("\""));
157 }else{
158// PString strValue(parser.getStrComposedOf("_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789%$£?.*/+=-&~#(){}[]|!<>@°"));
159// parser.skipWhiteSpace();
160// PString strValue(parser.getStrComposedOf("_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789{}§"));
161// if(strValue != ""){
162// parse_yml_dicoSetValue(data.currentlyParsedKeyValue, strValue);
163// }else{
164 return false;
165// }
166 }
167 return true;
168}
169
171
175bool parse_yml_compactDicoContent(VecValue & parent, PFileParser & parser, PYmlParserData & data){
176 if(!parser.isMatch("{", "$§_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/*+-.")){return false;}
177 std::vector<size_t> saveVecIndentation = data.vecIndentation;
179 bool oldMode = data.compactMode;
180 data.compactMode = true;
181
182 VecValue & dico = *data.currentlyParsedKeyValue;
183 data.vecIndentation.clear();
184 data.vecIndentation.push_back(0lu);
185 parser.getStrComposedOf(" \t\n"); //Skip all blank characters
186 while(parse_yml_isParse(data) && !parser.isMatch("}")){
187 if(!parse_yml_all(dico, parser, data)){
188 std::cerr << "parse_yml_compactDicoContent : error at " << parser.getLocation() << std::endl;
189 std::cerr << "\tunexpected token '"<<parser.getNextToken()<<"'" << std::endl;
191 }
192 parser.isMatch(","); //Skip comma if there is one
193 }
195 data.vecIndentation = saveVecIndentation;
196 data.compactMode = oldMode;
197 return true;
198}
199
201
205bool parse_yml_dicoContent(VecValue & parent, PFileParser & parser, PYmlParserData & data){
206 parser.pushPosition();
207 PString keyName("");
208 size_t keyIndentation(0lu);
209 if(!parse_yml_key(keyName, keyIndentation, parser)){ //Check if there is a key
210 parser.popPosition(); //This is not a key
211 return false;
212 }
214 VecValue dico;
215 dico.setKey(keyName);
217 if(data.compactMode){
218 keyIndentation = -1lu;
219 }
220 dico.setIndentation(keyIndentation);
221 //Add the dico into its parent and get back the pointer of the current dico we want to fill
222 VecValue * ptrDico = addChildToParentVecValue(parent, data.vecIndentation, data.compactMode, dico, keyIndentation);
223
224 //Update indentation to be used to fill the VecValue in the current dico
225 parse_yml_updateIndentation(data.vecIndentation, keyIndentation);
226
228 data.currentlyParsedKeyValue = ptrDico;
229
230 //We do not need to parse the dico content, because its content will depend on what comes next (key, value, list)
231
232 //OK, on pourrait dire que les dicos se regroupent par leur indentation donc ça fonctionne
233 //Et que les valeurs associée (string, listes) sont ajoutées en utilisant data.currentlyParsedKeyValue
234
235 return true;
236}
237
239
243bool parse_yml_compactListContent(VecValue & parent, PFileParser & parser, PYmlParserData & data){
244 if(!parser.isMatch("[")){return false;}
246 VecVecValue & listValue = data.currentlyParsedKeyValue->getVecChild();
247
248 while(parse_yml_isParse(data) && !parser.isMatch("]") && !parser.isEndOfFile()){
249 PString tmpStr("");
250 if(parse_yml_string(tmpStr, parser)){
251 VecValue vecTmp;
252 vecTmp.setValue(tmpStr);
253 listValue.push_back(vecTmp);
254 }else{
255 while(parse_yml_isParse(data) && !parser.isMatchRewind("]") && !parser.isMatchRewind(",") && !parser.isEndOfFile()){
256 parse_yml_incrementCurrentChar(parser, data);
257 }
258 VecValue vecTmp;
259 vecTmp.setValue(data.currentText.eraseFirstChar(" \t\n"));
260 listValue.push_back(vecTmp);
261 data.currentText = "";
262 }
263
264 // Vérification de fin de fichier avant de continuer
265 if(parser.isEndOfFile()){
267 std::cerr << "parse_yml_compactListContent : error at " << parser.getLocation() << std::endl;
268 std::cerr << "\tunexpected end of file, missing ']'" << std::endl;
269 return false;
270 }
271
272 if(!parser.isMatch(",") && !parser.isMatchRewind("]")){
274 std::cerr << "parser_yml_fileParser : error at " << parser.getLocation() << std::endl;
275 std::cerr << "\tunexpected token '"<<parser.getNextToken()<<"'" << std::endl;
276 std::cerr << "\texpected token ',' or ']'" << std::endl;
277 return false;
278 }
279 }
280
281 // Si on sort de la boucle sans avoir trouvé ']' et qu'on est à la fin du fichier
282 if(parser.isEndOfFile() && !parser.isMatchRewind("]")){
284 std::cerr << "parse_yml_compactListContent : error - missing closing ']'" << std::endl;
285 return false;
286 }
287
288 return true;
289}
290
292
296bool parse_yml_listContent(VecValue & parent, PFileParser & parser, PYmlParserData & data){
297 if(!parser.isMatch("- ")){return false;} //There is no extra space, this is exactly the syntax
298 size_t currentIndentation(parser.getColumn() - 1lu);
300 VecValue dashList;
301 dashList.setKey("");
303 dashList.setIndentation(currentIndentation);
304// std::cerr << "parse_yml_listContent : Add LIST_ITEM at " << parser.getLocation() << std::endl;
305 //Add the dico into its parent and get back the pointer of the current dico we want to fill
306 VecValue * ptrDashList = addChildToParentVecValueAddListItem(parent, data.vecIndentation, data.compactMode, dashList, currentIndentation);
307
308 //Update indentation to be used to fill the VecValue in the current dico
309 parse_yml_updateIndentation(data.vecIndentation, currentIndentation);
310
312 data.currentlyParsedKeyValue = ptrDashList;
313 return true;
314}
315
317
321bool parse_yml_all(VecValue & parent, PFileParser & parser, PYmlParserData & data){
322 if(parser.isMatch("#")){parser.getUntilKeyWithoutPatern("\n");} //Skip the comment
323 else if(parse_yml_compactListContent(parent, parser, data)){}
324 else if(parse_yml_compactDicoContent(parent, parser, data)){}
325 else if(parse_yml_listContent(parent, parser, data)){}
326 else if(parse_yml_dicoContent(parent, parser, data)){}
327 else if(parse_yml_stringValue(parser, data)){}
328 else{
329 parse_yml_incrementCurrentChar(parser, data);
330 }
331 return true;
332}
333
335
339bool parser_yml_fileParser(VecValue & dico, PFileParser & parser){
341 data.currentlyParsedKeyValue = &dico;
342 parser.getStrComposedOf(" \t\n"); //Skip all blank characters
343 while(!parser.isEndOfFile() && parse_yml_isParse(data)){
344 if(!parse_yml_all(dico, parser, data)){
345 std::cerr << "parser_yml_fileParser : error at " << parser.getLocation() << std::endl;
346 std::cerr << "\tunexpected token '"<<parser.getNextToken()<<"'" << std::endl;
348 }
349 }
351 return data.isRun;
352}
353
355
359bool parser_yml_parseVecValue(VecValue & dico, const PPath & fileName){
360 PFileParser parser;
361 parser.setWhiteSpace("");
362 parser.setSeparator(":-'\",{}[]>|#");
363 parser.setEscapeChar('\\');
364 if(!parser.open(fileName)){
365 std::cerr << "parser_yml_parseVecValue : cannot open file '"<<fileName<<"'" << std::endl;
366 return false;
367 }
369 dico.setIndentation(parser.getLocation().getColumn());
370 return parser_yml_fileParser(dico, parser);
371}
372
374
378bool parser_yml(DicoValue & dico, const PPath & fileName){
379 VecValue vecValue;
380 bool b(parser_yml_parseVecValue(vecValue, fileName));
381 vecValueToDicoValue(dico, vecValue);
382 return b;
383}
384
386
390bool parser_yml(ConfigNode & dico, const PPath & fileName){
391 VecValue vecValue;
392 bool b(parser_yml_parseVecValue(vecValue, fileName));
393 vecValueToConfigNode(dico, vecValue);
394 return b;
395}
396
398
402bool parser_ymlString(ConfigNode & node, const PString & fileContent){
403 PFileParser parser;
404 parser.setWhiteSpace("");
405 parser.setSeparator(":-'\",{}[]>|#");
406 parser.setEscapeChar('\\');
407 parser.setFileContent(fileContent);
408 VecValue vecValue;
409 vecValue.setType(VecValueType::MAIN);
410 vecValue.setIndentation(parser.getLocation().getColumn());
411 bool b = parser_yml_fileParser(vecValue, parser);
412 vecValueToConfigNode(node, vecValue);
413
414 return b;
415}
Vector of keys and values.
Definition VecValue.h:15
void setIndentation(size_t indentation)
Sets the indentation of the VecValue.
Definition VecValue.cpp:69
void setValue(const PString &value)
Sets the value of the VecValue.
Definition VecValue.cpp:41
void setKey(const PString &key)
Sets the key of the VecValue.
Definition VecValue.cpp:48
const std::vector< VecValue > & getVecChild() const
Gets the vecChild of the VecValue.
Definition VecValue.cpp:104
void setType(const VecValueType::VecValueType &type)
Sets the type of the VecValue.
Definition VecValue.cpp:62
bool parser_yml_fileParser(VecValue &dico, PFileParser &parser)
Parse a yml file and update the given VecValue.
bool parse_yml_compactDicoContent(VecValue &parent, PFileParser &parser, PYmlParserData &data)
Parse compact dico content.
void parse_yml_incrementCurrentChar(PFileParser &parser, PYmlParserData &data)
Increment the current character.
bool parser_yml_parseVecValue(VecValue &dico, const PPath &fileName)
Parse a VecValue from a file.
bool parse_yml_dicoContent(VecValue &parent, PFileParser &parser, PYmlParserData &data)
Parse dico content.
void parse_yml_dicoSetValue(VecValue *vecVal, const PString &value)
Set a value into a VecValue.
void parse_yml_updateIndentation(std::vector< size_t > &vecIndentation, size_t currentIndentation)
Update the indentation vector by respect to the given indentation.
bool parse_yml_listContent(VecValue &parent, PFileParser &parser, PYmlParserData &data)
Parse dico content.
bool parser_yml(DicoValue &dico, const PPath &fileName)
Parse a yml file and update the given DicoValue.
void parse_yml_playCurrentText(PYmlParserData &data)
Play the current parsed text.
bool parse_yml_compactListContent(VecValue &parent, PFileParser &parser, PYmlParserData &data)
Parse compact dico content.
PYmlParserData default_PYmlParserData()
Default value of PYmlParserData.
void parse_yml_stopParsing(PYmlParserData &data)
Stop the file parsing.
bool parser_ymlString(ConfigNode &node, const PString &fileContent)
Parse a toml string.
bool parse_yml_string(PString &str, PFileParser &parser)
Parse string value.
bool parse_yml_stringValue(PFileParser &parser, PYmlParserData &data)
Parse compact dico content.
bool parse_yml_isParse(const PYmlParserData &data)
Say if the file parsing is enable.
bool parse_yml_all(VecValue &parent, PFileParser &parser, PYmlParserData &data)
Parse all yml features.
bool parse_yml_key(PString &key, size_t &keyIndentation, PFileParser &parser)
Parse key.
Data used to parse a yml file.
bool compactMode
True if the compact mode is activated.
bool isRun
True to continue the parsing, false to stop.
size_t currentLine
Current line number.
std::vector< size_t > vecIndentation
Vector of previous line indentations.
PString currentText
Current parsed text.
VecValue * currentlyParsedKeyValue
Currently parsed key value.
VecValue * addChildToParentVecValueAddListItem(VecValue &mainVecValue, const std::vector< size_t > &vecIndentation, bool isCompactMode, const VecValue &child, size_t currentIndentation)
Add the given child to the main VecValue and return a pointer to the added child.
void vecValueToConfigNode(ConfigNode &dicoValue, const VecValue &vecVal, bool isMainValue)
Convert a VecValue into a ConfigNode.
VecValue * addChildToParentVecValue(VecValue &mainVecValue, const std::vector< size_t > &vecIndentation, bool isCompactMode, const VecValue &child, size_t currentIndentation)
Add the given child to the main VecValue and return a pointer to the added child.
void vecValueToDicoValue(DicoValue &dicoValue, const VecValue &vecVal, bool isMainValue)
Convert a VecValue into a DicoValue.
std::vector< VecValue > VecVecValue