[It seems that my explanations and expectations are not entirely clear, so I added how much I would like to use the function at the end of the message]
I am currently working on grammars using boost qi. I had a loop construct for the rule because I needed to build it from the elements of the vector. I rewrote it with simple types, and it looks like this:
#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); }
(It seems that it doesn’t want to be replaced by the corresponding hyperlink, so here is the address for searching for the function test_phrase_parser (): http://www.boost.org/doc/libs/1_43_0/libs/spirit/doc/html/spirit/qi/reference /basics.html )
Everything was for the best in the best of all worlds ... until I had to accept an argument in favor of this rule. Here is a new type of rule:
// my not-anymore-working rule type: bqi::rule<Iterator, std::string(int*)> myLoopBuiltRule;
The 'int *' type, for example, is for purposes only, my real pointer addresses a much more complex class ... but still a simple pointer.
I changed my "for" loop accordingly, that is:
for(iv = v.begin() ; iv != v.end() ; iv++) { myLoopBuiltRule = myLoopBuiltRule.copy()(bqi::_r1) [ bqi::_val = bqi::_1 ] | bqi::string(*iv) [ bqi::_val = bqi::_1 ] ; }
I had to add a new rule because test_phrase_parser () cannot guess which value should be assigned to the int pointer:
bqi::rule<Iterator> myInitialRule;
And change everything that followed the for loop:
myInitialRule = myLoopBuiltRule((int*)NULL); debug(myLoopBuiltRule); char s[] = " abc "; test_phrase_parser(s, myInitialRule);
Then everything crashed:
/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&)
Then I went crazy and tried:
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> >&)'
Then I got angry and wrote:
myLoopBuiltRule = myLoopBuiltRule(bqi::_r1) [ bqi::_val = bqi::_1 ] | bqi::string(*iv) [ bqi::_val = bqi::_1 ]
What compiles, since it is completely syntactically correct, but which perfectly overflows the stacks, it happily, beautifully, recursively calls itself to death ...
Then I lost my mind and typed:
myLoopBuiltRule = jf jhsgf jshdg fjsdgh fjsg jhsdg jhg sjfg jsgh df
Which, as you probably expect, could not be compiled.
You assume that before writing the aforementioned novel, I checked on the Internet but did not find anything related to copying () and passing arguments at the same time. Has anyone already experienced this problem? Did I miss something?
Be sure that any help will be truly appreciated.
PS: Many thanks to hkaiser, who, not knowing about it, answered many of my problems: qi via google (but this one).
Additional Information:
The purpose of my analyzer is to read files written in a given language L. The purpose of my message is to spread my "context" (that is: definitions of variables and especially constant values, so I can evaluate expressions).
The number of processed types of variables is small, but it is associated with growth, so I save these types in the container class. I can use these managed types.
So, consider the pseudo-algorithm of what I would like to achieve:
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 ] }
This is done during initialization, and then myLoopBuiltRule is used and reused with another LContext *, parsing several types. And since some L types can have boundaries that are integer expressions, and that these integer expressions can expose constants, I (I think I) need my inherited attribute to take my LContext and calculate the value of the expression.
I hope that I was more clear in my intentions.