2016-11-03 121 views
3

我試圖定義一個解析器,其中規則沒有完全預定義,即它們包含可變部分。這與齊靈無關,但由於X3的靜態特性,我無法實現它。我嘗試了與指令,這是不幸的,但沒有記錄,但沒有運氣到目前爲止。目前爲止我發現的唯一例子是在lambda表達式中。解析器規則依賴於參數

我構建了一個簡單的例子來演示這個問題:解析分隔符作爲參數給出的整數。

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

namespace x3 = boost::spirit::x3; 

namespace parsing { 
    x3::rule<struct parser> parser {"parser"}; 

    //struct separator {}; 
    char separator(','); 

    //auto parser_def = x3::int_ % x3::lit(x3::get<separator>(/* context */)); // candidate function template not viable: requires single argument 'context' 
    auto parser_def = x3::int_ % x3::lit(separator); 

    BOOST_SPIRIT_DEFINE(parser) 
} 

void parse(const std::string &data, const char separator) { 
    using namespace std; 

    //auto parser = x3::with<parsing::separator>(ref(separator)) [parsing::parser] >> x3::eoi; 
    auto parser = parsing::parser >> x3::eoi; 

    if (x3::parse(data.begin(), data.end(), parser)) 
     cout << "Parse succeeded\n"; 
    else 
     cout << "Parse failed\n"; 
} 

int main() { 
    parse("1 2 3", ' '); 
    parse("1,2,3", ','); 
    parse("1;2;3", ';'); 
} 

我註釋掉的部分,我試圖用指令使用

這是目前可能與X3?有沒有人做過這個?

+0

只是想大聲這裏...您可以創建調用轉發給相應''%的解析函數自己'parse'功能。在這種情況下,你可能可以使用'x3 :: get'來從'context'(這是一個用於解析函數的參數)中獲得分隔符? – Arunmu

回答

1

尋找一些更X3的帖子後,我被這個答案sehe的啓發:https://stackoverflow.com/a/38303379/7110782

知道關於X3 :: _通使我這個解決方案:

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

namespace x3 = boost::spirit::x3; 

namespace parsing { 
    x3::rule<struct parser> parser {"parser"}; 

    struct separator {}; 

    // only the separator which is currently in the context is allowed (passes) 
    auto isSeparator = [](auto& ctx){ x3::_pass(ctx) = x3::_attr(ctx) == x3::get<separator>(ctx); }; 

    // at first match any char and then check whether it is the separator 
    auto parser_def = x3::int_ % x3::char_[isSeparator]; 

    BOOST_SPIRIT_DEFINE(parser) 
} 

void parse(const std::string &data, const char separator) { 
    using namespace std; 

    auto parser = x3::with<parsing::separator>(ref(separator)) [parsing::parser] >> x3::eoi; 

    if (x3::parse(data.begin(), data.end(), parser)) 
     cout << "Parse succeeded\n"; 
    else 
     cout << "Parse failed\n"; 
} 

int main() { 
    // succeed 
    parse("1 2 3", ' '); 
    parse("1,2,3", ','); 
    parse("1;2;3", ';'); 

    // fail 
    parse("1,2,3", ' '); 
    parse("1;2;3", ','); 
} 

剩下來測試進一步的步驟是可以設置多個參數(可能通過級聯x3 ::與<>)。

編輯:

是,通過設置級聯X3 ::多個參數與<>似乎工作。 例如:

auto parser = x3::with<parsing::separator>(ref(separator))[x3::with<parsing::separator2>(ref(separator2))[parsing::parser]] >> x3::eoi;