/ Použite Boost Phoenix v Qi, aby ste odkazovali na predchádzajúci zápas v gramatike - c ++, boost, c ++ 11, boost-spirit, boost-spirit-qi

Použite Boost Phoenix v Qi, aby ste odkazovali na predchádzajúci zápas v gramatike - c ++, boost, c ++ 11, boost-spirit, boost-spirit-qi

Som úplne nový pre Boost Spirit. V ideálnom prípade by som sa chcel presvedčiť o dvoch hodnotách v mojej gramatike za rovnakých okolností pomocou Phoenixu. Zmiešaná verzia toho, čo sa pokúšam pracovať, by bola n-ticka, kde sú oba atribúty rovnaké.

Mám rád reťazec "14,14, test" na analýzu, ale "14,12, test" zlyhal, pretože 14 nie je rovné 12. Mám rád kód nižšie na tlač:

Good: (14 14 test)
Fail

V súčasnosti prechádzajú obe vstupy, pretože dovoľujem a qi :: int_ analyzovať druhú hodnotu bez akýchkoľvek kontrol.

#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/spirit/include/qi_matches.hpp>

#include <string>
#include <vector>
#include <algorithm>

namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;


int main(){


std::vector<std::string> test_inputs = {"14,14,test","14,12,test"};

std::for_each(test_inputs.begin(),test_inputs.end(),[](const std::string& input){
boost::fusion::vector<int,int,std::string> result;
int i(0);

auto res = qi::parse(input.begin(),input.end(),
//works but also parses "14,12,test"
qi::int_[phx::ref(i) = qi::_1] >> qi::lit(",") >> qi::int_ >> qi::lit(",") >> +qi::char_,
//Fails to compile
//qi::int_[phx::ref(i) = qi::_1] >> qi::lit(",") >> qi::int_(phx::val(i)) >> qi::lit(",") >> +qi::char_,
//qi::int_[phx::ref(i) = qi::_1] >> qi::lit(",") >> qi::int_(phx::ref(i)) >> qi::lit(",") >> +qi::char_,
result);
if(res){
std::cout << "Good: " << result << std::endl;
}
else{
std::cout << "Fail" << std::endl;
}
});
}

Môžem použiť phoenix ::ref zachytiť prvú hodnotu, ale nemôžem zistiť, otestovať môj druhý qi :: int_ analyzátor pre hodnotu i.I som sa snažil používať phoenix :: val a phoenix :: ref bez kompilácie šťastia. V ideálnom prípade by som rád zachytil hodnotu v druhom int a myslel si, že int_parser by vzal lenivý literál z Phoenixu.

Ďakujeme za každú a všetku pomoc.

odpovede:

4 pre odpoveď č. 1

Najjednoduchšia oprava je poskytnúť hodnotu i zozbierané z prvej qi :: int_ do druhej, tzn.

qi::int_[phx::ref(i) = qi::_1] >> qi::lit(",") >> qi::int_(phx::ref(i)) >> qi::lit(",") >> +qi::char_,

qi :: _ int s parametrom očakáva dodávanú hodnotu.

Ďalšou alternatívou, ktorú treba zvážiť, je použitie premennej pravidlo-miestne. Môžete to urobiť:

typedef boost::fusion::vector<int,int,std::string> result_t;
result_t result;
qi::rule<std::string::const_iterator, result_t(),
boost::spirit::qi::locals<int> > r;
r %= qi::int_[qi::_a = qi::_1] >> qi::lit(",") >> qi::int_(qi::_a) >> qi::lit(",") >> +qi::char_;

Potom použite "r" namiesto pravidla. Aj keď predpokladám, že ak chcete spraviť pravidlo priamo pomocou qi :: parse, to nedáva zmysel.