Как разобрать структурированный формат? - PullRequest
0 голосов
/ 25 декабря 2011

У меня есть строка, и я хотел бы проанализировать ее на структурных блоках.

Итак, структура в строке выглядит так:

if(true) {
    if(true) {
        if(true) {}
    }
}
if(true) {
    if(true) {
        if(true) {}
    }
}

И я бы хотелразделить один на родительские блоки следующим образом:

if(true) {
    if(true) {
        if(true) {}
    }
},

if(true) {
    if(true) {
        if(true) {}
    }
}

Мой код:

string condition = 
"if(true) {\
    if(true) {\
        if(true) {}\
    }\
}\
if(true) {\
    if(true) {\
        if(true) {}\
    }\
}";

string item; 
stringstream stream(condition);
vector<string> array;

//splitting on sections
while (getline(stream, item, '}')) {
    array.push_back(item + "}");
}

for(int i = 0; i < array.size(); i++) {
    cout << i << array[i] << endl;
}

Результат:

0 if(true) { if(true) { if(true) {}
1   }
2 }
3 if(true) { if(true) { if(true) {}
4   }
5 }

Но нужно:

0 if(true) { if(true) { if(true) {} } }
1 if(true) { if(true) { if(true) {} } }

Как правильно определить и проанализировать родительские блоки или указать алгоритм?

1 Ответ

2 голосов
/ 26 декабря 2011

Вам нужно будет вести подсчет вашей текущей глубины.Я считаю, что лучшие парсеры основаны на итераторах, вот что я покажу здесь.std::getline не очень полезен для разбора, за исключением самых простых форматов.

Полностью непроверенный код:

std::vector<std::string> vec;

int depth = 0;
std::string::const_iterator first = condition.begin(),
                            last = condition.end(),
                            iter = first;

for(;;)
{
    iter = std::find_if(iter, last,
                        [](char ch) { return ch == '{' || ch == '}'; });

    if(iter == last)
    {
        if(depth)
        {
            throw std::runtime_error("unclosed block found.");
        }

        break;
    }

    if(*iter == '{')
    {
        ++depth;
        ++iter;
    }
    else if(*iter == '}' && !--depth)
    {
        v.push_back(std::string(first, ++iter));
        first = iter;
    }
    else
    {
        ++iter;
    }
}
...