21 #ifndef DOXYGEN_NOTFOR_DEVEL
33 ParserError(
int err=0,
int lin=0,
int cha=0):errorNumber(err),lineInFile(lin),charInLine(cha) {}
44 std::pair<long, long> range;
47 enum TLPToken { BOOLTOKEN,ENDOFSTREAM,STRINGTOKEN,INTTOKEN,DOUBLETOKEN,IDTOKEN,ERRORINFILE,OPENTOKEN,CLOSETOKEN,COMMENTTOKEN,RANGETOKEN};
49 struct TLPTokenParser {
53 TLPTokenParser(std::istream &i):curLine(0),curChar(0),is(i) {}
54 TLPToken nextToken(TLPValue &val,
int &curPos) {
56 bool endOfStream=
false,strGet=
false,slashMode=
false,started=
false,stop=
false,strComment=
false;
59 while ( (!stop) && (endOfStream=!(is.get(ch).fail()))) {
136 if (started) stop=
true;
145 if (started) stop=
true;
151 if (!started)
return OPENTOKEN;
162 if (!started)
return CLOSETOKEN;
202 if (!started && !endOfStream)
return ENDOFSTREAM;
205 const char *cstr = val.str.c_str();
207 long resultl= strtol(cstr, &endPtr, 10);
212 unsigned long strlength = val.str.length();
214 if (endPtr==(cstr+ strlength)) {
220 if (endPtr > cstr && (cstr + strlength) > (endPtr + 2)) {
221 val.range.first = resultl;
223 if ((endPtr[0] ==
'.') && (endPtr[1] ==
'.')) {
224 char* beginPtr = endPtr + 2;
226 resultl = strtol(beginPtr, &endPtr, 10);
231 if (endPtr == (cstr + strlength)) {
232 if (resultl < val.range.first)
235 val.range.second = resultl;
243 double resultd=strtod(cstr, &endPtr);
248 if (endPtr==(cstr + strlength)) {
253 if (strcasecmp(cstr,
"true")==0) {
258 if (strcasecmp(cstr,
"false")==0) {
263 if (started)
return STRINGTOKEN;
270 virtual ~TLPBuilder() {}
271 virtual bool addBool(
const bool)=0;
272 virtual bool addInt(
const int)=0;
273 virtual bool addRange(
int,
int)=0;
274 virtual bool addDouble(
const double)=0;
275 virtual bool addString(
const std::string &)=0;
276 virtual bool addStruct(
const std::string&,TLPBuilder*&)=0;
277 virtual bool close() =0;
278 virtual bool canRead() {
281 virtual bool read(std::istream&) {
286 struct TLPTrue:
public TLPBuilder {
287 bool addBool(
const bool) {
290 bool addInt(
const int) {
293 bool addRange(
int,
int) {
296 bool addDouble(
const double) {
299 bool addString(
const std::string &) {
302 bool addStruct(
const std::string& , TLPBuilder*&newBuilder) {
303 newBuilder=
new TLPTrue();
311 struct TLPFalse:
public TLPBuilder {
312 bool addBool(
const bool) {
315 bool addInt(
const int) {
318 bool addRange(
int,
int) {
321 bool addDouble(
const double) {
324 bool addString(
const std::string &) {
327 bool addStruct(
const std::string& , TLPBuilder*&newBuilder) {
328 newBuilder=
new TLPFalse();
336 template <
bool displayComment>
338 std::list<TLPBuilder *> builderStack;
339 std::istream &inputStream;
340 TLPTokenParser *tokenParser;
341 PluginProgress *pluginProgress;
344 TLPParser(std::istream &inputStream,TLPBuilder *builder,PluginProgress *pluginProgress,
int size): inputStream(inputStream),
345 pluginProgress(pluginProgress),
348 builderStack.push_front(builder);
352 while (!builderStack.empty()) {
353 TLPBuilder *builder = builderStack.front();
354 builderStack.pop_front();
356 if (builderStack.empty() || builder != builderStack.front())
362 std::stringstream ess;
363 ess <<
"Error when parsing char " << tokenParser->curChar
364 <<
" at line " << tokenParser->curLine + 1;
367 ess << std::endl << strerror(errno);
369 pluginProgress->setError(ess.str());
374 TLPTokenParser tParser(inputStream);
375 tokenParser= &tParser;
376 TLPToken currentToken;
377 TLPValue currentValue;
379 while ((currentToken=tokenParser->nextToken(currentValue,curPos))!=ENDOFSTREAM) {
380 if (curPos%2000==1)
if (pluginProgress->progress(curPos,fileSize)!=
TLP_CONTINUE)
383 switch (currentToken) {
385 currentToken=tokenParser->nextToken(currentValue,curPos);
387 if (currentToken!=STRINGTOKEN)
388 return formatError();
390 TLPBuilder *newBuilder;
392 if (builderStack.front()->addStruct(currentValue.str, newBuilder)) {
393 builderStack.push_front(newBuilder);
395 if (newBuilder->canRead())
396 if (!newBuilder->read(inputStream))
397 return formatError();
400 return formatError();
406 if (!builderStack.front()->addBool(currentValue.boolean))
407 return formatError();
413 if (!builderStack.front()->addInt(currentValue.integer))
414 return formatError();
420 if (!builderStack.front()->addRange(currentValue.range.first,
421 currentValue.range.second))
422 return formatError();
428 if (!builderStack.front()->addDouble(currentValue.real))
429 return formatError();
435 if (!builderStack.front()->addString(currentValue.str))
436 return formatError();
442 if (builderStack.front()->close()) {
443 TLPBuilder * builder = builderStack.front();
444 builderStack.pop_front();
446 if (builder != builderStack.front())
450 return formatError();
455 return formatError();
462 if (displayComment) tlp::debug() <<
"Comment line:" << tokenParser->curLine <<
"->" << currentValue.str;
478 #endif // DOXYGEN_NOTFOR_DEVEL