-
Notifications
You must be signed in to change notification settings - Fork 159
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
boost::qvm not usable in boost::spirit::x3 #720
Comments
Tip: use clang++ because of g++ 'internal compiler error' |
Try mimicking for qvm what's done with boost::array in fusion here:
https://www.boost.org/doc/libs/develop/libs/fusion/doc/html/fusion/adapted/boost__array.html
It works for me:
… //copy&pasted from:
// ./qvm-not-usable.1rule-deque.cpp
//then just changed deque to boost::array & included the fusion
adaptation for boost::array.
//===================
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/adapted/boost_array.hpp>
namespace x3 = boost::spirit::x3;
namespace fusion = boost::fusion;
using scalar_t = int;
auto const scalar =
x3::int_;
#define VECTOR_N 3
int constexpr vector_n=VECTOR_N;
#include <boost/array.hpp>
using vector_t =
boost::array<scalar_t,vector_n>
;
#include <boost/fusion/adapted/boost_array.hpp>
#include <boost/fusion/include/io.hpp>
using fusion::operators::operator<<;
auto const vector_def
= x3::lit("center")
> x3::lit('=')
> x3::lit('<')
> scalar
> x3::lit(',')
> scalar
> x3::lit(',')
> scalar
> x3::lit('>')
> x3::eoi
;
auto const vector = x3::rule<struct vector_, vector_t>{"vector"}
= vector_def
;
#include <iostream>
int main() {
std::string input = "center = <1,2,3>";
vector_t result;
auto first=input.begin();
auto last=input.end();
x3::phrase_parse(first, last, vector, x3::space, result);
std::cout<<"result="<<result<<";\n";
return 0;
}
On 3/27/2022 4:41 PM, Mike Gresens wrote:
|#include <boost/qvm/vec.hpp> #include <boost/spirit/home/x3.hpp>
namespace qvm = boost::qvm; namespace x3 = boost::spirit::x3; using
scalar_t = float; auto const scalar = x3::rule<struct scalar_,
scalar_t>{"scalar"} = x3::float_; using vector_t = qvm::vec<scalar_t,
3>; template <size_t N> struct foo { template <typename C> void
operator()(C const& ctx) const { x3::_val(ctx).a[N] = x3::_attr(ctx);
} }; auto const vector = x3::rule<struct vector_, vector_t>{"vector"}
= x3::lit('<') > scalar [foo<0>()] > x3::lit(',') > scalar [foo<1>()]
> x3::lit(',') > scalar [foo<2>()] > x3::lit('>'); int main() {
std::string input = "center = <0,0,0>"; vector_t result;
x3::phrase_parse(input.begin(), input.end(), x3::lit("center") >
x3::lit('=') > vector > x3::eoi, x3::space, result); return 0; } |
Tip: use clang++ because of g++ 'internal compiler error'
—
Reply to this email directly, view it on GitHub
<#720 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAEFBA5AIADUABFSGQGUU7TVCDPY5ANCNFSM5RYXHM2Q>.
You are receiving this because you are subscribed to this
thread.Message ID: ***@***.***>
|
Actually, there not even a need for any rule's in this case. This works
for me:
x3::phrase_parse(first, last, vector_def, x3::space, result);
and outputs:
result=(1 2 3);
…On 3/29/2022 7:27 AM, cppljevans wrote:
Try mimicking for qvm what's done with boost::array in fusion here:
https://www.boost.org/doc/libs/develop/libs/fusion/doc/html/fusion/adapted/boost__array.html
It works for me:
> //copy&pasted from:
> // ./qvm-not-usable.1rule-deque.cpp
> //then just changed deque to boost::array & included the fusion
> adaptation for boost::array.
> //===================
> #include <boost/spirit/home/x3.hpp>
> #include <boost/fusion/adapted/boost_array.hpp>
>
> namespace x3 = boost::spirit::x3;
> namespace fusion = boost::fusion;
>
> using scalar_t = int;
>
> auto const scalar =
> x3::int_;
> #define VECTOR_N 3
> int constexpr vector_n=VECTOR_N;
> #include <boost/array.hpp>
> using vector_t =
> boost::array<scalar_t,vector_n>
> ;
> #include <boost/fusion/adapted/boost_array.hpp>
> #include <boost/fusion/include/io.hpp>
> using fusion::operators::operator<<;
>
> auto const vector_def
> = x3::lit("center")
> > x3::lit('=')
> > x3::lit('<')
> > scalar
> > x3::lit(',')
> > scalar
> > x3::lit(',')
> > scalar
> > x3::lit('>')
> > x3::eoi
> ;
>
> auto const vector = x3::rule<struct vector_, vector_t>{"vector"}
> = vector_def
> ;
>
> #include <iostream>
> int main() {
> std::string input = "center = <1,2,3>";
> vector_t result;
> auto first=input.begin();
> auto last=input.end();
> x3::phrase_parse(first, last, vector, x3::space, result);
> std::cout<<"result="<<result<<";\n";
> return 0;
> }
On 3/27/2022 4:41 PM, Mike Gresens wrote:
> |#include <boost/qvm/vec.hpp> #include <boost/spirit/home/x3.hpp>
> namespace qvm = boost::qvm; namespace x3 = boost::spirit::x3; using
> scalar_t = float; auto const scalar = x3::rule<struct scalar_,
> scalar_t>{"scalar"} = x3::float_; using vector_t = qvm::vec<scalar_t,
> 3>; template <size_t N> struct foo { template <typename C> void
> operator()(C const& ctx) const { x3::_val(ctx).a[N] = x3::_attr(ctx);
> } }; auto const vector = x3::rule<struct vector_, vector_t>{"vector"}
> = x3::lit('<') > scalar [foo<0>()] > x3::lit(',') > scalar [foo<1>()]
> > x3::lit(',') > scalar [foo<2>()] > x3::lit('>'); int main() {
> std::string input = "center = <0,0,0>"; vector_t result;
> x3::phrase_parse(input.begin(), input.end(), x3::lit("center") >
> x3::lit('=') > vector > x3::eoi, x3::space, result); return 0; } |
>
> Tip: use clang++ because of g++ 'internal compiler error'
>
> —
> Reply to this email directly, view it on GitHub
>
<#720 (comment)>,
> or unsubscribe
>
<https://github.com/notifications/unsubscribe-auth/AAEFBA5AIADUABFSGQGUU7TVCDPY5ANCNFSM5RYXHM2Q>.
> You are receiving this because you are subscribed to this
> thread.Message ID: ***@***.***>
>
—
Reply to this email directly, view it on GitHub
<#720 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAEFBA7FUNWH5MAUUIXVHXDVCLZMPANCNFSM5RYXHM2Q>.
You are receiving this because you are subscribed to this
thread.Message ID: ***@***.***>
|
Thanks for your answers @cppljevans But your parser produces boost::array and not boost::qvm::vec Parsing as array is simple... But the goal is to produce a boost::qvm::vec |
But my point was that you could just duplicate the
fusion/adapted/boost_array.hpp file and just replace boost::array with
qvm::vec
and rename to adapted_qvm.hpp or something similar.
…On 3/29/2022 10:09 AM, Mike Gresens wrote:
Thanks for your answers @cppljevans <https://github.com/cppljevans>
But your parser produces boost::array and not boost::qvm::vec
Parsing as array is simple...
just use
#include <boost/fusion/adapted/std_array.hpp>
But the goal is to produce a boost::qvm::vec
—
Reply to this email directly, view it on GitHub
<#720 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAEFBA5YSG4KH5U4TRDP4UDVCMML3ANCNFSM5RYXHM2Q>.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
@octopus-prime I've started to create a boost/fusion/adapted/qvm_vec directory which is essentially a copy of boost/fusion/adapted/std_array with "semi-obvious" modifications to adapt it to qvm::vec. It's tedious, but before I go any further, I was wondering if you'd already done that; hence, such efforts on my part would be needless. Please let us know if you are trying to do that, and if so, please let us know the progress. TIA. |
Hi @cppljevans no - i did not start any adaptation.
Way to much! I am just a qvm/spirit user. So i am very glad to hear that you want to do the adaptation :-) |
Without your adaptation my plan would be
It's a lot of boilerplate but should work fine... |
Hi,
|
@octopus-prime , you could use BOOST_FUSION_ADAPT_STRUCT if you're careful to use a 2 element preprocessor sequence, as shown below: //copy&pasted from:
// ./qvm-not-usable.1rule.cpp
//then added adapt_struct with 2 element arg (type,name)
//===================
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/at_c.hpp>
#include <boost/qvm/vec.hpp>
namespace qvm = boost::qvm;
namespace x3 = boost::spirit::x3;
namespace fusion = boost::fusion;
using scalar_t = int;
auto const scalar =
x3::int_;
#define VECTOR_N 2
int constexpr vector_n=VECTOR_N;
using vector_t =
qvm::vec<scalar_t,vector_n>
;
BOOST_FUSION_ADAPT_STRUCT(vector_t, (scalar_t,a[0]), (scalar_t,a[1]));
#include <boost/fusion/include/io.hpp>
using fusion::operators::operator<<;
auto const vector_def
= x3::lit("center")
> x3::lit('=')
> x3::lit('<')
> scalar
> x3::lit(',')
> scalar
> x3::lit('>')
> x3::eoi
;
#include <iostream>
int main() {
std::string input = "center = <1,2>";
vector_t result;
auto first=input.begin();
auto last=input.end();
x3::phrase_parse(first, last, vector_def, x3::space, result);
std::cout<<"result="<<result<<";\n";
return 0;
} which, at least for me, produces output: Compilation finished at Mon Apr 4 06:34:11 |
Thank you @lakeweb and @cppljevans ! Looks like you both avoided the critical Instead you see someting like So i tried
without success. Still ugly expectation failures. |
@octopus-prime , the following minor change to previous code, when defined(USE_VECTOR_RULE), does use rule: //copy&pasted from:
// ./qvm-not-usable.1rule.cpp
//then added adapt_struct with 2 element arg (type,name)
//===================
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/at_c.hpp>
#include <boost/qvm/vec.hpp>
namespace qvm = boost::qvm;
namespace x3 = boost::spirit::x3;
namespace fusion = boost::fusion;
using scalar_t = int;
#define VECTOR_N 2
int constexpr vector_n=VECTOR_N;
using vector_t =
qvm::vec<scalar_t,vector_n>
;
BOOST_FUSION_ADAPT_STRUCT(vector_t, (scalar_t,a[0]), (scalar_t,a[1]));
#include <boost/fusion/include/io.hpp>
using fusion::operators::operator<<;
auto const scalar
= x3::int_
;
auto const vector_def
= x3::lit("center")
> x3::lit('=')
> x3::lit('<')
> scalar
> x3::lit(',')
> scalar
> x3::lit('>')
> x3::eoi
;
#define USE_VECTOR_RULE
#ifdef USE_VECTOR_RULE
auto const vector_ = x3::rule<struct vector_, vector_t>{"vector"} =
vector_def
;
#endif//USE_VECTOR_RULE
#include <iostream>
int main() {
#ifdef USE_VECTOR_RULE
{//parse error
std::string input = "center = <1>";
vector_t result;
auto first=input.begin();
auto last=input.end();
x3::phrase_parse(first, last, vector_, x3::space, result);
std::cout<<"result="<<result<<";\n";
}
#else
{//parse success
std::string input = "center = <1,2>";
vector_t result;
auto first=input.begin();
auto last=input.end();
x3::phrase_parse(first, last, vector_def, x3::space, result);
std::cout<<"result="<<result<<";\n";
}
#endif
return 0;
} and when run, with input containing error, produces HUGE error output. Is this kind of output what you were hoping for?
|
These are the compiler erros i opened this issue for... And if you want to handle
|
This ambiguous conversion error is eliminated if: boost/qvm/vec.hpp is changed to contain: #include <boost/spirit/home/x3/support/unused.hpp>
#include <type_traits>
namespace boost { namespace qvm {
template <class T,int D>
struct
vec
{
T a[D];
template
< class R
, typename Enable=
std::enable_if_t
< !std::is_same_v<R,boost::spirit::x3::unused_type>
>//don't allow conversion to boost::spirit::x3::unused_type
//let unused_type to handle that.
>
operator R() const
{
R r;
assign(r,*this);
return r;
}
};
.
.
.
}}//boost::qvm IOW, the "convenient" conversion operators lead to this "annoyingly inconvenient" error. |
OTOH, instead of #720 (comment), To be more specific, here's an example of the change in one primitive
where, obviously, in the above, /home/evansl/prog_dev/boost.org/boost.replacements Similar changes could be made to other primitive parsers. In short, by simply adding another template parameter, IgnoreContext, to the parse @djowel , that seems a simple solution. Is there some downside to such a |
Pardon, I've not been actively following this thread. Does this mean changing all primitive parsers? |
I think so. The problem is that the primitive parsers have
'unused_type' as the type of one of the arguments,
and unused_type has conversion operator from anything to unused_type.
Unfortunately, qvm::vec also
has a conversion operator that can convert qvm::vec to unused_type.
This leads to the compiler error
about ambiguous conversions. The easiest workaround is as I described
in my previous comment.
…On 4/25/2022 6:11 PM, Joel de Guzman wrote:
@djowel <https://github.com/djowel> , that seems a simple
solution. Is there some downside to such a
solution?
Pardon, I've not been actively following this thread. Does this mean
changing all primitive parsers?
—
Reply to this email directly, view it on GitHub
<#720 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAEFBAZVST6CLWTSSLO76VDVG4RATANCNFSM5RYXHM2Q>.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Isn't this an issue of |
The qvm team was working on this issue -> boostorg/qvm#39 |
Thanks @octopus-prime ! |
If you try to parse
boost::qvm::vec<float, 3>
you fail with compiler errors:
error: conversion from 'boost::qvm::vec<float, 3>' to 'boost::spirit::x3::unused_type' is ambiguous
reason:
The text was updated successfully, but these errors were encountered: