C ++ Boost qi rekurencyjna konstrukcja reguł

[Wygląda na to, że moje wyjaśnienia i oczekiwania w ogóle nie są jasne, więc dodałem precyzję, jak chciałbym korzystać z funkcji na końcu postu]

Obecnie pracuję nad gramatykami przy użyciu boost qi. Miałem konstrukcję pętli dla reguły, ponieważ musiałem ją zbudować z elementów wektora. Przepisałem go ponownie za pomocą prostych typów i wygląda to tak:

#include <string>

// using boost 1.43.0
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_eps.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace bqi = boost::spirit::qi;

typedef const char* Iterator;

// function that you can find [here][1]
template<typename P> void test_phrase_parser(char const* input, P const& p, bool full_match = true);

int main()
{
    // my working rule type:
    bqi::rule<Iterator, std::string()> myLoopBuiltRule;
    std::vector<std::string> v;
    std::vector<std::string>::const_iterator iv;

    v.push_back("abc");
    v.push_back("def");
    v.push_back("ghi");
    v.push_back("jkl");

    myLoopBuiltRule = (! bqi::eps);
    for(iv = v.begin() ; iv != v.end() ; iv++)
    {
        myLoopBuiltRule =
                myLoopBuiltRule.copy()  [ bqi::_val = bqi::_1 ]
                | bqi::string(*iv)      [ bqi::_val = bqi::_1 ]
                ;
    }
    debug(myLoopBuiltRule);

    char s[] = "  abc ";

    test_phrase_parser(s, myLoopBuiltRule);
}

(Wygląda jaktutaj nie chce być zastępowany przez odpowiednie hiperłącze, więc tutaj jest adres do znalezienia funkcji test_phrase_parser ():http://www.boost.org/doc/libs/1_43_0/libs/spirit/doc/html/spirit/qi/reference/basics.html)

Wszystko było dla najlepszych w najlepszych światach ... dopóki nie musiałem przekazać argumentu tej regule. Oto nowy typ reguły:

    // my not-anymore-working rule type:
    bqi::rule<Iterator, std::string(int*)> myLoopBuiltRule;

Typ 'int *' jest na przykład tylko celowy, mój prawdziwy wskaźnik wskazuje znacznie bardziej złożoną klasę ... ale wciąż jest zwykłym wskaźnikiem.

Zmieniłem odpowiednio pętlę „for”, tj .:

    for(iv = v.begin() ; iv != v.end() ; iv++)
    {
        myLoopBuiltRule =
                myLoopBuiltRule.copy()(bqi::_r1)    [ bqi::_val = bqi::_1 ]
                | bqi::string(*iv)      [ bqi::_val = bqi::_1 ]
                ;
    }

Musiałem dodać nową regułę, ponieważ test_phrase_parser () nie może odgadnąć, która wartość ma zostać podana wskaźnikowi int:

bqi::rule<Iterator> myInitialRule;

I zmień wszystko, co nastąpiło po pętli for:

myInitialRule = myLoopBuiltRule((int*)NULL);

debug(myLoopBuiltRule);

char s[] = "  abc ";

test_phrase_parser(s, myInitialRule);

Potem wszystko się załamało:

/home/sylvain.darras/software/repository/software/external/include/boost/boost_1_43_0/boost/spirit/home/qi/nonterminal/rule.hpp:199: error: no matching function for call to ‘assertion_failed(mpl_::failed************ (boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::operator=(const Expr&)

Potem zwariowałem i próbowałem:

myLoopBuiltRule =
        myLoopBuiltRule.copy(bqi::_r1)  [ bqi::_val = bqi::_1 ]
        | bqi::string(*iv)      [ bqi::_val = bqi::_1 ]

->

error: no matching function for call to ‘boost::spirit::qi::rule<const char*, std::string(int*), boost::fusion::unused_type, boost::fusion::unused_type, boost::fusion::unused_type>::copy(const boost::phoenix::actor<boost::spirit::attribute<1> >&)’

Potem oszalałem i napisałem:

myLoopBuiltRule =
        myLoopBuiltRule(bqi::_r1)   [ bqi::_val = bqi::_1 ]
        | bqi::string(*iv)      [ bqi::_val = bqi::_1 ]

Który kompiluje, ponieważ jest doskonale poprawny pod względem składniowym, ale który przepełnia się przepełnieniem, bo jest szczęśliwy, ładnie, rekurencyjnie, wzywa się do śmierci ...

Potem straciłem rozum i wpisałem:

myLoopBuiltRule =
        jf jhsgf jshdg fjsdgh fjsg jhsdg jhg sjfg jsgh df

Co, jak prawdopodobnie się spodziewasz, nie udało się skompilować.

Wyobrażasz sobie, że przed napisaniem powyższej powieści, sprawdziłem w sieci, ale nie znalazłem nic związanego z kopiowaniem () i przekazywaniem argumentów w tym samym czasie. Czy ktoś już doświadczył tego problemu? Czy coś przegapiłem?

Zapewniamy, że każda pomoc zostanie naprawdę doceniona.

PS: Wielkie dzięki dla hkaisera, który nie wiedząc o tym, odpowiedział na wiele moich podwyżek :: problemy qi przez google (ale ten).

Dalsza informacja:

Celem mojego parsera jest odczyt plików zapisanych w danym języku L. Celem mojego postu jest propagowanie mojego „kontekstu” (tj. Definicji zmiennych, a zwłaszcza wartości stałych, dzięki czemu mogę obliczać wyrażenia).

Liczba typów zmiennych, które obsługuję, jest niewielka, ale będzie rosła, więc przechowuję te typy w klasie kontenerów. Mogę zapętlić te zarządzane typy.

Rozważmy więc pseudo-algorytm tego, co chciałbym osiągnąć:

LTypeList myTypes;
LTypeList::const_iterator iTypes;

bqi::rule<Iterator, LType(LContext*)> myLoopBuiltRule;

myLoopBuiltRule = (! bqi::eps);
for(iTypes = myTypes.begin() ; iTypes != myTypes.end() ; iTypes++)
{
    myLoopBuiltRule =
        myLoopBuiltRule.copy()(bqi::_r1)    [ bqi::_val = bqi::_1 ]
        | iTypes->getRule()(bqi::_r1)           [ bqi::_val = bqi::_1 ]
}

Robi się to podczas inicjalizacji, a następnie myLoopBuiltRule jest używany i ponownie używany z innym LContext *, analizując wiele typów. A ponieważ niektóre typy L mogą mieć granice, które są wyrażeniami całkowitymi i że te wyrażenia całkowite mogą wykazywać stałe, ja (myślę, że I) potrzebuję mojego odziedziczonego atrybutu, aby objąć mój LContext i móc obliczyć wartość ekspresji.

Mam nadzieję, że moje intencje były jaśniejsze.

questionAnswers(1)

yourAnswerToTheQuestion