33 ParserError(
int err = 0,
int lin = 0,
int cha = 0)
34 : errorNumber(err), lineInFile(lin), charInLine(cha) {}
45 std::pair<long, long> range;
62 struct TLPTokenParser {
65 TLPTokenParser(std::istream &i) : curLine(0), is(i) {}
67 bool newLine(
char ch,
int &curPos) {
83 TLPToken nextToken(TLPValue &val,
int &curPos) {
85 bool endOfStream =
false, strGet =
false, slashMode =
false, started =
false, stop =
false,
89 while ((!stop) && (endOfStream = !(is.get(ch).fail()))) {
96 if (!newLine(ch, curPos))
146 if (!newLine(ch, curPos))
168 if (!newLine(ch, curPos))
229 if (!started && !endOfStream)
232 char *endPtr =
nullptr;
233 const char *cstr = val.str.c_str();
235 long resultl = strtol(cstr, &endPtr, 10);
240 unsigned long strlength = val.str.length();
242 if (endPtr == (cstr + strlength)) {
243 val.integer = resultl;
248 if (endPtr > cstr && (cstr + strlength) > (endPtr + 2)) {
249 val.range.first = resultl;
251 if ((endPtr[0] ==
'.') && (endPtr[1] ==
'.')) {
252 char *beginPtr = endPtr + 2;
254 resultl = strtol(beginPtr, &endPtr, 10);
259 if (endPtr == (cstr + strlength)) {
260 if (resultl < val.range.first)
263 val.range.second = resultl;
271 double resultd = strtod(cstr, &endPtr);
276 if (endPtr == (cstr + strlength)) {
281 if (strcasecmp(cstr,
"true") == 0) {
286 if (strcasecmp(cstr,
"false") == 0) {
299 virtual ~TLPBuilder() {}
300 virtual bool addBool(
const bool) = 0;
301 virtual bool addInt(
const int) = 0;
302 virtual bool addRange(
int,
int) = 0;
303 virtual bool addDouble(
const double) = 0;
304 virtual bool addString(
const std::string &) = 0;
305 virtual bool addStruct(
const std::string &, TLPBuilder *&) = 0;
306 virtual bool close() = 0;
307 virtual bool canRead() {
310 virtual bool read(std::istream &) {
315 struct TLPTrue :
public TLPBuilder {
316 bool addBool(
const bool)
override {
319 bool addInt(
const int)
override {
322 bool addRange(
int,
int)
override {
325 bool addDouble(
const double)
override {
328 bool addString(
const std::string &)
override {
331 bool addStruct(
const std::string & , TLPBuilder *&newBuilder)
override {
332 newBuilder =
new TLPTrue();
335 bool close()
override {
340 struct TLPFalse :
public TLPBuilder {
341 bool addBool(
const bool)
override {
344 bool addInt(
const int)
override {
347 bool addRange(
int,
int)
override {
350 bool addDouble(
const double)
override {
353 bool addString(
const std::string &)
override {
356 bool addStruct(
const std::string & , TLPBuilder *&newBuilder)
override {
357 newBuilder =
new TLPFalse();
360 bool close()
override {
365 template <
bool displayComment>
367 std::list<TLPBuilder *> builderStack;
368 std::istream &inputStream;
369 TLPTokenParser *tokenParser;
370 PluginProgress *pluginProgress;
371 int fileSize, curPos;
373 TLPParser(std::istream &inputStream, TLPBuilder *builder, PluginProgress *pluginProgress,
375 : inputStream(inputStream), pluginProgress(pluginProgress), fileSize(size), curPos(0) {
376 builderStack.push_front(builder);
380 while (!builderStack.empty()) {
381 TLPBuilder *builder = builderStack.front();
382 builderStack.pop_front();
384 if (builderStack.empty() || builder != builderStack.front())
389 bool formatError(
const std::string &value) {
390 std::stringstream ess;
391 ess <<
"Error when parsing '" << value.c_str() <<
"' at line " << tokenParser->curLine + 1;
394 ess << std::endl << strerror(errno);
396 pluginProgress->setError(ess.str());
401 TLPTokenParser tParser(inputStream);
402 tokenParser = &tParser;
403 TLPToken currentToken;
404 TLPValue currentValue;
406 while ((currentToken = tokenParser->nextToken(currentValue, curPos)) != ENDOFSTREAM) {
407 if (curPos % 2000 == 1)
408 if (pluginProgress->progress(curPos, fileSize) !=
TLP_CONTINUE)
411 switch (currentToken) {
413 currentToken = tokenParser->nextToken(currentValue, curPos);
415 if (currentToken != STRINGTOKEN)
416 return formatError(currentValue.str);
418 TLPBuilder *newBuilder;
420 if (builderStack.front()->addStruct(currentValue.str, newBuilder)) {
421 builderStack.push_front(newBuilder);
423 if (newBuilder->canRead())
424 if (!newBuilder->read(inputStream))
425 return formatError(currentValue.str);
427 return formatError(currentValue.str);
433 if (!builderStack.front()->addBool(currentValue.boolean))
434 return formatError(currentValue.str);
440 if (!builderStack.front()->addInt(currentValue.integer))
441 return formatError(currentValue.str);
447 if (!builderStack.front()->addRange(currentValue.range.first, currentValue.range.second))
448 return formatError(currentValue.str);
454 if (!builderStack.front()->addDouble(currentValue.real))
455 return formatError(currentValue.str);
461 if (!builderStack.front()->addString(currentValue.str))
462 return formatError(currentValue.str);
468 if (builderStack.front()->close()) {
469 TLPBuilder *builder = builderStack.front();
470 builderStack.pop_front();
472 if (builder != builderStack.front())
475 return formatError(currentValue.str);
480 return formatError(currentValue.str);
488 tlp::debug() <<
"Comment line:" << tokenParser->curLine <<
"->" << currentValue.str;
498 pluginProgress->progress(fileSize, fileSize);
505 #endif // TLPPARSER_H