
]' ../../../../opensource/opt/include/boost/spirit/core/scanner/ scanner.hpp:161: instantiated from 'void boost::spirit::action_policy::do_action(const ActorT&, AttrT&, const IteratorT&, const IteratorT&) const [with ActorT = boost::spirit::ref_value_actor<phoenix::actor<phoenix::closure_member<0,
]' ../../../../opensource/opt/include/boost/spirit/core/composite/ actions.hpp:109: instantiated from 'typename boost::spirit::parser_result<boost::spirit::action<ParserT, ActionT>, ScannerT>::type boost::spirit::action<ParserT, ActionT>::parse(const ScannerT&) const [with ScannerT = boost::spirit::scanner<__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> , boost::spirit::scanner_policies<boost::spirit::iter_policy_t, boost::spirit::match_policy, boost::spirit::action_policy> >, ParserT = boost::spirit::rule<boost::spirit::scanner<__gnu_cxx::__normal_iterator< char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, boost::spirit::scanner_policies<boost::spirit::iter_policy_t, boost::spirit::match_policy, boost::spirit::action_policy> >, boost::spirit::nil_t, boost::spirit::nil_t>, ActionT = boost::spirit::ref_value_actor<phoenix::actor<phoenix::closure_member<0,
I'm trying to build a parser that does a fairly simple transformation of an input string - kind of like an L-System. I can get rules to properly match the input string, but I'm having real trouble with DOING anything. For testing, I've created some simple actions and a grammar (and rules) with a closure. When I don't use the closure for "temporary" variables, I seem to be able to proceed, but when I do anything except assign a value to my closure result, I'm getting failures to compile. This is using gcc4.01 on MacOSX and spirit 1.8.3 (from boost 1.34). The specific compiler error is: ../../src/lsystem/catalog_lsystem.cpp: In member function 'void do_appender::act(T&, const IteratorT&, const IteratorT&) const [with T = phoenix::actor<phoenix::closure_member<0, phoenix::closure<String, size_t, String> > >, IteratorT = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >]': <snip> ../../src/lsystem/catalog_lsystem.cpp:211: error: no matching function for call to 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string (phoenix::actor<phoenix::closure_member<0, phoenix::closure<String, size_t, String> > >&)' From the error, it appears that I need some transformation from phoenix::actor back into my closure member, which is a String (typedef for std::basic_string<char>). Any suggestions? do_appender (a simple example actor) looks like: struct do_appender { template <typename T, typename ValueT> void act(T& ref, ValueT const &val) const { ref += val; } template <typename T, typename IteratorT> void act(T& ref, IteratorT const &first, IteratorT const & last) const { String s(first, last); ref += s; } }; template <typename T> inline ref_value_actor<T, do_appender> do_append(T& lhs) { return ref_value_actor<T, do_appender>(lhs); } template <typename T, typename ValueT> inline ref_const_ref_actor<T, ValueT, do_appender> do_append(T& lhs, ValueT const& val) { return ref_const_ref_actor<T, ValueT, do_appender>(lhs,val); } and the closure and grammar (stripped slightly) look like: struct ProductionClosure : boost::spirit::closure<ProductionClosure, String, size_t, String> { member1 m_result; member2 m_count; member3 m_temporary; }; struct ParameterLSystem::ProductionGrammar : public grammar<ParameterLSystem::ProductionGrammar, ProductionClosure::context_t> { String * m_append; ProductionGrammar(String * ap) : m_append(ap) {} template <typename ScannerT> struct definition { typedef rule<ScannerT, ProductionClosure::context_t> rule_t; typedef rule<ScannerT> srule_t; srule_t r_segment; rule_t r_segments; srule_t r_leaf; rule_t r_leaves; srule_t r_push; srule_t r_pop; rule_t r_start; rule_t r_terminalLeaves; rule_t r_branch; rule_t r_top; definition(ProductionGrammar const& self) { // basics r_leaf = ch_p('L'); r_leaves = (+r_leaf)[r_leaves.m_result = construct_<String>(arg1, arg2)]; r_segment = ch_p('S'); r_segments = (+r_segment)[r_segments.m_result = construct_<String>(arg1, arg2)]; r_push = ch_p('['); r_pop = ch_p(']'); r_terminalLeaves = r_push[do_append (r_terminalLeaves.m_result)]; r_top = r_branch[self.m_result = arg1]; } rule_t const& start() const { return r_top; } }; }; }; String is a typedef for std::basic_string<char> in my namespace. When I use m_append for a "temporary", I can get things to "work", i.e., it compiles and generates the correct output but the grammar will get more complex and I don't believe I can get away without using a closure variable. The full error stack from the compiler is: ../../src/lsystem/catalog_lsystem.cpp: In member function 'void do_appender::act(T&, const IteratorT&, const IteratorT&) const [with T = phoenix::actor<phoenix::closure_member<0, phoenix::closure<String, size_t, String> > >, IteratorT = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >]': ../../../../opensource/opt/include/boost/spirit/actor/ ref_value_actor.hpp:59: instantiated from 'void boost::spirit::ref_value_actor<T, ActionT>::operator()(const IteratorT&, const IteratorT&) const [with IteratorT = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, T = phoenix::actor<phoenix::closure_member<0, phoenix::closure<String, size_t, String> > >, ActionT = do_appender]' ../../../../opensource/opt/include/boost/spirit/core/scanner/ scanner.hpp:146: instantiated from 'static void boost::spirit::attributed_action_policy<boost::spirit::nil_t>::call (const ActorT&, boost::spirit::nil_t, const IteratorT&, const IteratorT&) [with ActorT = boost::spirit::ref_value_actor<phoenix::actor<phoenix::closure_member<0, phoenix::closure<String, size_t, String> > >, do_appender>, IteratorT = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> phoenix::closure<String, size_t, String> > >, do_appender>, AttrT = boost::spirit::nil_t, IteratorT = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> phoenix::closure<String, size_t, String> > >, do_appender>]' ../../../../opensource/opt/include/boost/spirit/core/non_terminal/ impl/rule.ipp:233: instantiated from 'typename boost::spirit::match_result<ScannerT, ContextResultT>::type boost::spirit::impl::concrete_parser<ParserT, ScannerT, AttrT>::do_parse_virtual(const ScannerT&) const [with ParserT = boost::spirit::action<boost::spirit::rule<boost::spirit::scanner<__gnu_c xx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, boost::spirit::scanner_policies<boost::spirit::iter_policy_t, boost::spirit::match_policy, boost::spirit::action_policy> >, boost::spirit::nil_t, boost::spirit::nil_t>, boost::spirit::ref_value_actor<phoenix::actor<phoenix::closure_member<0, phoenix::closure<String, size_t, String> > >, do_appender> >, ScannerT = boost::spirit::scanner<__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char>
, boost::spirit::scanner_policies<boost::spirit::iter_policy_t, boost::spirit::match_policy, boost::spirit::action_policy> >, AttrT = String]' ../../src/lsystem/catalog_lsystem.cpp:547: instantiated from here ../../src/lsystem/catalog_lsystem.cpp:211: error: no matching function for call to 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string (phoenix::actor<phoenix::closure_member<0, phoenix::closure<String, size_t, String> > >&)'

For the record - I figured out my problem, which was a bit of confusion about what was an actor and how to access closure members. The "ref" passed in is a phoenix::actor, NOT the closure member itself, so to access the closure member, the operator()() of the actor needs to be invoked - substituting into the do_appender::act below: String& value(ref()); value += val; Of course, if act is called with something other than an actor, THIS will break, but I'm thinking it should ONLY be fed actors... And for my purposes, only an actor that returns a std::string&. On Jan 2, 2007, at 17:09, Hugh Hoover wrote:
I'm trying to build a parser that does a fairly simple transformation of an input string - kind of like an L-System. I can get rules to properly match the input string, but I'm having real trouble with DOING anything. For testing, I've created some simple actions and a grammar (and rules) with a closure. When I don't use the closure for "temporary" variables, I seem to be able to proceed, but when I do anything except assign a value to my closure result, I'm getting failures to compile. This is using gcc4.01 on MacOSX and spirit 1.8.3 (from boost 1.34).
The specific compiler error is: ../../src/lsystem/catalog_lsystem.cpp: In member function 'void do_appender::act(T&, const IteratorT&, const IteratorT&) const [with T = phoenix::actor<phoenix::closure_member<0, phoenix::closure<String, size_t, String> > >, IteratorT = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >]': <snip> ../../src/lsystem/catalog_lsystem.cpp:211: error: no matching function for call to 'std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string (phoenix::actor<phoenix::closure_member<0, phoenix::closure<String, size_t, String> > >&)'
From the error, it appears that I need some transformation from phoenix::actor back into my closure member, which is a String (typedef for std::basic_string<char>).
Any suggestions?
do_appender (a simple example actor) looks like:
struct do_appender { template <typename T, typename ValueT> void act(T& ref, ValueT const &val) const { ref += val; }
template <typename T, typename IteratorT> void act(T& ref, IteratorT const &first, IteratorT const & last) const { String s(first, last); ref += s; } };

Hubert Hoover wrote:
For the record - I figured out my problem, which was a bit of confusion about what was an actor and how to access closure members. The "ref" passed in is a phoenix::actor, NOT the closure member itself, so to access the closure member, the operator()() of the actor needs to be invoked - substituting into the do_appender::act below:
String& value(ref()); value += val;
Of course, if act is called with something other than an actor, THIS will break, but I'm thinking it should ONLY be fed actors... And for my purposes, only an actor that returns a std::string&.
That's good to hear. To be honest, I had a difficult time trying to read the code in your post. In the future, it's always a good idea to attach a minimal cpp file that we can try without much fuss. Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net
participants (3)
-
Hubert Hoover
-
Hugh Hoover
-
Joel de Guzman