2017-02-10 2 views
2

Я пытаюсь создать простой синтаксический анализатор, который принимает один из двух возможных символов, используя boost::spirit::x3. Проблема в том, что x3::char_('#') | x3::char_('.'), кажется, имеет атрибут типа boost::variant<char, ?>. Это означает, что я должен использовать boost::get<char> на _attr, тогда как он должен быть напрямую конвертирован в char.Атрибут boost spirit x3 (A | A) - это вариант <A, ?> вместо A

http://ciere.com/cppnow15/x3_docs/spirit/quick_reference/compound_attribute_rules.html, он говорит A | A -> A

Если закомментирована версия mapChars используется, то это конвертируемые в char, но не в |.

Я на boost версии 1.63.0 и на Linux. Код не скомпилирован как на g ++, так и на clang ++ с -std=c++14.

Что я делаю неправильно?

#include <iostream> 
#include <string> 

#include <boost/spirit/home/x3.hpp> 

int main() { 
    std::string s("#"); 
    namespace x3 = boost::spirit::x3; 
    auto f = [](auto & ctx) { 
     auto & attr = x3::_attr(ctx); 
     //char c = attr; // doesn't work 
     char c = boost::get<char>(attr); // does work 
    }; 
    auto mapChar = x3::char_('#') | x3::char_('.'); // _attr not convertible to char, is a variant 
    //auto mapChar = x3::char_('#'); // _attr convertible to char, isn't a variant 
    auto p = mapChar[f]; 
    auto b = s.begin(); 
    bool success = x3::parse(b, s.end(), p); 
    std::cout << "Success: " << success << ' ' << (b == s.end()) << '\n'; 
} 
+1

Я думаю, что 'x3 :: полукокса _ ("#").' Должен делать то, что вы хотите. Конечно, это не решает проблему варианта «A | A->'. – llonesmiz

+0

Для этого примера это очень эквивалентно – sehe

ответ

1

Вы правильно, он должен быть совместимы, и на самом деле она уже есть: правила совместимости атрибут

auto const& attr = x3::_attr(ctx); 
char c; 
x3::traits::move_to(attr, c); 

Духа (плюс точка настройки) является средством для выполнения такой семантики.

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

+0

Я пробовал то, что и в основном дает ту же ошибку ('присвоение char из несовместимого типа ... > ...'). Кажется, что в этом случае 'x3 :: traits :: move_to' просто выполняет' dest = std :: move (src); 'который ничего не меняет. – aeubanks

+2

@aeubanks Mmm. Вы совершенно правы. Должно быть, я сделал что-то не так. Между тем, вы можете использовать принуждение правила ([demo] (http://coliru.stacked-crooked.com/a/a7f8df9f67ac3a7b)), что становится намного более удобным [со вспомогательной функцией] (http://stackoverflow.com/ вопросы/33816662/understanding-the-list-operator-in-boost-spirit/33817135 # 33817135): http://coliru.stacked-crooked.com/a/1f5788a7eeaf872b – sehe

+0

Если вы считаете, что это должно обсуждаться для улучшения, вы можете дойти до разработчиков в списке рассылки [spirit-general] – sehe

0

Если семантическое действие имеет атрибут, значение, оно должно работать:

char result = 0; 

auto f = [&result](char c){ result = c; }; 

auto mapChar = x3::char_('#') | x3::char_('.'); 
auto p = mapChar[f]; 
auto b = s.begin(); 
bool success = x3::parse(b, s.end(), p); 
Смежные вопросы