在解析過程中,我只需要在語義動作中設置一些屬性(因爲它們是從正在解析的數據派生的,並且我想避免使用global
變量和依賴BOOST_FUSION_ADAPT_STRUCT
以及我的代碼應該是通用的,以便我可以重用它的多種類型)。如果我使用多個傳入qi::phrase_parse
的變量,我會得到非常長的編譯錯誤列表。我需要幫助嚴重:-)從傳遞到qi :: phrase_parse的表達式的語義動作中設置屬性
#define BOOST_RESULT_OF_USE_DECLTYPE
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/function.hpp>
#include <boost/phoenix/fusion.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iostream>
#include <string>
#include <climits>
namespace qi = boost::spirit::qi;
namespace ph = boost::phoenix;
namespace ascii = boost::spirit::ascii;
int main(int argc, char**argv)
{
bool rc;
std::string input("");
//Test case 1 works fine
{
auto iter(input.begin());
auto last(input.end());
int val1=33;
rc = qi::phrase_parse(iter, last, qi::eps[ qi::_val=11 ] ,
ascii::space, val1) && iter==last;
if(rc)
std::cout << "val1=" << val1 << std::endl;
}
//Test case 2 does not compile
{
auto iter(input.begin());
auto last(input.end());
int val1=33;
int val2=0;
rc = qi::phrase_parse(iter, last,
qi::eps[ ph::at_c<0>(qi::_val)=1,ph::at_c<1>(qi::_val)=2 ],
ascii::space, val1,val2) && iter==last;
if(rc)
std::cout << "val1=" << val1 <<
" val2=" << val2 << std::endl;
}
//Test case 3 works fine
{
auto iter(input.begin());
auto last(input.end());
int val1=33;
int val2=0;
rc = qi::phrase_parse(iter, last,
qi::attr(1)>>qi::attr(2),
ascii::space, val1,val2) && iter==last;
if(rc)
std::cout << "val1=" << val1 <<
" val2=" << val2 << std::endl;
}
return 0;
}
我把「定製」 my_phrase_parse從cv_and_he
但它打破的全面測試案例彙編,我想獲得運行:
template<typename T,typename R>
void testParser(R rule)
{
for (const auto input : std::vector<std::string>{ "5 1.0 2.0 3.0 4.0 5.0", "1 1.0", "0" , "", "2 3 ab" })
{
bool rc;
T maxValue;
T minValue;
auto iter(input.begin());
auto last(input.end());
std::vector<T> v;
rc = my_phrase_parse(iter, last,
qi::eps[
ph::at_c<0>(qi::_val)=std::numeric_limits<T>::max(),
ph::at_c<1>(qi::_val)=std::numeric_limits<T>::min()
]
>> -(qi::omit[ qi::int_]
>> *rule[ ph::if_(ph::at_c<0>(qi::_val)>qi::_1)[ ph::at_c<0>(qi::_val)=qi::_1 ],
ph::if_(ph::at_c<1>(qi::_val)<qi::_1)[ ph::at_c<1>(qi::_val)=qi::_1 ]
])
,ascii::space, minValue, maxValue,v) && iter==last;
std::cout << (rc ? "ok :`" : "err:`") << input << "` -> ";
if(rc)
{
std::cout << "min=" << minValue << " max=" << maxValue << "\t";
std::copy(v.begin(), v.end(), std::ostream_iterator<T>(std::cout," "));
}
else
std::cout << *iter;
std::cout << std::endl;
}
}
...
testParser<double>(qi::double_);
[升壓1.47.0之前,你的第一個例子是行不通的(HTTP:// boost-spirit.com/home/2011/02/26/using-_val-in-top-level-semantic-actions/)。在那個版本中,一個修復被應用於「正常」的'parse'和'phrase_parse',但顯然不適用於「可變參數」。如果創建了一個規則,如:qi :: rule(),ascii :: space_type> parser = qi :: eps [ph :: at_c <0>(qi :: _val)= 1 ,ph :: at_c <1>(qi :: _val)= 2];'它會起作用。 –
llonesmiz
@cv_and_he嗨,感謝您的反饋。我正在使用1_52。如果單個變量的情況不起作用,我不會問這個問題,因爲它會很明顯:-),因爲我可以避免使用attr的'測試用例3'生成值的問題。 –
我知道它的工作原理。如果你閱讀這個鏈接,你會發現它唯一的原因是因爲它只改變了'parse'和'phrase_parse'的唯一屬性。 – llonesmiz