PhoenixYml  0.5.0
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("]")){
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(",")){
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 if(!parser.isMatch(",") && !parser.isMatchRewind("]")){
265 std::cerr << "parser_yml_fileParser : error at " << parser.getLocation() << std::endl;
266 std::cerr << "\tunexpected token '"<<parser.getNextToken()<<"'" << std::endl;
267 std::cerr << "\texpect token ',' or ']'" << std::endl;
268 return true;
269 }
270 }
271 return true;
272}
273
275
279bool parse_yml_listContent(VecValue & parent, PFileParser & parser, PYmlParserData & data){
280 if(!parser.isMatch("- ")){return false;} //There is no extra space, this is exactly the syntax
281 size_t currentIndentation(parser.getColumn() - 1lu);
283 VecValue dashList;
284 dashList.setKey("");
286 dashList.setIndentation(currentIndentation);
287// std::cerr << "parse_yml_listContent : Add LIST_ITEM at " << parser.getLocation() << std::endl;
288 //Add the dico into its parent and get back the pointer of the current dico we want to fill
289 VecValue * ptrDashList = addChildToParentVecValueAddListItem(parent, data.vecIndentation, data.compactMode, dashList, currentIndentation);
290
291 //Update indentation to be used to fill the VecValue in the current dico
292 parse_yml_updateIndentation(data.vecIndentation, currentIndentation);
293
295 data.currentlyParsedKeyValue = ptrDashList;
296 return true;
297}
298
300
304bool parse_yml_all(VecValue & parent, PFileParser & parser, PYmlParserData & data){
305 if(parser.isMatch("#")){parser.getUntilKeyWithoutPatern("\n");} //Skip the comment
306 else if(parse_yml_compactListContent(parent, parser, data)){}
307 else if(parse_yml_compactDicoContent(parent, parser, data)){}
308 else if(parse_yml_listContent(parent, parser, data)){}
309 else if(parse_yml_dicoContent(parent, parser, data)){}
310 else if(parse_yml_stringValue(parser, data)){}
311 else{
312 parse_yml_incrementCurrentChar(parser, data);
313 }
314 return true;
315}
316
318
322bool parser_yml_fileParser(VecValue & dico, PFileParser & parser){
324 data.currentlyParsedKeyValue = &dico;
325 parser.getStrComposedOf(" \t\n"); //Skip all blank characters
326 while(!parser.isEndOfFile() && parse_yml_isParse(data)){
327 if(!parse_yml_all(dico, parser, data)){
328 std::cerr << "parser_yml_fileParser : error at " << parser.getLocation() << std::endl;
329 std::cerr << "\tunexpected token '"<<parser.getNextToken()<<"'" << std::endl;
331 }
332 }
334 return data.isRun;
335}
336
337
339
343bool parser_yml(DicoValue & dico, const PPath & fileName){
344 PFileParser parser;
345 parser.setWhiteSpace("");
346 parser.setSeparator(":-'\",{}[]>|#");
347 parser.setEscapeChar('\\');
348 if(!parser.open(fileName)){
349 std::cerr << "parser_yml : cannot open file '"<<fileName<<"'" << std::endl;
350 return false;
351 }
352 VecValue vecValue;
353 vecValue.setType(VecValueType::MAIN);
354 vecValue.setIndentation(parser.getLocation().getColumn());
355 bool b(parser_yml_fileParser(vecValue, parser));
356 vecValueToDicoValue(dico, vecValue);
357 return b;
358}
359
360
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 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 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.
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