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 {
52 TLPTokenParser(std::istream &i):curLine(0),is(i) {}
54 bool newLine(
char ch,
int &curPos) {
70 TLPToken nextToken(TLPValue &val,
int &curPos) {
72 bool endOfStream=
false,strGet=
false,slashMode=
false,started=
false,stop=
false,strComment=
false;
75 while ( (!stop) && (endOfStream=!(is.get(ch).fail()))) {
82 if (!newLine(ch, curPos))
134 if (!newLine(ch, curPos))
149 if (started) stop=
true;
155 if (!newLine(ch, curPos))
158 if (started) stop=
true;
163 if (!started)
return OPENTOKEN;
173 if (!started)
return CLOSETOKEN;
213 if (!started && !endOfStream)
return ENDOFSTREAM;
216 const char *cstr = val.str.c_str();
218 long resultl= strtol(cstr, &endPtr, 10);
223 unsigned long strlength = val.str.length();
225 if (endPtr==(cstr+ strlength)) {
231 if (endPtr > cstr && (cstr + strlength) > (endPtr + 2)) {
232 val.range.first = resultl;
234 if ((endPtr[0] ==
'.') && (endPtr[1] ==
'.')) {
235 char* beginPtr = endPtr + 2;
237 resultl = strtol(beginPtr, &endPtr, 10);
242 if (endPtr == (cstr + strlength)) {
243 if (resultl < val.range.first)
246 val.range.second = resultl;
254 double resultd=strtod(cstr, &endPtr);
259 if (endPtr==(cstr + strlength)) {
264 if (strcasecmp(cstr,
"true")==0) {
269 if (strcasecmp(cstr,
"false")==0) {
274 if (started)
return STRINGTOKEN;
281 virtual ~TLPBuilder() {}
282 virtual bool addBool(
const bool)=0;
283 virtual bool addInt(
const int)=0;
284 virtual bool addRange(
int,
int)=0;
285 virtual bool addDouble(
const double)=0;
286 virtual bool addString(
const std::string &)=0;
287 virtual bool addStruct(
const std::string&,TLPBuilder*&)=0;
288 virtual bool close() =0;
289 virtual bool canRead() {
292 virtual bool read(std::istream&) {
297 struct TLPTrue:
public TLPBuilder {
298 bool addBool(
const bool) {
301 bool addInt(
const int) {
304 bool addRange(
int,
int) {
307 bool addDouble(
const double) {
310 bool addString(
const std::string &) {
313 bool addStruct(
const std::string& , TLPBuilder*&newBuilder) {
314 newBuilder=
new TLPTrue();
322 struct TLPFalse:
public TLPBuilder {
323 bool addBool(
const bool) {
326 bool addInt(
const int) {
329 bool addRange(
int,
int) {
332 bool addDouble(
const double) {
335 bool addString(
const std::string &) {
338 bool addStruct(
const std::string& , TLPBuilder*&newBuilder) {
339 newBuilder=
new TLPFalse();
347 template <
bool displayComment>
349 std::list<TLPBuilder *> builderStack;
350 std::istream &inputStream;
351 TLPTokenParser *tokenParser;
352 PluginProgress *pluginProgress;
355 TLPParser(std::istream &inputStream,TLPBuilder *builder,PluginProgress *pluginProgress,
int size): inputStream(inputStream),
356 pluginProgress(pluginProgress),
359 builderStack.push_front(builder);
363 while (!builderStack.empty()) {
364 TLPBuilder *builder = builderStack.front();
365 builderStack.pop_front();
367 if (builderStack.empty() || builder != builderStack.front())
372 bool formatError(
const std::string& value) {
373 std::stringstream ess;
374 ess <<
"Error when parsing '" << value.c_str()
375 <<
"' at line " << tokenParser->curLine + 1;
378 ess << std::endl << strerror(errno);
380 pluginProgress->setError(ess.str());
385 TLPTokenParser tParser(inputStream);
386 tokenParser= &tParser;
387 TLPToken currentToken;
388 TLPValue currentValue;
390 while ((currentToken=tokenParser->nextToken(currentValue,curPos))!=ENDOFSTREAM) {
391 if (curPos%2000==1)
if (pluginProgress->progress(curPos,fileSize)!=
TLP_CONTINUE)
394 switch (currentToken) {
396 currentToken=tokenParser->nextToken(currentValue, curPos);
398 if (currentToken!=STRINGTOKEN)
399 return formatError(currentValue.str);
401 TLPBuilder *newBuilder;
403 if (builderStack.front()->addStruct(currentValue.str, newBuilder)) {
404 builderStack.push_front(newBuilder);
406 if (newBuilder->canRead())
407 if (!newBuilder->read(inputStream))
408 return formatError(currentValue.str);
411 return formatError(currentValue.str);
417 if (!builderStack.front()->addBool(currentValue.boolean))
418 return formatError(currentValue.str);
424 if (!builderStack.front()->addInt(currentValue.integer))
425 return formatError(currentValue.str);
431 if (!builderStack.front()->addRange(currentValue.range.first,
432 currentValue.range.second))
433 return formatError(currentValue.str);
439 if (!builderStack.front()->addDouble(currentValue.real))
440 return formatError(currentValue.str);
446 if (!builderStack.front()->addString(currentValue.str))
447 return formatError(currentValue.str);
453 if (builderStack.front()->close()) {
454 TLPBuilder * builder = builderStack.front();
455 builderStack.pop_front();
457 if (builder != builderStack.front())
461 return formatError(currentValue.str);
466 return formatError(currentValue.str);
473 if (displayComment) tlp::debug() <<
"Comment line:" << tokenParser->curLine <<
"->" << currentValue.str;
483 pluginProgress->progress(fileSize,fileSize);
492 #endif // DOXYGEN_NOTFOR_DEVEL