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.