boost ::spirit::qi — необязательное совпадение

#boost-spirit #optional

#boost-spirit #тип опции

Вопрос:

Я новичок в boost :: spirit. Я наткнулся на простую вещь. Учитывая строку, подобную этой:

 Optional text KEYWORD further text
  

Мне нужно разобрать его в строку, подобную этой:

 T KEYWORD further text
  

где ‘T’ появляется только в том случае, если существует необязательный текст. К чему я пришел, так это к этому правилу:

 start = ( (char_ - "KEYWORD"))  [_val  = 'T']  |  eps
        >> "KEYWORD"            [_val  = _1]   
        >> *char_               [_val  = _1];
  

Но это не удается. Кто-нибудь может мне помочь, пожалуйста?

Комментарии:

1. Спасибо, сехе. Spirit кажется мне немного сложным.

2. Да, я знаю, что ты имеешь в виду. Для меня это стоит усилий, но на случай, если вы ищете что-то более простое (и более быстрое для компиляции) Я искренне рекомендую CoCo/R C то, что я использовал до Spirit для «всех» моих потребностей в синтаксическом анализе. Его несомненным преимуществом является возможность повторного использования существующих грамматик на самых разных языках (C #, Java, C , C #, VB, Oberon, Ruby, Python, Oberon, Ada и т.д.).

Ответ №1:

Это в значительной степени зависит от целевых типов, которым вы присваиваете атрибуты, и (в меньшей степени) от политики пробелов, то есть от того, использует ли ваша грамматика шкипер или нет.

На данный момент, вот что я бы написал:

 #include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;

template <typename V>
   void test(const Vamp; input)
{
    typedef typename V::const_iterator It;

    using namespace qi;
    rule<It, bool(), space_type>        preambule =  (!lit("KEYWORD") > omit[char_]) > attr(true) | attr(false);
    rule<It, std::string(), space_type> word      =  char_;

    It first(input.begin()), last(input.end());

    bool hasPreamble;
    std::string furtherText;

    bool ok = phrase_parse(first, last,
            preambule > "KEYWORD" > raw[ *char_ ], space,
            hasPreamble, furtherText);

    if (ok)
        std::cout << (hasPreamble?"T ":"") << "KEYWORD " << furtherText << std::endl;

    if (first!=last)
        std::cout << "hmmm: '" << std::string(first, last) << "'" << std::endl;
}

int main()
{
    test(std::string("KEYWORD further text"));
    test(std::string("one KEYWORD further text"));
    test(std::string("one two KEYWORD further text"));
}
  

Вывод:

 KEYWORD further text
T KEYWORD further text
T KEYWORD further text