Porting from Qi to X3

classic Classic list List threaded Threaded
20 messages Options
Reply | Threaded
Open this post in threaded view
|

Porting from Qi to X3

Mario Lang
Hi.

This is what I figured out so far while porting my Qi grammar over to
X3:

* Compile time is definitely faster.  I used to have a few grammars
  hidden behind compiler firewalls with Qi.  With X3, I can have my full
  parser in a single C++ file and the TU only takes about 10 seconds to
  compile.
  Since Qi is spread across a few TUs, I can not directly measure
  compilation time differences, but it is more on the order of 3 or 4
  times faster with X3 here.
  Parse times were never a problem for me, so were not compared.

* I hit a few assertion failures in mpl::push_back from
  get_sequence_types.  I am really no expert with MPL, but it looks like
  it was trying to do a push_back on a joint_view.  I haven't managed to
  isolate the case into a simple test case.  Adding a x3::rule with an
  unused attribute here or there made the problems go away.
  However, I suspect a problem here.  Pushing back to a view doesn't
  sound like something that should happen, nor work.

* My grammar is now almost semantic action free.  I have a few actions
  left, partly for handling unsigned numbers composed of digits other
  than 0..9.  Thats fine.  However, in at least three placed, a pattern
  has appeared to form.

  auto assign_0 = [](auto& ctx) { _val(ctx) = 0; };
  auto plus_1 = [](auto& ctx) { _val(ctx) += 1; };
  auto const my_rule_def = eps[assign_0] >> +parser[plus_1];

  OR

  repeat(3)[unused_p] >> attr(3)
| repeat(2)[unused_p] >> attr(2)

  I am wondering if a count directive, a hybrid of the matches and
  repeat directives, could be useful.  It would have the same interface
  as repeat, but expose a std::size_t attribute.  With this, the above
  would become

  count(1, inf)[parser]

  OR

  count(2, 3)[unused_p]

  I don't remember having seen this in Qi, and I realize that X3 is
  supposed to keep it simple.  But this directive strikes me as rather
  useful.  If others agree, I could provide a pull request.

* While it is possibly rather obvious to others, I found the following
  pattern, which is now possible since we are using C++14, rather neat!

template < typename Encoding
         , template<typename> typename BinaryPredicate = std::equal_to
         , uint8_t Mask = 0XFF
         >
struct brl_parser : char_parser<brl_parser<Encoding, BinaryPredicate, Mask>>
{
  using attribute_type = unused_type;
  using char_type = typename Encoding::char_type;
  using encoding = Encoding;
  static bool const has_attribute = false;

  brl_parser(unsigned decimal_dots);
  template <typename Char, typename Context> bool test(Char, Context const&) const;

  uint8_t dots;
};

inline brl_parser<char_encoding::unicode, std::equal_to, 0X3F>
brl(unsigned decimal_dots)
{
  return { decimal_dots };
}

inline auto brl(unsigned a, unsigned b)
{
  return brl(a) >> brl(b);
}

inline auto brl(unsigned a, unsigned b, unsigned c)
{
  return brl(a) >> brl(b) >> brl(c);
}

--
CYa,
  ⡍⠁⠗⠊⠕

------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/spirit-general
Reply | Threaded
Open this post in threaded view
|

Re: Porting from Qi to X3

Joel de Guzman
On 5/29/15 2:50 AM, Mario Lang wrote:
> * I hit a few assertion failures in mpl::push_back from
>    get_sequence_types.  I am really no expert with MPL, but it looks like
>    it was trying to do a push_back on a joint_view.  I haven't managed to
>    isolate the case into a simple test case.  Adding a x3::rule with an
>    unused attribute here or there made the problems go away.
>    However, I suspect a problem here.  Pushing back to a view doesn't
>    sound like something that should happen, nor work.

Hmmm. I thought I fixed that. Can you give me a minimal cpp file I can test
with?

Regards,
--
Joel de Guzman
http://www.ciere.com
http://boost-spirit.com
http://www.cycfi.com/


------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/spirit-general
Reply | Threaded
Open this post in threaded view
|

Re: Porting from Qi to X3

Joel de Guzman
On 5/29/15 12:32 PM, Joel de Guzman wrote:

> On 5/29/15 2:50 AM, Mario Lang wrote:
>> * I hit a few assertion failures in mpl::push_back from
>>     get_sequence_types.  I am really no expert with MPL, but it looks like
>>     it was trying to do a push_back on a joint_view.  I haven't managed to
>>     isolate the case into a simple test case.  Adding a x3::rule with an
>>     unused attribute here or there made the problems go away.
>>     However, I suspect a problem here.  Pushing back to a view doesn't
>>     sound like something that should happen, nor work.
>
> Hmmm. I thought I fixed that. Can you give me a minimal cpp file I can test
> with?

Or at least give me the error message that points the the line/file.
I'm sure you did a pull from develop?

Regards,
--
Joel de Guzman
http://www.ciere.com
http://boost-spirit.com
http://www.cycfi.com/


------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/spirit-general
Reply | Threaded
Open this post in threaded view
|

Re: Porting from Qi to X3

Mario Lang
Joel de Guzman <[hidden email]> writes:

> On 5/29/15 12:32 PM, Joel de Guzman wrote:
>> On 5/29/15 2:50 AM, Mario Lang wrote:
>>> * I hit a few assertion failures in mpl::push_back from
>>>     get_sequence_types.  I am really no expert with MPL, but it looks like
>>>     it was trying to do a push_back on a joint_view.  I haven't managed to
>>>     isolate the case into a simple test case.  Adding a x3::rule with an
>>>     unused attribute here or there made the problems go away.
>>>     However, I suspect a problem here.  Pushing back to a view doesn't
>>>     sound like something that should happen, nor work.
>>
>> Hmmm. I thought I fixed that. Can you give me a minimal cpp file I can test
>> with?
>
> Or at least give me the error message that points the the line/file.

I was able to reproduce the error.  It happens if I replace this rule:

rule<struct eom> const eom = "eom";
auto const eom_def = brl(126, 13) >> !brl(3);
BOOST_SPIRIT_DEFINE(eom)

with a simple auto parser:

auto const eom = brl(126, 13) >> !brl(3);

If I understand the expression templates correctly, this means the
actual ET becomes bigger, with a bit of type erasure removed from it.
brl(126, 13) >> !brl(3) actually means
brl(126) >> brl(13) >> !brl(3)

The call sites for eom look like this:

rule<struct last_keyboard_section_body, std::vector<ast::paragraph>> const
last_keyboard_section_body = "last_keyboard_section_body";
auto const last_keyboard_section_body_def =
    omit[right_hand_sign]
 >> paragraph
 >> eom
 >> eol
 >> indent
 >> omit[left_hand_sign]
 >> paragraph
 >> eom
  ;

indent is a rule with unused attribute type.  i.e., all the parsers
except for paragraph are either rules with unused type or sequences of
unused types.  There are two paragraph parsers in the sequence, which
are supposed to be placed in an attribute of type std::vector<ast::paragraph>.
Something in the collapsing of this long chain breaks down.


In file included from /tmp/src/boost/boost/mpl/aux_/na_assert.hpp:23:0,
                 from /tmp/src/boost/boost/mpl/arg.hpp:25,
                 from /tmp/src/boost/boost/variant/variant_fwd.hpp:19,
                 from /tmp/src/boost/boost/variant/variant.hpp:26,
                 from include/bmc/braille_music.hpp:10,
                 from include/bmc/braille/parser/ast.hpp:5,
                 from include/bmc/braille/parser/ast_adapted.hpp:4,
                 from parser.cpp:1:
/tmp/src/boost/boost/mpl/aux_/push_back_impl.hpp: In instantiation of ‘struct boost::mpl::push_back_impl<boost::mpl::aux::joint_view_tag>::apply<boost::mpl::joint_view<boost::mpl::vector<boost::spirit::x3::unused_type, bmc::braille::parser::ast::paragraph, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::v_item<boost::spirit::x3::unused_type, boost::mpl::vector<boost::spirit::x3::unused_type, boost::spirit::x3::unused_type, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, 0> >, boost::spirit::x3::unused_type>’:
/tmp/src/boost/boost/mpl/push_back.hpp:29:8:   required from ‘struct boost::mpl::push_back<boost::mpl::joint_view<boost::mpl::vector<boost::spirit::x3::unused_type, bmc::braille::parser::ast::paragraph, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::v_item<boost::spirit::x3::unused_type, boost::mpl::vector<boost::spirit::x3::unused_type, boost::spirit::x3::unused_type, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, 0> >, boost::spirit::x3::unused_type>’
/tmp/src/boost/boost/spirit/home/x3/operator/detail/sequence.hpp:252:9:   required from ‘struct boost::spirit::x3::detail::get_sequence_types<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::omit_directive<boost::spirit::x3::rule<bmc::braille::parser::right_hand_sign, bmc::braille::parser::ast::hand_sign::type> >, boost::spirit::x3::rule<bmc::braille::parser::paragraph, bmc::braille::parser::ast::paragraph> >, boost::spirit::x3::sequence<boost::spirit::x3::sequence<bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u>, bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u> >, boost::spirit::x3::not_predicate<bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u> > > >, boost::spirit::x3::eol_parser>, boost::spirit::x3::rule<bmc::braille::parser::indent> >, boost::spirit::x3::omit_directive<boost::spirit::x3::rule<bmc::braille::parser::left_hand_sign, bmc::braille::parser::ast::hand_sign::type> > >, boost::spirit::x3::rule<bmc::braille::parser::paragraph, bmc::braille::parser::ast::paragraph>, boost::spirit::x3::context<boost::spirit::x3::error_handler_tag, const std::reference_wrapper<boost::spirit::x3::error_handler<__gnu_cxx::__normal_iterator<const char32_t*, std::basic_string<char32_t> > > >, boost::spirit::x3::unused_type> >’
/tmp/src/boost/boost/spirit/home/x3/operator/detail/sequence.hpp:281:60:   [ skipping 54 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/tmp/src/boost/boost/mpl/assert.hpp:429:42: error: no matching function for call to ‘assertion_failed(mpl_::failed************ (boost::mpl::push_back_impl<boost::mpl::aux::joint_view_tag>::apply<boost::mpl::joint_view<boost::mpl::vector<boost::spirit::x3::unused_type, bmc::braille::parser::ast::paragraph, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::v_item<boost::spirit::x3::unused_type, boost::mpl::vector<boost::spirit::x3::unused_type, boost::spirit::x3::unused_type, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, 0> >, boost::spirit::x3::unused_type>::REQUESTED_PUSH_BACK_SPECIALIZATION_FOR_SEQUENCE_DOES_NOT_EXIST::************)(boost::mpl::joint_view<boost::mpl::vector<boost::spirit::x3::unused_type, bmc::braille::parser::ast::paragraph, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::v_item<boost::spirit::x3::unused_type, boost::mpl::vector<boost::spirit::x3::unused_type, boost::spirit::x3::unused_type, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, 0> >))’
         boost::mpl::assertion_failed<(c)>( BOOST_PP_CAT(mpl_assert_arg,counter)::assert_arg() ) \
                                          ^
/tmp/src/boost/boost/mpl/assert.hpp:60:58: note: in definition of macro ‘BOOST_MPL_AUX_ASSERT_CONSTANT’
 #   define BOOST_MPL_AUX_ASSERT_CONSTANT(T, expr) enum { expr }
                                                          ^
/tmp/src/boost/boost/mpl/assert.hpp:436:1: note: in expansion of macro ‘BOOST_MPL_ASSERT_MSG_IMPL’
 BOOST_MPL_ASSERT_MSG_IMPL( BOOST_MPL_AUX_PP_COUNTER(), c, msg, types_ ) \
 ^
/tmp/src/boost/boost/mpl/aux_/push_back_impl.hpp:40:9: note: in expansion of macro ‘BOOST_MPL_ASSERT_MSG’
         BOOST_MPL_ASSERT_MSG(
         ^
/tmp/src/boost/boost/mpl/assert.hpp:83:5: note: candidate: template<bool C> int mpl_::assertion_failed(typename mpl_::assert<C>::type)
 int assertion_failed( typename assert<C>::type );
     ^
/tmp/src/boost/boost/mpl/assert.hpp:83:5: note:   template argument deduction/substitution failed:
/tmp/src/boost/boost/mpl/assert.hpp:429:92: note:   cannot convert ‘boost::mpl::push_back_impl<Tag>::apply<Sequence, T>::REQUESTED_PUSH_BACK_SPECIALIZATION_FOR_SEQUENCE_DOES_NOT_EXIST44::assert_arg<boost::mpl::joint_view<boost::mpl::vector<boost::spirit::x3::unused_type, bmc::braille::parser::ast::paragraph, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::v_item<boost::spirit::x3::unused_type, boost::mpl::vector<boost::spirit::x3::unused_type, boost::spirit::x3::unused_type, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, 0> >, boost::spirit::x3::unused_type>()’ (type ‘mpl_::failed************ (boost::mpl::push_back_impl<boost::mpl::aux::joint_view_tag>::apply<boost::mpl::joint_view<boost::mpl::vector<boost::spirit::x3::unused_type, bmc::braille::parser::ast::paragraph, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::v_item<boost::spirit::x3::unused_type, boost::mpl::vector<boost::spirit::x3::unused_type, boost::spirit::x3::unused_type, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, 0> >, boost::spirit::x3::unused_type>::REQUESTED_PUSH_BACK_SPECIALIZATION_FOR_SEQUENCE_DOES_NOT_EXIST::************)(boost::mpl::joint_view<boost::mpl::vector<boost::spirit::x3::unused_type, bmc::braille::parser::ast::paragraph, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::v_item<boost::spirit::x3::unused_type, boost::mpl::vector<boost::spirit::x3::unused_type, boost::spirit::x3::unused_type, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, 0> >)’) to type ‘mpl_::assert<false>::type {aka mpl_::assert<false>}’
         boost::mpl::assertion_failed<(c)>( BOOST_PP_CAT(mpl_assert_arg,counter)::assert_arg() ) \
                                                                                            ^
/tmp/src/boost/boost/mpl/assert.hpp:60:58: note: in definition of macro ‘BOOST_MPL_AUX_ASSERT_CONSTANT’
 #   define BOOST_MPL_AUX_ASSERT_CONSTANT(T, expr) enum { expr }
                                                          ^
/tmp/src/boost/boost/mpl/assert.hpp:436:1: note: in expansion of macro ‘BOOST_MPL_ASSERT_MSG_IMPL’
 BOOST_MPL_ASSERT_MSG_IMPL( BOOST_MPL_AUX_PP_COUNTER(), c, msg, types_ ) \
 ^
/tmp/src/boost/boost/mpl/aux_/push_back_impl.hpp:40:9: note: in expansion of macro ‘BOOST_MPL_ASSERT_MSG’
         BOOST_MPL_ASSERT_MSG(
         ^
In file included from /tmp/src/boost/boost/spirit/home/x3/operator/sequence.hpp:12:0,
                 from /tmp/src/boost/boost/spirit/home/x3/operator.hpp:10,
                 from /tmp/src/boost/boost/spirit/home/x3.hpp:19,
                 from parser.cpp:4:
/tmp/src/boost/boost/spirit/home/x3/operator/detail/sequence.hpp: In instantiation of ‘struct boost::spirit::x3::detail::get_sequence_types<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::omit_directive<boost::spirit::x3::rule<bmc::braille::parser::right_hand_sign, bmc::braille::parser::ast::hand_sign::type> >, boost::spirit::x3::rule<bmc::braille::parser::paragraph, bmc::braille::parser::ast::paragraph> >, boost::spirit::x3::sequence<boost::spirit::x3::sequence<bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u>, bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u> >, boost::spirit::x3::not_predicate<bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u> > > >, boost::spirit::x3::eol_parser, boost::spirit::x3::context<boost::spirit::x3::error_handler_tag, const std::reference_wrapper<boost::spirit::x3::error_handler<__gnu_cxx::__normal_iterator<const char32_t*, std::basic_string<char32_t> > > >, boost::spirit::x3::unused_type> >’:
/tmp/src/boost/boost/spirit/home/x3/operator/detail/sequence.hpp:252:9:   required from ‘struct boost::spirit::x3::detail::get_sequence_types<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::omit_directive<boost::spirit::x3::rule<bmc::braille::parser::right_hand_sign, bmc::braille::parser::ast::hand_sign::type> >, boost::spirit::x3::rule<bmc::braille::parser::paragraph, bmc::braille::parser::ast::paragraph> >, boost::spirit::x3::sequence<boost::spirit::x3::sequence<bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u>, bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u> >, boost::spirit::x3::not_predicate<bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u> > > >, boost::spirit::x3::eol_parser>, boost::spirit::x3::rule<bmc::braille::parser::indent> >, boost::spirit::x3::omit_directive<boost::spirit::x3::rule<bmc::braille::parser::left_hand_sign, bmc::braille::parser::ast::hand_sign::type> > >, boost::spirit::x3::rule<bmc::braille::parser::paragraph, bmc::braille::parser::ast::paragraph>, boost::spirit::x3::context<boost::spirit::x3::error_handler_tag, const std::reference_wrapper<boost::spirit::x3::error_handler<__gnu_cxx::__normal_iterator<const char32_t*, std::basic_string<char32_t> > > >, boost::spirit::x3::unused_type> >’
/tmp/src/boost/boost/spirit/home/x3/operator/detail/sequence.hpp:281:60:   required from ‘struct boost::spirit::x3::detail::attribute_of_sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::omit_directive<boost::spirit::x3::rule<bmc::braille::parser::right_hand_sign, bmc::braille::parser::ast::hand_sign::type> >, boost::spirit::x3::rule<bmc::braille::parser::paragraph, bmc::braille::parser::ast::paragraph> >, boost::spirit::x3::sequence<boost::spirit::x3::sequence<bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u>, bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u> >, boost::spirit::x3::not_predicate<bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u> > > >, boost::spirit::x3::eol_parser>, boost::spirit::x3::rule<bmc::braille::parser::indent> >, boost::spirit::x3::omit_directive<boost::spirit::x3::rule<bmc::braille::parser::left_hand_sign, bmc::braille::parser::ast::hand_sign::type> > >, boost::spirit::x3::rule<bmc::braille::parser::paragraph, bmc::braille::parser::ast::paragraph>, boost::spirit::x3::context<boost::spirit::x3::error_handler_tag, const std::reference_wrapper<boost::spirit::x3::error_handler<__gnu_cxx::__normal_iterator<const char32_t*, std::basic_string<char32_t> > > >, boost::spirit::x3::unused_type> >’
/tmp/src/boost/boost/spirit/home/x3/operator/sequence.hpp:71:12:   required from ‘struct boost::spirit::x3::traits::attribute_of<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::omit_directive<boost::spirit::x3::rule<bmc::braille::parser::right_hand_sign, bmc::braille::parser::ast::hand_sign::type> >, boost::spirit::x3::rule<bmc::braille::parser::paragraph, bmc::braille::parser::ast::paragraph> >, boost::spirit::x3::sequence<boost::spirit::x3::sequence<bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u>, bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u> >, boost::spirit::x3::not_predicate<bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u> > > >, boost::spirit::x3::eol_parser>, boost::spirit::x3::rule<bmc::braille::parser::indent> >, boost::spirit::x3::omit_directive<boost::spirit::x3::rule<bmc::braille::parser::left_hand_sign, bmc::braille::parser::ast::hand_sign::type> > >, boost::spirit::x3::rule<bmc::braille::parser::paragraph, bmc::braille::parser::ast::paragraph> >, boost::spirit::x3::context<boost::spirit::x3::error_handler_tag, const std::reference_wrapper<boost::spirit::x3::error_handler<__gnu_cxx::__normal_iterator<const char32_t*, std::basic_string<char32_t> > > >, boost::spirit::x3::unused_type>, void>’
/tmp/src/boost/boost/spirit/home/x3/operator/detail/sequence.hpp:484:13:   [ skipping 53 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/tmp/src/boost/boost/spirit/home/x3/operator/detail/sequence.hpp:252:9: error: no type named ‘type’ in ‘struct boost::mpl::push_back<boost::mpl::joint_view<boost::mpl::vector<boost::spirit::x3::unused_type, bmc::braille::parser::ast::paragraph, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::v_item<boost::spirit::x3::unused_type, boost::mpl::vector<boost::spirit::x3::unused_type, boost::spirit::x3::unused_type, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, 0> >, boost::spirit::x3::unused_type>’
         type;
       ^

> I'm sure you did a pull from develop?

Yes, I have.

--
CYa,
  ⡍⠁⠗⠊⠕

------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/spirit-general
Reply | Threaded
Open this post in threaded view
|

Re: Porting from Qi to X3

Mario Lang
In reply to this post by Joel de Guzman
Joel de Guzman <[hidden email]> writes:

> On 5/29/15 12:32 PM, Joel de Guzman wrote:
>> On 5/29/15 2:50 AM, Mario Lang wrote:
>>> * I hit a few assertion failures in mpl::push_back from
>>>     get_sequence_types.  I am really no expert with MPL, but it looks like
>>>     it was trying to do a push_back on a joint_view.  I haven't managed to
>>>     isolate the case into a simple test case.  Adding a x3::rule with an
>>>     unused attribute here or there made the problems go away.
>>>     However, I suspect a problem here.  Pushing back to a view doesn't
>>>     sound like something that should happen, nor work.
>>
>> Hmmm. I thought I fixed that. Can you give me a minimal cpp file I can test
>> with?
>
> Or at least give me the error message that points the the line/file.

I was able to reproduce the error.  It happens if I replace this rule:

rule<struct eom> const eom = "eom";
auto const eom_def = brl(126, 13) >> !brl(3);
BOOST_SPIRIT_DEFINE(eom)

with a simple auto parser:

auto const eom = brl(126, 13) >> !brl(3);

If I understand the expression templates correctly, this means the
actual ET becomes bigger, with a bit of type erasure removed from it.
brl(126, 13) >> !brl(3) actually means
brl(126) >> brl(13) >> !brl(3)

The call sites for eom look like this:

rule<struct last_keyboard_section_body, std::vector<ast::paragraph>> const
last_keyboard_section_body = "last_keyboard_section_body";
auto const last_keyboard_section_body_def =
    omit[right_hand_sign]
 >> paragraph
 >> eom
 >> eol
 >> indent
 >> omit[left_hand_sign]
 >> paragraph
 >> eom
  ;

indent is a rule with unused attribute type.  i.e., all the parsers
except for paragraph are either rules with unused type or sequences of
unused types.  There are two paragraph parsers in the sequence, which
are supposed to be placed in an attribute of type std::vector<ast::paragraph>.
Something in the collapsing of this long chain breaks down.


In file included from /tmp/src/boost/boost/mpl/aux_/na_assert.hpp:23:0,
                 from /tmp/src/boost/boost/mpl/arg.hpp:25,
                 from /tmp/src/boost/boost/variant/variant_fwd.hpp:19,
                 from /tmp/src/boost/boost/variant/variant.hpp:26,
                 from include/bmc/braille_music.hpp:10,
                 from include/bmc/braille/parser/ast.hpp:5,
                 from include/bmc/braille/parser/ast_adapted.hpp:4,
                 from parser.cpp:1:
/tmp/src/boost/boost/mpl/aux_/push_back_impl.hpp: In instantiation of ‘struct boost::mpl::push_back_impl<boost::mpl::aux::joint_view_tag>::apply<boost::mpl::joint_view<boost::mpl::vector<boost::spirit::x3::unused_type, bmc::braille::parser::ast::paragraph, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::v_item<boost::spirit::x3::unused_type, boost::mpl::vector<boost::spirit::x3::unused_type, boost::spirit::x3::unused_type, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, 0> >, boost::spirit::x3::unused_type>’:
/tmp/src/boost/boost/mpl/push_back.hpp:29:8:   required from ‘struct boost::mpl::push_back<boost::mpl::joint_view<boost::mpl::vector<boost::spirit::x3::unused_type, bmc::braille::parser::ast::paragraph, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::v_item<boost::spirit::x3::unused_type, boost::mpl::vector<boost::spirit::x3::unused_type, boost::spirit::x3::unused_type, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, 0> >, boost::spirit::x3::unused_type>’
/tmp/src/boost/boost/spirit/home/x3/operator/detail/sequence.hpp:252:9:   required from ‘struct boost::spirit::x3::detail::get_sequence_types<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::omit_directive<boost::spirit::x3::rule<bmc::braille::parser::right_hand_sign, bmc::braille::parser::ast::hand_sign::type> >, boost::spirit::x3::rule<bmc::braille::parser::paragraph, bmc::braille::parser::ast::paragraph> >, boost::spirit::x3::sequence<boost::spirit::x3::sequence<bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u>, bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u> >, boost::spirit::x3::not_predicate<bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u> > > >, boost::spirit::x3::eol_parser>, boost::spirit::x3::rule<bmc::braille::parser::indent> >, boost::spirit::x3::omit_directive<boost::spirit::x3::rule<bmc::braille::parser::left_hand_sign, bmc::braille::parser::ast::hand_sign::type> > >, boost::spirit::x3::rule<bmc::braille::parser::paragraph, bmc::braille::parser::ast::paragraph>, boost::spirit::x3::context<boost::spirit::x3::error_handler_tag, const std::reference_wrapper<boost::spirit::x3::error_handler<__gnu_cxx::__normal_iterator<const char32_t*, std::basic_string<char32_t> > > >, boost::spirit::x3::unused_type> >’
/tmp/src/boost/boost/spirit/home/x3/operator/detail/sequence.hpp:281:60:   [ skipping 54 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/tmp/src/boost/boost/mpl/assert.hpp:429:42: error: no matching function for call to ‘assertion_failed(mpl_::failed************ (boost::mpl::push_back_impl<boost::mpl::aux::joint_view_tag>::apply<boost::mpl::joint_view<boost::mpl::vector<boost::spirit::x3::unused_type, bmc::braille::parser::ast::paragraph, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::v_item<boost::spirit::x3::unused_type, boost::mpl::vector<boost::spirit::x3::unused_type, boost::spirit::x3::unused_type, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, 0> >, boost::spirit::x3::unused_type>::REQUESTED_PUSH_BACK_SPECIALIZATION_FOR_SEQUENCE_DOES_NOT_EXIST::************)(boost::mpl::joint_view<boost::mpl::vector<boost::spirit::x3::unused_type, bmc::braille::parser::ast::paragraph, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::v_item<boost::spirit::x3::unused_type, boost::mpl::vector<boost::spirit::x3::unused_type, boost::spirit::x3::unused_type, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, 0> >))’
         boost::mpl::assertion_failed<(c)>( BOOST_PP_CAT(mpl_assert_arg,counter)::assert_arg() ) \
                                          ^
/tmp/src/boost/boost/mpl/assert.hpp:60:58: note: in definition of macro ‘BOOST_MPL_AUX_ASSERT_CONSTANT’
 #   define BOOST_MPL_AUX_ASSERT_CONSTANT(T, expr) enum { expr }
                                                          ^
/tmp/src/boost/boost/mpl/assert.hpp:436:1: note: in expansion of macro ‘BOOST_MPL_ASSERT_MSG_IMPL’
 BOOST_MPL_ASSERT_MSG_IMPL( BOOST_MPL_AUX_PP_COUNTER(), c, msg, types_ ) \
 ^
/tmp/src/boost/boost/mpl/aux_/push_back_impl.hpp:40:9: note: in expansion of macro ‘BOOST_MPL_ASSERT_MSG’
         BOOST_MPL_ASSERT_MSG(
         ^
/tmp/src/boost/boost/mpl/assert.hpp:83:5: note: candidate: template<bool C> int mpl_::assertion_failed(typename mpl_::assert<C>::type)
 int assertion_failed( typename assert<C>::type );
     ^
/tmp/src/boost/boost/mpl/assert.hpp:83:5: note:   template argument deduction/substitution failed:
/tmp/src/boost/boost/mpl/assert.hpp:429:92: note:   cannot convert ‘boost::mpl::push_back_impl<Tag>::apply<Sequence, T>::REQUESTED_PUSH_BACK_SPECIALIZATION_FOR_SEQUENCE_DOES_NOT_EXIST44::assert_arg<boost::mpl::joint_view<boost::mpl::vector<boost::spirit::x3::unused_type, bmc::braille::parser::ast::paragraph, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::v_item<boost::spirit::x3::unused_type, boost::mpl::vector<boost::spirit::x3::unused_type, boost::spirit::x3::unused_type, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, 0> >, boost::spirit::x3::unused_type>()’ (type ‘mpl_::failed************ (boost::mpl::push_back_impl<boost::mpl::aux::joint_view_tag>::apply<boost::mpl::joint_view<boost::mpl::vector<boost::spirit::x3::unused_type, bmc::braille::parser::ast::paragraph, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::v_item<boost::spirit::x3::unused_type, boost::mpl::vector<boost::spirit::x3::unused_type, boost::spirit::x3::unused_type, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, 0> >, boost::spirit::x3::unused_type>::REQUESTED_PUSH_BACK_SPECIALIZATION_FOR_SEQUENCE_DOES_NOT_EXIST::************)(boost::mpl::joint_view<boost::mpl::vector<boost::spirit::x3::unused_type, bmc::braille::parser::ast::paragraph, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::v_item<boost::spirit::x3::unused_type, boost::mpl::vector<boost::spirit::x3::unused_type, boost::spirit::x3::unused_type, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, 0> >)’) to type ‘mpl_::assert<false>::type {aka mpl_::assert<false>}’
         boost::mpl::assertion_failed<(c)>( BOOST_PP_CAT(mpl_assert_arg,counter)::assert_arg() ) \
                                                                                            ^
/tmp/src/boost/boost/mpl/assert.hpp:60:58: note: in definition of macro ‘BOOST_MPL_AUX_ASSERT_CONSTANT’
 #   define BOOST_MPL_AUX_ASSERT_CONSTANT(T, expr) enum { expr }
                                                          ^
/tmp/src/boost/boost/mpl/assert.hpp:436:1: note: in expansion of macro ‘BOOST_MPL_ASSERT_MSG_IMPL’
 BOOST_MPL_ASSERT_MSG_IMPL( BOOST_MPL_AUX_PP_COUNTER(), c, msg, types_ ) \
 ^
/tmp/src/boost/boost/mpl/aux_/push_back_impl.hpp:40:9: note: in expansion of macro ‘BOOST_MPL_ASSERT_MSG’
         BOOST_MPL_ASSERT_MSG(
         ^
In file included from /tmp/src/boost/boost/spirit/home/x3/operator/sequence.hpp:12:0,
                 from /tmp/src/boost/boost/spirit/home/x3/operator.hpp:10,
                 from /tmp/src/boost/boost/spirit/home/x3.hpp:19,
                 from parser.cpp:4:
/tmp/src/boost/boost/spirit/home/x3/operator/detail/sequence.hpp: In instantiation of ‘struct boost::spirit::x3::detail::get_sequence_types<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::omit_directive<boost::spirit::x3::rule<bmc::braille::parser::right_hand_sign, bmc::braille::parser::ast::hand_sign::type> >, boost::spirit::x3::rule<bmc::braille::parser::paragraph, bmc::braille::parser::ast::paragraph> >, boost::spirit::x3::sequence<boost::spirit::x3::sequence<bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u>, bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u> >, boost::spirit::x3::not_predicate<bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u> > > >, boost::spirit::x3::eol_parser, boost::spirit::x3::context<boost::spirit::x3::error_handler_tag, const std::reference_wrapper<boost::spirit::x3::error_handler<__gnu_cxx::__normal_iterator<const char32_t*, std::basic_string<char32_t> > > >, boost::spirit::x3::unused_type> >’:
/tmp/src/boost/boost/spirit/home/x3/operator/detail/sequence.hpp:252:9:   required from ‘struct boost::spirit::x3::detail::get_sequence_types<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::omit_directive<boost::spirit::x3::rule<bmc::braille::parser::right_hand_sign, bmc::braille::parser::ast::hand_sign::type> >, boost::spirit::x3::rule<bmc::braille::parser::paragraph, bmc::braille::parser::ast::paragraph> >, boost::spirit::x3::sequence<boost::spirit::x3::sequence<bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u>, bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u> >, boost::spirit::x3::not_predicate<bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u> > > >, boost::spirit::x3::eol_parser>, boost::spirit::x3::rule<bmc::braille::parser::indent> >, boost::spirit::x3::omit_directive<boost::spirit::x3::rule<bmc::braille::parser::left_hand_sign, bmc::braille::parser::ast::hand_sign::type> > >, boost::spirit::x3::rule<bmc::braille::parser::paragraph, bmc::braille::parser::ast::paragraph>, boost::spirit::x3::context<boost::spirit::x3::error_handler_tag, const std::reference_wrapper<boost::spirit::x3::error_handler<__gnu_cxx::__normal_iterator<const char32_t*, std::basic_string<char32_t> > > >, boost::spirit::x3::unused_type> >’
/tmp/src/boost/boost/spirit/home/x3/operator/detail/sequence.hpp:281:60:   required from ‘struct boost::spirit::x3::detail::attribute_of_sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::omit_directive<boost::spirit::x3::rule<bmc::braille::parser::right_hand_sign, bmc::braille::parser::ast::hand_sign::type> >, boost::spirit::x3::rule<bmc::braille::parser::paragraph, bmc::braille::parser::ast::paragraph> >, boost::spirit::x3::sequence<boost::spirit::x3::sequence<bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u>, bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u> >, boost::spirit::x3::not_predicate<bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u> > > >, boost::spirit::x3::eol_parser>, boost::spirit::x3::rule<bmc::braille::parser::indent> >, boost::spirit::x3::omit_directive<boost::spirit::x3::rule<bmc::braille::parser::left_hand_sign, bmc::braille::parser::ast::hand_sign::type> > >, boost::spirit::x3::rule<bmc::braille::parser::paragraph, bmc::braille::parser::ast::paragraph>, boost::spirit::x3::context<boost::spirit::x3::error_handler_tag, const std::reference_wrapper<boost::spirit::x3::error_handler<__gnu_cxx::__normal_iterator<const char32_t*, std::basic_string<char32_t> > > >, boost::spirit::x3::unused_type> >’
/tmp/src/boost/boost/spirit/home/x3/operator/sequence.hpp:71:12:   required from ‘struct boost::spirit::x3::traits::attribute_of<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::omit_directive<boost::spirit::x3::rule<bmc::braille::parser::right_hand_sign, bmc::braille::parser::ast::hand_sign::type> >, boost::spirit::x3::rule<bmc::braille::parser::paragraph, bmc::braille::parser::ast::paragraph> >, boost::spirit::x3::sequence<boost::spirit::x3::sequence<bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u>, bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u> >, boost::spirit::x3::not_predicate<bmc::braille::parser::brl_parser<boost::spirit::char_encoding::unicode, std::equal_to, 63u> > > >, boost::spirit::x3::eol_parser>, boost::spirit::x3::rule<bmc::braille::parser::indent> >, boost::spirit::x3::omit_directive<boost::spirit::x3::rule<bmc::braille::parser::left_hand_sign, bmc::braille::parser::ast::hand_sign::type> > >, boost::spirit::x3::rule<bmc::braille::parser::paragraph, bmc::braille::parser::ast::paragraph> >, boost::spirit::x3::context<boost::spirit::x3::error_handler_tag, const std::reference_wrapper<boost::spirit::x3::error_handler<__gnu_cxx::__normal_iterator<const char32_t*, std::basic_string<char32_t> > > >, boost::spirit::x3::unused_type>, void>’
/tmp/src/boost/boost/spirit/home/x3/operator/detail/sequence.hpp:484:13:   [ skipping 53 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/tmp/src/boost/boost/spirit/home/x3/operator/detail/sequence.hpp:252:9: error: no type named ‘type’ in ‘struct boost::mpl::push_back<boost::mpl::joint_view<boost::mpl::vector<boost::spirit::x3::unused_type, bmc::braille::parser::ast::paragraph, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::mpl::v_item<boost::spirit::x3::unused_type, boost::mpl::vector<boost::spirit::x3::unused_type, boost::spirit::x3::unused_type, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, 0> >, boost::spirit::x3::unused_type>’
         type;
       ^

> I'm sure you did a pull from develop?

Yes, I have.

--
CYa,
  ⡍⠁⠗⠊⠕

------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/spirit-general
Reply | Threaded
Open this post in threaded view
|

Re: Porting from Qi to X3

Mario Lang
In reply to this post by Joel de Guzman
Joel de Guzman <[hidden email]> writes:

> On 5/29/15 2:50 AM, Mario Lang wrote:
>> * I hit a few assertion failures in mpl::push_back from
>>    get_sequence_types.  I am really no expert with MPL, but it looks like
>>    it was trying to do a push_back on a joint_view.  I haven't managed to
>>    isolate the case into a simple test case.  Adding a x3::rule with an
>>    unused attribute here or there made the problems go away.
>>    However, I suspect a problem here.  Pushing back to a view doesn't
>>    sound like something that should happen, nor work.
>
> Hmmm. I thought I fixed that.

You did, but only for get_alternative_types.
See https://github.com/boostorg/spirit/pull/111 for the corresponding
fix to get_sequence_types.

--
CYa,
  ⡍⠁⠗⠊⠕

------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/spirit-general
Reply | Threaded
Open this post in threaded view
|

Re: Porting from Qi to X3

Joel de Guzman
In reply to this post by Mario Lang
On 5/29/15 2:50 AM, Mario Lang wrote:

>   I am wondering if a count directive, a hybrid of the matches and
>    repeat directives, could be useful.  It would have the same interface
>    as repeat, but expose a std::size_t attribute.  With this, the above
>    would become
>
>    count(1, inf)[parser]
>
>    OR
>
>    count(2, 3)[unused_p]
>
>    I don't remember having seen this in Qi, and I realize that X3 is
>    supposed to keep it simple.  But this directive strikes me as rather
>    useful.  If others agree, I could provide a pull request.

I was thinking about this. I suppose we can inject a _repeat_count(ctx)
into the context so we can get it if we need to. I think the compiler
will optimize this out if it is unused.

Regards,
--
Joel de Guzman
http://www.ciere.com
http://boost-spirit.com
http://www.cycfi.com/


------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/spirit-general
Reply | Threaded
Open this post in threaded view
|

Re: Porting from Qi to X3

sehe
On Mon, Jun 1, 2015, at 10:17 AM, Joel de Guzman wrote:
>
> I was thinking about this. I suppose we can inject a _repeat_count(ctx)
> into the context so we can get it if we need to. I think the compiler
> will optimize this out if it is unused.
>

If we're considering this, please think about the complementary, very
often we parse things like:

     vec(4): 1 2 3 4
     vec(7): 0 0 1 0 3 3 3

And we have to use locals like e.g.

      "vec(" << uint_ [_a=_1] << "):" << repeat(_a) [ int_ ] << eol;

It would probably help if there was an implicit _repeat_count local
(that would be optimized out if unused)

Alternatively, simple cases could be helped by the even more expressive  

      repeat("vec(" << uint_ << "):") [ int_ ] << eol;

Or (to make implementation slightly simpler):

      repeat(attribute_of ["vec(" << uint_ << "):"]) [ int_ ] << eol;

Mor complicated scenarios will still require some extra state (locals<>
again). Thinking about multiple dimension and derived counts (_1 * _2,
or max(_1, _2) etc)


--
Seth

> Regards,
> --
> Joel de Guzman
> http://www.ciere.com
> http://boost-spirit.com
> http://www.cycfi.com/
>
>
> ------------------------------------------------------------------------------
> _______________________________________________
> Spirit-general mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/spirit-general

------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/spirit-general
Reply | Threaded
Open this post in threaded view
|

Re: Porting from Qi to X3

Joel de Guzman
On 6/1/15 4:44 PM, Seth wrote:

> On Mon, Jun 1, 2015, at 10:17 AM, Joel de Guzman wrote:
>>
>> I was thinking about this. I suppose we can inject a _repeat_count(ctx)
>> into the context so we can get it if we need to. I think the compiler
>> will optimize this out if it is unused.
>>
>
> If we're considering this, please think about the complementary, very
> often we parse things like:
>
>       vec(4): 1 2 3 4
>       vec(7): 0 0 1 0 3 3 3
>
> And we have to use locals like e.g.
>
>        "vec(" << uint_ [_a=_1] << "):" << repeat(_a) [ int_ ] << eol;
>
> It would probably help if there was an implicit _repeat_count local
> (that would be optimized out if unused)
>
> Alternatively, simple cases could be helped by the even more expressive
>
>        repeat("vec(" << uint_ << "):") [ int_ ] << eol;
>
> Or (to make implementation slightly simpler):
>
>        repeat(attribute_of ["vec(" << uint_ << "):"]) [ int_ ] << eol;
>
> Mor complicated scenarios will still require some extra state (locals<>
> again). Thinking about multiple dimension and derived counts (_1 * _2,
> or max(_1, _2) etc)

Sounds good! I think we can provide a lot of info into the context.
A good thing about X3 is that everything is visible in the compiler
and thus can optimize the code very well, even through the rule
boundary.

But first things first. We need better semantic actions. Imagine
writing what you wrote above using native c++ lambda! Ughh!

Regards,
--
Joel de Guzman
http://www.ciere.com
http://boost-spirit.com
http://www.cycfi.com/


------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/spirit-general
Reply | Threaded
Open this post in threaded view
|

Re: Porting from Qi to X3

teajay-2
Le 01/06/2015 19:11, Joel de Guzman a écrit :

> On 6/1/15 4:44 PM, Seth wrote:
>> On Mon, Jun 1, 2015, at 10:17 AM, Joel de Guzman wrote:
>>>
>>> I was thinking about this. I suppose we can inject a _repeat_count(ctx)
>>> into the context so we can get it if we need to. I think the compiler
>>> will optimize this out if it is unused.
>>>
>>
>> If we're considering this, please think about the complementary, very
>> often we parse things like:
>>
>>        vec(4): 1 2 3 4
>>        vec(7): 0 0 1 0 3 3 3
>>
>> And we have to use locals like e.g.
>>
>>         "vec(" << uint_ [_a=_1] << "):" << repeat(_a) [ int_ ] << eol;
>>
>> It would probably help if there was an implicit _repeat_count local
>> (that would be optimized out if unused)
>>
>> Alternatively, simple cases could be helped by the even more expressive
>>
>>         repeat("vec(" << uint_ << "):") [ int_ ] << eol;
>>
>> Or (to make implementation slightly simpler):
>>
>>         repeat(attribute_of ["vec(" << uint_ << "):"]) [ int_ ] << eol;
>>
>> Mor complicated scenarios will still require some extra state (locals<>
>> again). Thinking about multiple dimension and derived counts (_1 * _2,
>> or max(_1, _2) etc)
>
> Sounds good! I think we can provide a lot of info into the context.
> A good thing about X3 is that everything is visible in the compiler
> and thus can optimize the code very well, even through the rule
> boundary.
>
> But first things first. We need better semantic actions. Imagine
> writing what you wrote above using native c++ lambda! Ughh!
>
> Regards,
>

Reading your comments I thought of a possible other syntax I came up
with while looking at a way to implement locals using contexts. Reusing
the above examples:

"vec("<< uint_.named<struct VecSize>() << ":"<<repeat(local<struct
VecSize>())[ int_]<<eol;

Using this approach a reference to the attribute of the first uint_
parser can be added to the right context of the sequence parser and be
pulled out through it's name.

Don't know if it's any good, but it shouldn't be too hard to implement.

Regards,

Thomas Bernard


------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/spirit-general
Reply | Threaded
Open this post in threaded view
|

Re: Porting from Qi to X3

Joel de Guzman
On 6/2/15 5:28 AM, teajay wrote:

> Le 01/06/2015 19:11, Joel de Guzman a écrit :
>> On 6/1/15 4:44 PM, Seth wrote:
>>> On Mon, Jun 1, 2015, at 10:17 AM, Joel de Guzman wrote:
>>>>
>>>> I was thinking about this. I suppose we can inject a _repeat_count(ctx)
>>>> into the context so we can get it if we need to. I think the compiler
>>>> will optimize this out if it is unused.
>>>>
>>>
>>> If we're considering this, please think about the complementary, very
>>> often we parse things like:
>>>
>>>         vec(4): 1 2 3 4
>>>         vec(7): 0 0 1 0 3 3 3
>>>
>>> And we have to use locals like e.g.
>>>
>>>          "vec(" << uint_ [_a=_1] << "):" << repeat(_a) [ int_ ] << eol;
>>>
>>> It would probably help if there was an implicit _repeat_count local
>>> (that would be optimized out if unused)
>>>
>>> Alternatively, simple cases could be helped by the even more expressive
>>>
>>>          repeat("vec(" << uint_ << "):") [ int_ ] << eol;
>>>
>>> Or (to make implementation slightly simpler):
>>>
>>>          repeat(attribute_of ["vec(" << uint_ << "):"]) [ int_ ] << eol;
>>>
>>> Mor complicated scenarios will still require some extra state (locals<>
>>> again). Thinking about multiple dimension and derived counts (_1 * _2,
>>> or max(_1, _2) etc)
>>
>> Sounds good! I think we can provide a lot of info into the context.
>> A good thing about X3 is that everything is visible in the compiler
>> and thus can optimize the code very well, even through the rule
>> boundary.
>>
>> But first things first. We need better semantic actions. Imagine
>> writing what you wrote above using native c++ lambda! Ughh!
>>
>> Regards,
>>
>
> Reading your comments I thought of a possible other syntax I came up
> with while looking at a way to implement locals using contexts. Reusing
> the above examples:
>
> "vec("<< uint_.named<struct VecSize>() << ":"<<repeat(local<struct
> VecSize>())[ int_]<<eol;
>
> Using this approach a reference to the attribute of the first uint_
> parser can be added to the right context of the sequence parser and be
> pulled out through it's name.
>
> Don't know if it's any good, but it shouldn't be too hard to implement.

Is it just me? Somehow, I find the original syntax using phoenix still
the best in terms of clarity and verbosity.

Regards,
--
Joel de Guzman
http://www.ciere.com
http://boost-spirit.com
http://www.cycfi.com/


------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/spirit-general
Reply | Threaded
Open this post in threaded view
|

Re: Porting from Qi to X3

Mario Lang
In reply to this post by Joel de Guzman
Joel de Guzman <[hidden email]> writes:

> On 6/1/15 4:44 PM, Seth wrote:
>> On Mon, Jun 1, 2015, at 10:17 AM, Joel de Guzman wrote:
>>>
>>> I was thinking about this. I suppose we can inject a _repeat_count(ctx)
>>> into the context so we can get it if we need to. I think the compiler
>>> will optimize this out if it is unused.
>>>
>>
>> If we're considering this, please think about the complementary, very
>> often we parse things like:
>>
>>       vec(4): 1 2 3 4
>>       vec(7): 0 0 1 0 3 3 3
>>
>> And we have to use locals like e.g.
>>
>>        "vec(" << uint_ [_a=_1] << "):" << repeat(_a) [ int_ ] << eol;
>>
>> It would probably help if there was an implicit _repeat_count local
>> (that would be optimized out if unused)
>>
>> Alternatively, simple cases could be helped by the even more expressive
>>
>>        repeat("vec(" << uint_ << "):") [ int_ ] << eol;
>>
>> Or (to make implementation slightly simpler):
>>
>>        repeat(attribute_of ["vec(" << uint_ << "):"]) [ int_ ] << eol;
>>
>> Mor complicated scenarios will still require some extra state (locals<>
>> again). Thinking about multiple dimension and derived counts (_1 * _2,
>> or max(_1, _2) etc)
>
> Sounds good! I think we can provide a lot of info into the context.
> A good thing about X3 is that everything is visible in the compiler
> and thus can optimize the code very well, even through the rule
> boundary.
>
> But first things first. We need better semantic actions. Imagine
> writing what you wrote above using native c++ lambda! Ughh!

Note that the most concise example from above

>>        repeat("vec(" << uint_ << "):") [ int_ ] << eol;

does not make use of semantic actions at all.  I guess something like the following
(psuedo-code) could make it work.  Note the really cool line:

             return repeat(arg_attr)[subject].parse(first, last, context, rcontext, attr);

repeat has either arity one or two.  So a second version of this would
need to be written, or the dynamic wrapper would need to be made
variadic.


template <typename Arg, typename Subject>
struct dynamic_repeat_directive : ...
{
    using attribute_type =
        typename traits::attribute_of<repeat_directive<Subject, ...>>::type;
    ...

    dynamic_repeat_directive(Arg const& arg, Subject const& subject)
      : arg(arg), subject(subject) {}

    template <...>
    bool parse(first, last, context rcontext, attr) const
    {
         traits::attribute_of<Arg>::type arg_attr;
         auto saved = first;
         if (arg.parse(first, last, context, rcontext, arg_attr)) {
             return repeat(arg_attr)[subject].parse(first, last, context, rcontext, attr);
         }
         first = saved;
         return false;
    }

    Arg arg;
    Subject subject;
};

struct repeat_gen
{
    ...

    template <typename Arg>
    struct dynamic_lvl1_gen
    {
        dynamic_lvl1_gen(Arg const& arg) : arg(arg) {}

        template <typename Subject>
        dynamic_repeat_directive<Arg, Subject>
        operator[](Subject const& subject)
        {
            return { arg, subject };
        }

        Arg const& arg;
    };

    template <typename Arg, enable_if<is_parser<Arg>>>
    dynamic_lvl1_gen<Arg> operator()(Arg const& arg)
    {
        return { arg };
    }
};


-
CYa,
  ⡍⠁⠗⠊⠕

------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/spirit-general
Reply | Threaded
Open this post in threaded view
|

Re: Porting from Qi to X3

teajay-2
In reply to this post by Joel de Guzman
Le 02/06/2015 01:35, Joel de Guzman a écrit :

> On 6/2/15 5:28 AM, teajay wrote:
>> Le 01/06/2015 19:11, Joel de Guzman a écrit :
>>> On 6/1/15 4:44 PM, Seth wrote:
>>>> On Mon, Jun 1, 2015, at 10:17 AM, Joel de Guzman wrote:
>>>>>
>>>>> I was thinking about this. I suppose we can inject a _repeat_count(ctx)
>>>>> into the context so we can get it if we need to. I think the compiler
>>>>> will optimize this out if it is unused.
>>>>>
>>>>
>>>> If we're considering this, please think about the complementary, very
>>>> often we parse things like:
>>>>
>>>>          vec(4): 1 2 3 4
>>>>          vec(7): 0 0 1 0 3 3 3
>>>>
>>>> And we have to use locals like e.g.
>>>>
>>>>           "vec(" << uint_ [_a=_1] << "):" << repeat(_a) [ int_ ] << eol;
>>>>
>>>> It would probably help if there was an implicit _repeat_count local
>>>> (that would be optimized out if unused)
>>>>
>>>> Alternatively, simple cases could be helped by the even more expressive
>>>>
>>>>           repeat("vec(" << uint_ << "):") [ int_ ] << eol;
>>>>
>>>> Or (to make implementation slightly simpler):
>>>>
>>>>           repeat(attribute_of ["vec(" << uint_ << "):"]) [ int_ ] << eol;
>>>>
>>>> Mor complicated scenarios will still require some extra state (locals<>
>>>> again). Thinking about multiple dimension and derived counts (_1 * _2,
>>>> or max(_1, _2) etc)
>>>
>>> Sounds good! I think we can provide a lot of info into the context.
>>> A good thing about X3 is that everything is visible in the compiler
>>> and thus can optimize the code very well, even through the rule
>>> boundary.
>>>
>>> But first things first. We need better semantic actions. Imagine
>>> writing what you wrote above using native c++ lambda! Ughh!
>>>
>>> Regards,
>>>
>>
>> Reading your comments I thought of a possible other syntax I came up
>> with while looking at a way to implement locals using contexts. Reusing
>> the above examples:
>>
>> "vec("<< uint_.named<struct VecSize>() << ":"<<repeat(local<struct
>> VecSize>())[ int_]<<eol;
>>
>> Using this approach a reference to the attribute of the first uint_
>> parser can be added to the right context of the sequence parser and be
>> pulled out through it's name.
>>
>> Don't know if it's any good, but it shouldn't be too hard to implement.
>
> Is it just me? Somehow, I find the original syntax using phoenix still
> the best in terms of clarity and verbosity.
>
> Regards,
>
I agree the syntax is not really good, I thought of that myself. Just
wanted to share the idea of one way of getting intermediate parser
results into the context, using names.

There's probably a move elegant syntax to achieve this. I'll look a
little deeper.

Regards,

Thomas Bernard

------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/spirit-general
Reply | Threaded
Open this post in threaded view
|

Re: Porting from Qi to X3

teajay-2
In reply to this post by Mario Lang
Le 02/06/2015 01:49, Mario Lang a écrit :

> Joel de Guzman <[hidden email]> writes:
>
>> On 6/1/15 4:44 PM, Seth wrote:
>>> On Mon, Jun 1, 2015, at 10:17 AM, Joel de Guzman wrote:
>>>>
>>>> I was thinking about this. I suppose we can inject a _repeat_count(ctx)
>>>> into the context so we can get it if we need to. I think the compiler
>>>> will optimize this out if it is unused.
>>>>
>>>
>>> If we're considering this, please think about the complementary, very
>>> often we parse things like:
>>>
>>>        vec(4): 1 2 3 4
>>>        vec(7): 0 0 1 0 3 3 3
>>>
>>> And we have to use locals like e.g.
>>>
>>>         "vec(" << uint_ [_a=_1] << "):" << repeat(_a) [ int_ ] << eol;
>>>
>>> It would probably help if there was an implicit _repeat_count local
>>> (that would be optimized out if unused)
>>>
>>> Alternatively, simple cases could be helped by the even more expressive
>>>
>>>         repeat("vec(" << uint_ << "):") [ int_ ] << eol;
>>>
>>> Or (to make implementation slightly simpler):
>>>
>>>         repeat(attribute_of ["vec(" << uint_ << "):"]) [ int_ ] << eol;
>>>
>>> Mor complicated scenarios will still require some extra state (locals<>
>>> again). Thinking about multiple dimension and derived counts (_1 * _2,
>>> or max(_1, _2) etc)
>>
>> Sounds good! I think we can provide a lot of info into the context.
>> A good thing about X3 is that everything is visible in the compiler
>> and thus can optimize the code very well, even through the rule
>> boundary.
>>
>> But first things first. We need better semantic actions. Imagine
>> writing what you wrote above using native c++ lambda! Ughh!
>
> Note that the most concise example from above
>
>>>         repeat("vec(" << uint_ << "):") [ int_ ] << eol;
>
> does not make use of semantic actions at all.  I guess something like the following
> (psuedo-code) could make it work.  Note the really cool line:
>
>               return repeat(arg_attr)[subject].parse(first, last, context, rcontext, attr);
>
> repeat has either arity one or two.  So a second version of this would
> need to be written, or the dynamic wrapper would need to be made
> variadic.
>
>
> template <typename Arg, typename Subject>
> struct dynamic_repeat_directive : ...
> {
>      using attribute_type =
>          typename traits::attribute_of<repeat_directive<Subject, ...>>::type;
>      ...
>
>      dynamic_repeat_directive(Arg const& arg, Subject const& subject)
>        : arg(arg), subject(subject) {}
>
>      template <...>
>      bool parse(first, last, context rcontext, attr) const
>      {
>           traits::attribute_of<Arg>::type arg_attr;
>           auto saved = first;
>           if (arg.parse(first, last, context, rcontext, arg_attr)) {
>               return repeat(arg_attr)[subject].parse(first, last, context, rcontext, attr);
>           }
>           first = saved;
>           return false;
>      }
>
>      Arg arg;
>      Subject subject;
> };
>
> struct repeat_gen
> {
>      ...
>
>      template <typename Arg>
>      struct dynamic_lvl1_gen
>      {
>          dynamic_lvl1_gen(Arg const& arg) : arg(arg) {}
>
>          template <typename Subject>
>          dynamic_repeat_directive<Arg, Subject>
>          operator[](Subject const& subject)
>          {
>              return { arg, subject };
>          }
>
>          Arg const& arg;
>      };
>
>      template <typename Arg, enable_if<is_parser<Arg>>>
>      dynamic_lvl1_gen<Arg> operator()(Arg const& arg)
>      {
>          return { arg };
>      }
> };
>
>
> -
> CYa,
>    ⡍⠁⠗⠊⠕
>
> ------------------------------------------------------------------------------
> _______________________________________________
> Spirit-general mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/spirit-general
>

Pretty cool ! And simple.

Regards,

Thomas Bernard

------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/spirit-general
Reply | Threaded
Open this post in threaded view
|

Re: Porting from Qi to X3

Mario Lang
teajay <[hidden email]> writes:

> Le 02/06/2015 01:49, Mario Lang a écrit :
>> Joel de Guzman <[hidden email]> writes:
>>
>>> On 6/1/15 4:44 PM, Seth wrote:
>>>> On Mon, Jun 1, 2015, at 10:17 AM, Joel de Guzman wrote:
>>>>>
>>>>> I was thinking about this. I suppose we can inject a _repeat_count(ctx)
>>>>> into the context so we can get it if we need to. I think the compiler
>>>>> will optimize this out if it is unused.
>>>>>
>>>>
>>>> If we're considering this, please think about the complementary, very
>>>> often we parse things like:
>>>>
>>>>        vec(4): 1 2 3 4
>>>>        vec(7): 0 0 1 0 3 3 3
>>>>
>>>> And we have to use locals like e.g.
>>>>
>>>>         "vec(" << uint_ [_a=_1] << "):" << repeat(_a) [ int_ ] << eol;
>>>>
>>>> It would probably help if there was an implicit _repeat_count local
>>>> (that would be optimized out if unused)
>>>>
>>>> Alternatively, simple cases could be helped by the even more expressive
>>>>
>>>>         repeat("vec(" << uint_ << "):") [ int_ ] << eol;
>>>>
>>>> Or (to make implementation slightly simpler):
>>>>
>>>>         repeat(attribute_of ["vec(" << uint_ << "):"]) [ int_ ] << eol;
>>>>
>>>> Mor complicated scenarios will still require some extra state (locals<>
>>>> again). Thinking about multiple dimension and derived counts (_1 * _2,
>>>> or max(_1, _2) etc)
>>>
>>> Sounds good! I think we can provide a lot of info into the context.
>>> A good thing about X3 is that everything is visible in the compiler
>>> and thus can optimize the code very well, even through the rule
>>> boundary.
>>>
>>> But first things first. We need better semantic actions. Imagine
>>> writing what you wrote above using native c++ lambda! Ughh!
>>
>> Note that the most concise example from above
>>
>>>>         repeat("vec(" << uint_ << "):") [ int_ ] << eol;
>>
>> does not make use of semantic actions at all.  I guess something like the following
>> (psuedo-code) could make it work.  Note the really cool line:
>>
>>               return repeat(arg_attr)[subject].parse(first, last, context, rcontext, attr);
>>
>> repeat has either arity one or two.  So a second version of this would
>> need to be written, or the dynamic wrapper would need to be made
>> variadic.
>>
>>
>> template <typename Arg, typename Subject>
>> struct dynamic_repeat_directive : ...
>> {
>>      using attribute_type =
>>          typename traits::attribute_of<repeat_directive<Subject, ...>>::type;
>>      ...
>>
>>      dynamic_repeat_directive(Arg const& arg, Subject const& subject)
>>        : arg(arg), subject(subject) {}
>>
>>      template <...>
>>      bool parse(first, last, context rcontext, attr) const
>>      {
>>           traits::attribute_of<Arg>::type arg_attr;
>>           auto saved = first;
>>           if (arg.parse(first, last, context, rcontext, arg_attr)) {
>>               return repeat(arg_attr)[subject].parse(first, last, context, rcontext, attr);
>>           }
>>           first = saved;
>>           return false;
>>      }
>>
>>      Arg arg;
>>      Subject subject;
>> };
>>
>> struct repeat_gen
>> {
>>      ...
>>
>>      template <typename Arg>
>>      struct dynamic_lvl1_gen
>>      {
>>          dynamic_lvl1_gen(Arg const& arg) : arg(arg) {}
>>
>>          template <typename Subject>
>>          dynamic_repeat_directive<Arg, Subject>
>>          operator[](Subject const& subject)
>>          {
>>              return { arg, subject };
>>          }
>>
>>          Arg const& arg;
>>      };
>>
>>      template <typename Arg, enable_if<is_parser<Arg>>>
>>      dynamic_lvl1_gen<Arg> operator()(Arg const& arg)
>>      {
>>          return { arg };
>>      }
>> };
>
> Pretty cool ! And simple.

Thanks.

We can probably generalize it like this:

template<typename Gen, typename Subject, typename... Arg>
struct dynamic_parser : ...
{
    using attribute_type =
        traits::attribute_of<
            decltype(Gen{}(traits::attribute_type<Arg>::type()...)[std::declval<Subject>()])
        >::type;
    ...

    template <...> bool parse(...)
    {
        std::tuple<traits::attribute_of<Arg>::type...> args;
        ...
        return std::apply(Gen{}, args)[subject].parse(...);
    }
}

But I guess the infamous evaluation order problem is going to be an
issue.  Also, since ``repeat`` only has two args, it is probably not
worth the trouble to generalize this, let alone me not being experienced
enough with variadic code like this.

Joel?  What's your opinion on the idea in general?
I can try to make it work for ``repeat`` if people like it.

I think the motivating example is really very pretty.

repeat("vec(" >> uint_ >> ")")[int_]

--
CYa,
  ⡍⠁⠗⠊⠕

------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/spirit-general
Reply | Threaded
Open this post in threaded view
|

Re: Porting from Qi to X3

teajay-2
Le 02/06/2015 10:16, Mario Lang a écrit :

> teajay <[hidden email]> writes:
>
>> Le 02/06/2015 01:49, Mario Lang a écrit :
>>> Joel de Guzman <[hidden email]> writes:
>>>
>>>> On 6/1/15 4:44 PM, Seth wrote:
>>>>> On Mon, Jun 1, 2015, at 10:17 AM, Joel de Guzman wrote:
>>>>>>
>>>>>> I was thinking about this. I suppose we can inject a _repeat_count(ctx)
>>>>>> into the context so we can get it if we need to. I think the compiler
>>>>>> will optimize this out if it is unused.
>>>>>>
>>>>>
>>>>> If we're considering this, please think about the complementary, very
>>>>> often we parse things like:
>>>>>
>>>>>         vec(4): 1 2 3 4
>>>>>         vec(7): 0 0 1 0 3 3 3
>>>>>
>>>>> And we have to use locals like e.g.
>>>>>
>>>>>          "vec(" << uint_ [_a=_1] << "):" << repeat(_a) [ int_ ] << eol;
>>>>>
>>>>> It would probably help if there was an implicit _repeat_count local
>>>>> (that would be optimized out if unused)
>>>>>
>>>>> Alternatively, simple cases could be helped by the even more expressive
>>>>>
>>>>>          repeat("vec(" << uint_ << "):") [ int_ ] << eol;
>>>>>
>>>>> Or (to make implementation slightly simpler):
>>>>>
>>>>>          repeat(attribute_of ["vec(" << uint_ << "):"]) [ int_ ] << eol;
>>>>>
>>>>> Mor complicated scenarios will still require some extra state (locals<>
>>>>> again). Thinking about multiple dimension and derived counts (_1 * _2,
>>>>> or max(_1, _2) etc)
>>>>
>>>> Sounds good! I think we can provide a lot of info into the context.
>>>> A good thing about X3 is that everything is visible in the compiler
>>>> and thus can optimize the code very well, even through the rule
>>>> boundary.
>>>>
>>>> But first things first. We need better semantic actions. Imagine
>>>> writing what you wrote above using native c++ lambda! Ughh!
>>>
>>> Note that the most concise example from above
>>>
>>>>>          repeat("vec(" << uint_ << "):") [ int_ ] << eol;
>>>
>>> does not make use of semantic actions at all.  I guess something like the following
>>> (psuedo-code) could make it work.  Note the really cool line:
>>>
>>>                return repeat(arg_attr)[subject].parse(first, last, context, rcontext, attr);
>>>
>>> repeat has either arity one or two.  So a second version of this would
>>> need to be written, or the dynamic wrapper would need to be made
>>> variadic.
>>>
>>>
>>> template <typename Arg, typename Subject>
>>> struct dynamic_repeat_directive : ...
>>> {
>>>       using attribute_type =
>>>           typename traits::attribute_of<repeat_directive<Subject, ...>>::type;
>>>       ...
>>>
>>>       dynamic_repeat_directive(Arg const& arg, Subject const& subject)
>>>         : arg(arg), subject(subject) {}
>>>
>>>       template <...>
>>>       bool parse(first, last, context rcontext, attr) const
>>>       {
>>>            traits::attribute_of<Arg>::type arg_attr;
>>>            auto saved = first;
>>>            if (arg.parse(first, last, context, rcontext, arg_attr)) {
>>>                return repeat(arg_attr)[subject].parse(first, last, context, rcontext, attr);
>>>            }
>>>            first = saved;
>>>            return false;
>>>       }
>>>
>>>       Arg arg;
>>>       Subject subject;
>>> };
>>>
>>> struct repeat_gen
>>> {
>>>       ...
>>>
>>>       template <typename Arg>
>>>       struct dynamic_lvl1_gen
>>>       {
>>>           dynamic_lvl1_gen(Arg const& arg) : arg(arg) {}
>>>
>>>           template <typename Subject>
>>>           dynamic_repeat_directive<Arg, Subject>
>>>           operator[](Subject const& subject)
>>>           {
>>>               return { arg, subject };
>>>           }
>>>
>>>           Arg const& arg;
>>>       };
>>>
>>>       template <typename Arg, enable_if<is_parser<Arg>>>
>>>       dynamic_lvl1_gen<Arg> operator()(Arg const& arg)
>>>       {
>>>           return { arg };
>>>       }
>>> };
>>
>> Pretty cool ! And simple.
>
> Thanks.
>
> We can probably generalize it like this:
>
> template<typename Gen, typename Subject, typename... Arg>
> struct dynamic_parser : ...
> {
>      using attribute_type =
>          traits::attribute_of<
>              decltype(Gen{}(traits::attribute_type<Arg>::type()...)[std::declval<Subject>()])
>          >::type;
>      ...
>
>      template <...> bool parse(...)
>      {
>          std::tuple<traits::attribute_of<Arg>::type...> args;
>          ...
>          return std::apply(Gen{}, args)[subject].parse(...);
>      }
> }
>
> But I guess the infamous evaluation order problem is going to be an
> issue.  Also, since ``repeat`` only has two args, it is probably not
> worth the trouble to generalize this, let alone me not being experienced
> enough with variadic code like this.
>
> Joel?  What's your opinion on the idea in general?
> I can try to make it work for ``repeat`` if people like it.
>
> I think the motivating example is really very pretty.
>
> repeat("vec(" >> uint_ >> ")")[int_]
>
I have an idea to extend this and implement locals, based a bit on what
I proposed earlier.

The idea would be to define a pass_through directive to capture
references to attributes and push it onto the context for the following
parsers. It would look like this:

"vec(" >> local::a[uint_]>>")")>>repeat(local::a)[int_]

This would enable to overcome the implicit strict odering of you solution.

@MLang: If you like we can try to prototype this on some branch together.

Regards,

Thomas Bernard

------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/spirit-general
Reply | Threaded
Open this post in threaded view
|

Re: Porting from Qi to X3

Michael Powell-2
On Tue, Jun 2, 2015 at 2:15 PM, teajay <[hidden email]> wrote:

> Le 02/06/2015 10:16, Mario Lang a écrit :
>> teajay <[hidden email]> writes:
>>
>>> Le 02/06/2015 01:49, Mario Lang a écrit :
>>>> Joel de Guzman <[hidden email]> writes:
>>>>
>>>>> On 6/1/15 4:44 PM, Seth wrote:
>>>>>> On Mon, Jun 1, 2015, at 10:17 AM, Joel de Guzman wrote:
>>>>>>>
>>>>>>> I was thinking about this. I suppose we can inject a _repeat_count(ctx)
>>>>>>> into the context so we can get it if we need to. I think the compiler
>>>>>>> will optimize this out if it is unused.
>>>>>>>
>>>>>>
>>>>>> If we're considering this, please think about the complementary, very
>>>>>> often we parse things like:
>>>>>>
>>>>>>         vec(4): 1 2 3 4
>>>>>>         vec(7): 0 0 1 0 3 3 3
>>>>>>
>>>>>> And we have to use locals like e.g.
>>>>>>
>>>>>>          "vec(" << uint_ [_a=_1] << "):" << repeat(_a) [ int_ ] << eol;
>>>>>>
>>>>>> It would probably help if there was an implicit _repeat_count local
>>>>>> (that would be optimized out if unused)
>>>>>>
>>>>>> Alternatively, simple cases could be helped by the even more expressive
>>>>>>
>>>>>>          repeat("vec(" << uint_ << "):") [ int_ ] << eol;
>>>>>>
>>>>>> Or (to make implementation slightly simpler):
>>>>>>
>>>>>>          repeat(attribute_of ["vec(" << uint_ << "):"]) [ int_ ] << eol;
>>>>>>
>>>>>> Mor complicated scenarios will still require some extra state (locals<>
>>>>>> again). Thinking about multiple dimension and derived counts (_1 * _2,
>>>>>> or max(_1, _2) etc)
>>>>>
>>>>> Sounds good! I think we can provide a lot of info into the context.
>>>>> A good thing about X3 is that everything is visible in the compiler
>>>>> and thus can optimize the code very well, even through the rule
>>>>> boundary.
>>>>>
>>>>> But first things first. We need better semantic actions. Imagine
>>>>> writing what you wrote above using native c++ lambda! Ughh!
>>>>
>>>> Note that the most concise example from above
>>>>
>>>>>>          repeat("vec(" << uint_ << "):") [ int_ ] << eol;
>>>>
>>>> does not make use of semantic actions at all.  I guess something like the following
>>>> (psuedo-code) could make it work.  Note the really cool line:
>>>>
>>>>                return repeat(arg_attr)[subject].parse(first, last, context, rcontext, attr);
>>>>
>>>> repeat has either arity one or two.  So a second version of this would
>>>> need to be written, or the dynamic wrapper would need to be made
>>>> variadic.
>>>>
>>>>
>>>> template <typename Arg, typename Subject>
>>>> struct dynamic_repeat_directive : ...
>>>> {
>>>>       using attribute_type =
>>>>           typename traits::attribute_of<repeat_directive<Subject, ...>>::type;
>>>>       ...
>>>>
>>>>       dynamic_repeat_directive(Arg const& arg, Subject const& subject)
>>>>         : arg(arg), subject(subject) {}
>>>>
>>>>       template <...>
>>>>       bool parse(first, last, context rcontext, attr) const
>>>>       {
>>>>            traits::attribute_of<Arg>::type arg_attr;
>>>>            auto saved = first;
>>>>            if (arg.parse(first, last, context, rcontext, arg_attr)) {
>>>>                return repeat(arg_attr)[subject].parse(first, last, context, rcontext, attr);
>>>>            }
>>>>            first = saved;
>>>>            return false;
>>>>       }
>>>>
>>>>       Arg arg;
>>>>       Subject subject;
>>>> };
>>>>
>>>> struct repeat_gen
>>>> {
>>>>       ...
>>>>
>>>>       template <typename Arg>
>>>>       struct dynamic_lvl1_gen
>>>>       {
>>>>           dynamic_lvl1_gen(Arg const& arg) : arg(arg) {}
>>>>
>>>>           template <typename Subject>
>>>>           dynamic_repeat_directive<Arg, Subject>
>>>>           operator[](Subject const& subject)
>>>>           {
>>>>               return { arg, subject };
>>>>           }
>>>>
>>>>           Arg const& arg;
>>>>       };
>>>>
>>>>       template <typename Arg, enable_if<is_parser<Arg>>>
>>>>       dynamic_lvl1_gen<Arg> operator()(Arg const& arg)
>>>>       {
>>>>           return { arg };
>>>>       }
>>>> };
>>>
>>> Pretty cool ! And simple.
>>
>> Thanks.
>>
>> We can probably generalize it like this:
>>
>> template<typename Gen, typename Subject, typename... Arg>
>> struct dynamic_parser : ...
>> {
>>      using attribute_type =
>>          traits::attribute_of<
>>              decltype(Gen{}(traits::attribute_type<Arg>::type()...)[std::declval<Subject>()])
>>          >::type;
>>      ...
>>
>>      template <...> bool parse(...)
>>      {
>>          std::tuple<traits::attribute_of<Arg>::type...> args;
>>          ...
>>          return std::apply(Gen{}, args)[subject].parse(...);
>>      }
>> }
>>
>> But I guess the infamous evaluation order problem is going to be an
>> issue.  Also, since ``repeat`` only has two args, it is probably not
>> worth the trouble to generalize this, let alone me not being experienced
>> enough with variadic code like this.
>>
>> Joel?  What's your opinion on the idea in general?
>> I can try to make it work for ``repeat`` if people like it.
>>
>> I think the motivating example is really very pretty.
>>
>> repeat("vec(" >> uint_ >> ")")[int_]
>>
> I have an idea to extend this and implement locals, based a bit on what
> I proposed earlier.
>
> The idea would be to define a pass_through directive to capture
> references to attributes and push it onto the context for the following
> parsers. It would look like this:
>
> "vec(" >> local::a[uint_]>>")")>>repeat(local::a)[int_]
>
> This would enable to overcome the implicit strict odering of you solution.

Sounds like something like placeholders? Except, "locals" ... ?

> @MLang: If you like we can try to prototype this on some branch together.
>
> Regards,
>
> Thomas Bernard
>
> ------------------------------------------------------------------------------
> _______________________________________________
> Spirit-general mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/spirit-general

------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/spirit-general
Reply | Threaded
Open this post in threaded view
|

Re: Porting from Qi to X3

Joel de Guzman
In reply to this post by Mario Lang
On 6/2/15 4:16 PM, Mario Lang wrote:

> But I guess the infamous evaluation order problem is going to be an
> issue.  Also, since ``repeat`` only has two args, it is probably not
> worth the trouble to generalize this, let alone me not being experienced
> enough with variadic code like this.
>
> Joel?  What's your opinion on the idea in general?
> I can try to make it work for ``repeat`` if people like it.
>
> I think the motivating example is really very pretty.
>
> repeat("vec(" >> uint_ >> ")")[int_]

I'm working on something else generic, but still related right now
so I'm not sure. The advantage with locals (and we need locals,
I realized!) and inherited attributes (and we need those too!)
is that they are generic and applies to *all* parsers. You learn
one syntax and that's it, instead of different syntax for different
cases.

Anyway, the idea of using a parser as a parameter to another parser
is very interesting. It should probably be made more generic though.
I bet its use can extend beyond the repeat parser! But then again,
hmmm... let's keep it simple. I wouldn't mind a bit more verbosity
to make things simpler.

Aside: I see you guys are having fun with writing X3 parsers.
I guess that's a success! It was a lot more difficult with Qi.

Regards,
--
Joel de Guzman
http://www.ciere.com
http://boost-spirit.com
http://www.cycfi.com/


------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/spirit-general
Reply | Threaded
Open this post in threaded view
|

Re: Porting from Qi to X3

Mario Lang
Joel de Guzman <[hidden email]> writes:

> On 6/2/15 4:16 PM, Mario Lang wrote:
>> But I guess the infamous evaluation order problem is going to be an
>> issue.  Also, since ``repeat`` only has two args, it is probably not
>> worth the trouble to generalize this, let alone me not being experienced
>> enough with variadic code like this.
>>
>> Joel?  What's your opinion on the idea in general?
>> I can try to make it work for ``repeat`` if people like it.
>>
>> I think the motivating example is really very pretty.
>>
>> repeat("vec(" >> uint_ >> ")")[int_]
>
> I'm working on something else generic, but still related right now
> so I'm not sure. The advantage with locals (and we need locals,
> I realized!) and inherited attributes (and we need those too!)
> is that they are generic and applies to *all* parsers. You learn
> one syntax and that's it, instead of different syntax for different
> cases.
>
> Anyway, the idea of using a parser as a parameter to another parser
> is very interesting. It should probably be made more generic though.
> I bet its use can extend beyond the repeat parser!

Another place where this could be useful is with<my_tag>(uint_).

> But then again, hmmm... let's keep it simple. I wouldn't mind a bit
> more verbosity to make things simpler.

I can live with lambda-syntax, it might be verbose, but it is easy
to understand.  While Phoenix was really concise, it also required to
deal with things like the phoenix sequence (,) operator, or free
functions to do container manipulation.  Although I wish simple
constructs like _val = _attr could be revived.

struct _val_gen
{
    template <typename Context>
    auto operator()(Context const& context) const
    {
        return x3::get<rule_val_context_tag>(context);
    }

    template <typename RHS>
    auto operator=(RHS const& rhs) const
    {
        return [=](auto& ctx) { (*this)(ctx) = rhs(ctx); }
    }
};
_val_gen const _val{};

But I guess I am reinventing Phoenix here, which we shouldn't actually
do.  Still, being able to return lambdas makes this wrapping bussiness
quite easy.

> Aside: I see you guys are having fun with writing X3 parsers.
> I guess that's a success! It was a lot more difficult with Qi.

Not having to deal with Proto definitely helps to understand the big
picture and makes it a lot easier to implement a custom parser.
Also, when reading the code, you don't have to context-switch to any
other libraries.  With Qi, you definitely had to grok Proto, and likely
Phoenix as well.  X3 feels a lot more self-contained.  You might need to
deal with Fusion or MPL, but these are mostly hidden away in details.

I managed to port three parsers from Qi to X3, eol, eoi and matches.
These are rather simple and porting them was really really easy.

--
CYa,
  ⡍⠁⠗⠊⠕

------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/spirit-general
Reply | Threaded
Open this post in threaded view
|

Re: Porting from Qi to X3

Joel de Guzman
On 6/3/15 4:18 PM, Mario Lang wrote:

> I can live with lambda-syntax, it might be verbose, but it is easy
> to understand.  While Phoenix was really concise, it also required to
> deal with things like the phoenix sequence (,) operator, or free
> functions to do container manipulation.  Although I wish simple
> constructs like _val = _attr could be revived.
>
> struct _val_gen
> {
>      template <typename Context>
>      auto operator()(Context const& context) const
>      {
>          return x3::get<rule_val_context_tag>(context);
>      }
>
>      template <typename RHS>
>      auto operator=(RHS const& rhs) const
>      {
>          return [=](auto& ctx) { (*this)(ctx) = rhs(ctx); }
>      }
> };
> _val_gen const _val{};
>
> But I guess I am reinventing Phoenix here, which we shouldn't actually
> do.  Still, being able to return lambdas makes this wrapping bussiness
> quite easy.

I'm not sure if I should advertize it now, but here goes...

We have a thing called phoenix-lite. Thomas Heller initially worked
on it while we were in Aspen as a response to a challenge I posed:
rewrite a minimal subset of phoenix using c++14 in ONE header file
with no dependencies. He did it. After Aspen, I worked on it more
and refined the code.

It's cool and best of all, it works side by side with native lambda.
Now you know why I want the lambda overloads thing. That guy will
most probably migrate to phoenix-lite.

Oh, compile time? blink of an eye :-)

regards,
--
Joel de Guzman
http://www.ciere.com
http://boost-spirit.com
http://www.cycfi.com/


------------------------------------------------------------------------------
_______________________________________________
Spirit-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/spirit-general