Как правильно разобрать это с духом? - PullRequest
3 голосов
/ 21 января 2009

Моя ситуация: я новичок в Spirit, я должен использовать VC6 и поэтому использую Spirit 1.6.4.

У меня есть строка, которая выглядит так:

//The Description;DESCRIPTION;;

Я хочу поместить текст DESCRIPTION в строку, если строка начинается с //The Description;.

У меня есть кое-что, что работает, но выглядит для меня не так элегантно:

vector<char> vDescription; // std::string doesn't work due to missing ::clear() in VC6's STL implementation
if(parse(chars,
    // Begin grammar
    (
       as_lower_d["//the description;"]
    >> (+~ch_p(';'))[assign(vDescription)]
    ),
    // End grammar
    space_p).hit)
{
    const string desc(vDescription.begin(), vDescription.end());
}

Я бы очень хотел назначить всем печатным символам до следующего ';', но следующее не будет работать, потому что parse(...).hit == false

parse(chars,
        // Begin grammar
        (
           as_lower_d["//the description;"]
        >> (+print_p)[assign(vDescription)]
        >> ';'
        ),
        // End grammar
        space_p).hit)

Как мне сделать это?

Ответы [ 2 ]

3 голосов
/ 22 января 2009

Вы можете попробовать использовать confix_p:

confix_p(as_lower_d["//the description;"],
         (+print_p)[assign(vDescription)],
         ch_p(';')
        )

Это должно быть эквивалентно ответ Фреда .

Причина, по которой ваш код не работает, заключается в том, что print_p является жадным . Синтаксический анализатор +print_p будет потреблять символы до тех пор, пока не встретит конец ввода или непечатаемый символ. Точка с запятой пригодна для печати, поэтому print_p заявляет об этом. Ваш ввод исчерпан, переменная назначена, и совпадение не выполнено - для последней запятой вашего синтаксического анализатора ничего не осталось.

Ответ Фреда создает новый синтаксический анализатор, (print_p - ';'), который соответствует всему, что print_p делает, кроме точек с запятой. «Сопоставить все, кроме X , а затем сопоставить X » - это обычный шаблон, поэтому confix_p предоставляется в качестве ярлыка для создания парсера такого типа. Документация предлагает использовать его для анализа комментариев в стиле C или Pascal, но это не обязательно.

Чтобы ваш код работал, Духу нужно было бы признать, что жадный print_p слишком сильно соответствовал, а затем вернуться назад , чтобы позволить сопоставление меньше. Но хотя Spirit будет возвращаться назад, он не будет возвращаться к «середине» того, что в противном случае подпарсер мог бы жадно сопоставить. Он вернется к следующей «точке выбора», но в вашей грамматике ее нет. См. Исчерпывающий откат и жадный RD в документации Spirit.

3 голосов
/ 22 января 2009

Вы не получите удар, потому что ';' соответствует print_p. Попробуйте это:

parse(chars,
    // Begin grammar
    (
       as_lower_d["//the description;"]
    >> (+(print_p-';'))[assign(vDescription)]
    >> ';'
    ),
    // End grammar
    space_p).hit)
...