Разбор строки как списка с использованием boost :: spirit - PullRequest
2 голосов
/ 17 марта 2012

У меня есть ситуация, когда я анализирую ввод в карту векторов boost :: Spirit.

Это работает хорошо, но я столкнулся с ситуацией, когда мне нужно предоставить фиксированную строку внутри для определенного случая пользовательского ввода, так что вместо пользовательского ввода внутренняя строка анализируется.

Вот пример грамматики:

input_pair = 
    key( std::string("__input")) >> valid_input % ','
    ;

где:

key = 
    qi::attr( _r1 )
    ;

и «valid_input» - это простое правило, которое проверяет наличие определенных строк / шаблонов символов и т. Д.

Эта грамматика связывает ввод с предопределенным внутренним ключом и сохраняет его на карте как вектор. Если входные данные содержат указанный разделитель, входные данные соответствующим образом анализируются на отдельные элементы принимающего вектора.

Однако проблема, с которой я столкнулся, заключается в предоставлении предопределенной строки для «valid_input».

Мое первое желание сделать то, что я сделал с ключом карты:

input_pair = 
    key( std::string("__input")) >> key ( std::string("A, B, C")) % ','
    ;

Но, конечно, вся строка вставляется как первый элемент вектора. То есть разделители запятых в "A, B, C" не распознаются, как я и надеялся.

Таким образом, мой вопрос:

Учитывая синтаксический анализатор boost :: Spirit, грамматика которого анализирует входные данные в карту векторов, есть ли способ проанализировать фиксированную строку , определенную в самом синтаксическом анализаторе , в вектор?

1 Ответ

2 голосов
/ 22 марта 2012

С учетом ввода «1 2 3 4», следующее правило:

typedef std::vector<std::string> attr_t;

rule = *qi::lexeme[+qi::char_];

(очевидно) проанализирует значение атрибута std::vector<string> { "1", "2", "3", "4" }.

Теперь измените правило на

rule %= qi::attr(attr_t { "aap", "noot", "mies" }) >>  *qi::lexeme[+qi::char_];

и вы получите std::vector<string> { "aap", "noot", "mies", "1", "2", "3", "4" }. Используйте qi::omit, если вы хотите использовать жестко закодированный вектор только .

Это унифицированный синтаксис C ++ 11 на работе, поэтому, если вы не можете его использовать, вам придется указать вектор другим способом:

static const std::string hardcoded[] = { "aap", "noot", "mies" };
static const attr_t const_data(hardcoded, hardcoded+3);
rule = qi::attr(const_data) >>  *qi::lexeme[+qi::char_];

Это также немного более эффективно (за счет более подробного кода).


Вот полностью рабочий пример с некоторыми вариациями этого (предполагая, что компилятор C ++ 11 для основного теста):

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

namespace qi    = boost::spirit::qi;
namespace karma = boost::spirit::karma;

typedef std::vector<std::string> attr_t;

int main()
{
    const std::string input = "1 2 3 4";
    auto f(std::begin(input)), l(std::end(input));

    qi::rule<decltype(f), attr_t(), qi::space_type> rule;

    // #1: no hardcoded values
    rule = *qi::lexeme[+qi::char_];

    // #2: hardcoded inline temp vector
    rule = qi::attr(attr_t { "aap", "noot", "mies" }) >>  *qi::lexeme[+qi::char_];

    // #3: hardcoded static vector, C++03 style
    static const std::string hardcoded[] = { "aap", "noot", "mies" };
    static const attr_t const_data(hardcoded, hardcoded+3);
    rule = qi::attr(const_data) >>  *qi::lexeme[+qi::char_];

    try
    {
        attr_t data;
        bool ok = qi::phrase_parse(f, l, rule, qi::space, data);
        if (ok)   
        {
            std::cout << "parse success\n";
            std::cout << "data: " << karma::format_delimited(karma::auto_, ' ', data) << "\n";
        }
        else std::cerr << "parse failed: '" << std::string(f,l) << "'\n";

        if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n";

        return ok? 0 : 255;
    } catch(const qi::expectation_failure<decltype(f)>& e)
    {
        std::string frag(e.first, e.last);
        std::cerr << e.what() << "'" << frag << "'\n";
        return 255;
    }

}

печатает

parse success
data: 1 2 3 4 
...