Boost logo

Boost Users :

Subject: Re: [Boost-users] [Spirit 2] Questions related to generating grammars meta-dynamically
From: Hartmut Kaiser (hartmut.kaiser_at_[hidden])
Date: 2010-11-29 16:55:28


> I'm trying to create a serialization facility that builds the underlying
> Spirit grammars based on a data model extracted from user-supplied types
> (I guess meta-dynamically ought to be the right word :) ). In doing so, I
> seem to quickly run out of documentation coverage and accumulate questions
> that are not easily answered by perusing the source code. Here are the
> more painful members of that collection, posted in the hopes that someone
> more informed might answer them for me:
>
> - What are the respective scopes of the rule and the grammar?
> Specifically, within a parser expression (situated within a grammar's
> constructor, according to the pattern established in the examples) which
> of the locals<> can I refer to in the sub-expressions specifying explicit
> parser parameters and semantic actions?

locals<> are - well - local to the rule they are defined for. Each
invocation of that rule creates a new instance of the local variables, very
much like local vaiables in functions.

> - I'd like to write a functor that selects one of the grammars from a list
> (Fusion sequence), and passes an argument (inherited attribute) to it; the
> [parser-like] result returned by this functor would then be used in an
> enclosing parser expression. Is there an easily computable type that such
> a functor can return? I have noticed that the implementations of
> grammar<>::operator() return a very intricate construct that would be hard
> to replicate outside Spirit code --
>
> proto::terminal<
> spirit::qi::parameterized_nonterminal<
> start_type, supplied-argument-types...
> >
> >

I must admit I don't fully understand what you're trying to achieve. But one
thing I do know for sure: you shouldn't need to even look at proto, not even
talking about using it. Everything should be accessible by utilizing
Spirit's own facilities.

If you need to invoke an arbitrary parser at runtime, try to look at the
lazy() construct, which takes whatever is passed to it and evaluates it as a
parser expression. See here for an example:
http://boost-spirit.com/home/articles/qi-example/nabialek-trick/

> -- but maybe there is a simpler front-end type the above is convertible to
> and that will still work as a component of parser expression?

Spirit has a meta-layer, we call it the auto facilities. It's essentially a
(extensible) mapping from certain (primitive) data types to the
corresponding parser/generator. By default, it supports all built-in data
types, fusion sequences (parser/generator sequences), boost::variant
(alternatives), stl containers (Kleene star) and boost::optional (optional
expressions). You can use it in the API as:

    string s("123");
    int val = 0;
    parse(s.begin(), s.end(), val);

look'Ma, no explicit grammar, Spirit deduces the parser expression from the
attribute type. The other possibility is to use the auto_ parser component
doing very similar things
(http://www.boost.org/doc/libs/1_45_0/libs/spirit/doc/html/spirit/qi/referen
ce/auto.html).

The meta-function responsible for this trick is

    boost::spirit::traits::create_parser<AttributeType>

which has an embedded typedef 'type' representing the parser expression
needed to fill the AttributeType (see here:
http://www.boost.org/doc/libs/1_45_0/libs/spirit/doc/html/spirit/advanced/cu
stomize/auto.html).

Regards Hartmut
---------------
http://boost-spirit.com


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net