djowel / spirit_x3 Goto Github PK
View Code? Open in Web Editor NEWSpirit X3 Experimental
Spirit X3 Experimental
The following parser does not parse a,z,A,Z,0,9 as part of an id without my workaround. The used version of boost.spirit is e95d80d.
x3::rule<class id, std::string> const id("id");
auto const id_def =
no_skip[
(
char_('_') |
char_('A', 'Z') |
char_('a', 'z')
//workaround
| char_("AZaz")
) >>
*(
char_('_') |
char_('A', 'Z') |
char_('a', 'z') |
char_('0', '9')
//workaround
| char_("AZaz09")
)
];
BOOST_SPIRIT_DEFINE(id);
Hi Joel,
would it be possible, to add a functionality for x3::lit which buffers the used string? From what I undestand if I write
std::string value = "Stuff";
auto rule = x3::lit(value);
lit only takes a reference to value. So if I do something like this:
auto make_rule()
{
std::string str = get_string(); //from somewhere
return x3::lit(str);
}
auto rule = x3::space >> make_rule();
It either will crash while parsing or not parse (I had the latter with msvc). A nice solution would be a x3::buffered_lit which stores the string inside the rule and is copied - if that is possible.
Now I would add such a feature myself, but I am rather helpless when looking into the spirit code.
I actually solved this issue by providing a buffer for the string, but it would be a nice feature. Might be a corner case though.
My use case is found here
In my current work, I was getting a little tired of having to use BOOST_SPIRIT_DEFINE on all my rules / definitions. To get around it, I added a little hack into the X3 code:
template <class T, class=void> struct allow_default : std::true_type {};
and edited the template signature of the default parse_rule()
to
template <typename ID, typename Attribute, typename Iterator, typename Context, typename ActualAttribute, std::enable_if_t<allow_default<ID>::value, int> = 0>
and in my own code write:
template <class T> static constexpr auto define = false;
and
template <typename ID, typename Attribute, class I, class C, class A, std::enable_if_t<(!is_same<decltype(define<ID>), bool const>), int> = 0> bool parse_rule(x3::rule<ID, Attribute> rule, I& first, I const &last , C const &context, A &attr) { static auto const def = (rule = define<ID>); return def.parse(first, last, context, boost::spirit::x3::unused, attr); }
namespace boost {namespace spirit { namespace x3 { template <class T> struct allow_default<T, std::enable_if_t<(!std::is_same<decltype(my_code::define<T>), bool const>) >> : std::false_type {}; }}}
With that in place I can just write the helper macro:
`
`
and then write e.g.
DEF(executable_program) = +program_unit;
This way I don't need to do BOOST_SPIRIT_DEFINE anywhere; the implementation of the rule is found by explicit variable template specialization (thus C++14 only I believe). I would prefer type template specialization, but I think it's not as clean in this case.
This approach would be simpler if there was support in X3 for user specialization to avoid the BOOST_SPIRIT_DEFINE avenue. Also, it seems like other C++14 people might like it more since it gets rid of the extra tying-together step. Plus this approach is not as macro-based (my DEF is just a little alias).
I may have overlooked some issue...but it seems to compile and work all right for me. If so, maybe it could be an enhancement? Of course I'm not recommending the exact approach I take above, just the general idea.
This test case fails:
{
// literals wrapping strings shall not be stored
std::string attr;
test_attr("foo", lit("foo"), attr, true);
BOOST_TEST((attr.empty()));
}
...while this one suceeds:
{
// same as above, but with lit(char)
std::string attr;
test_attr("foo", lit('f') >> lit('o') >> lit('o'), attr, true);
BOOST_TEST((attr.empty()));
}
If the parser depends on the attribute of one parser before it, or some globle state, how can I achieve that?
Hello,
Using auto, how is it possible to share rules between différents files ?
In fact, I need to use a rule in different grammars but :
Thank you in advance !
Victor
...in X3.
Is it not fundamental or lightweight? Is there an obvious way that permutation can be implemented by the user? (I don't know enough about grammars to tell)
x3::phrase_parse(
str.begin(), str.end(),
(x3::lit("a") >> '=' >> x3::double_)
^
(x3::lit("b") >> '=' >> x3::double_)
,
x3::space,
ab
);
Currently I am doing phrase_parse( ..., *( (x3::lit("a") >> "=" >> x3::double_)[action] | (x3::lit("b") >> "=" >> x3::double_)[action] ) ...)
but I think it is not the same.
Hello,
Has this repo been pulled into the master (or "develop") branch of the Boost.Spirit repo?
Thanks!
In Spirit v3 (distributed with boost 1.60) the following code doesn't compile:
double d1 = 0.0, d2 = 0.0;
x3::phrase_parse(begin, end, x3::double_ >> x3::double_, x3::space, d1, d2);
The problem is passing two attribute arguments (passing only std::pair<double, double>
works). As a temporary workaround I use this code:
template<class It, class Grammar, class Skipper, class T1, class... Ts, typename = typename std::enable_if<sizeof...(Ts)>=1>::type >
bool phrase_parse(It&& it1, It&& it2, Grammar&& g, Skipper&& s, T1&& t1, Ts&&... ts){
auto v = boost::fusion::vector_tie(std::forward<T1>(t1), std::forward<Ts>(ts)...);
return boost::spirit::x3::phrase_parse(it1, it2, g, s, v);
}
It would be nice if we could have a separate Sentinel
template argument to represent the last
iterator. This is pretty much the same approach of the ranges-v3 library from Eric Niebler; the advantage is that sometimes the last
iterator requires much less information than a normal iterator.
Consider the case where the Iterator is actually wrapping a lexer, then the last Iterator need to contain a copy of the lexer object (never used), just for the sake of having the same type as the first
iterator.
As far as I can see spirit only uses the last
iterator for equality/inequality comparisons, so this should be just a matter of adding an additional template parameter to every parse
function, and replace Iterator last
with Sentinel last
.
This is not really an issue, I apologize if this is not the proper place.
Could you please document somewhere how to run tests? I'd like to submit a patch, but can't do it without running tests which I couldn't figure out how :)
Simple run jam in libs/spirit/test directory doesn't work.
$ jam
Jamfile:12: in module scope
rule import unknown in module
I am not familiar with Boost build system, but I imagine that to make tests work spirit_x3 must be placed somewhere under regular boost source tree and/or some env variables must be set. Could you put basic basic instructions on github wiki or at least in a reply to this ticket please?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.