Boost logo

Proto :

Subject: Re: [proto] proto Digest, Vol 4, Issue 13
From: Christophe Henry (christophe.j.henry_at_[hidden])
Date: 2010-10-15 02:50:43


> // A collection of actions indexable by rules.
> struct MyActions
> {
>    template<typename Rule>
>    struct action;
> };
>
> // A helper that finds the appropriate action by looking it
> // up by rule
> template<typename Rule, typename Actions>
> struct MyWhen
>  : proto::when< Rule, typename Actions::template action<Rule> >
> {};
>
> // An easier way to dispatch to a tag-specific sub-grammar
> template<typename Tag, typename Actions>
> struct MyCases
>  : proto::not< proto::_ >
> {};
>
> template<typename Actions>
> struct MyCasesImpl
> {
>    template<typename Tag>
>    struct case_
>      : MyCases<Tag, Actions>
>    {};
> };
>
> // Define an openly extensible grammar using switch_
> template<typename Actions = MyActions>
> struct MyGrammar
>  : proto::switch_< MyCasesImpl<Actions> >
> {};
>
> // Define a grammar rule for int terminals
> struct IntTerminalRule
>  : proto::terminal<int>
> {};
>
> // Define a grammar rule for char terminals
> struct CharTerminalRule
>  : proto::terminal<char>
> {};
>
> // OK, handle the terminals we allow:
> template<typename Actions>
> struct MyCases< proto::tag::terminal, Actions >
>  : proto::or_<
>        MyWhen< IntTerminalRule,  Actions >
>      , MyWhen< CharTerminalRule, Actions >
>    >
> {};
>
> // Now, populate the MyActions metafunction class
> // with the default actions:
>
> template<>
> struct MyActions::action< IntTerminalRule >
>  : DoIntAction
> {};
>
> template<>
> struct MyActions::action< CharTerminalRule >
>  : DoCharAction
> {};
>
>
> Some things to note about this solution:
>
> - MyGrammar can be parameterized by a set of actions.
>
> - The actions are accessed by indexing via a well-defined
>  and openly extensible set of grammar rules.
>
> - Although the grammar is extensible, it is not mutable.
>  That is, new constructs can be added, but existing ones
>  cannot be changed. That makes it easier to understand
>  what it means for an expression to match the grammar.
>  (If a different grammar is desired, a new one needs to be
>  defined. It can reuse parts of MyGrammar, but MyGrammar
>  itself remains unchanged. This, I think, is desirable.)
>
> - The Actions parameter has *no* effect on what expressions
>  match the MyGrammar. MyGrammar<MyActions> and MyGrammar<
>  YourActions> both match exactly the same set of expressions.
>
> - A new set of actions can be created easily by delegating
>  to MyActions::action by default, and specializing only those
>  rules that need custom handling.
>
> I'm attaching the beginnings of a Phoenix implementation that is built
> using this technique. It is obviously just a shell. No nice actor
> wrappers or anything. This is just to demonstrate that the technique
> works. It builds an extensible core, handles placeholders, terminals
> (including reference_wrapped terminals), and if_/then_/else_ built as an
> extension to the core.
>
> Comments?

Oh yes sure.
1. Why to break my head so early in the morning (for me)? :)
2. Seriously, I'm not sure I understood it completely but it looks
exactly like what I was looking for. IIUC, I can use this to describe
the rules of a common grammar (not just terminals) and then use
different transforms for different end results. This could solve the
issue I talked about at the BoostCon, the impossibility to fit eUML
inside phoenix, and for a few new ideas I have in mind.
Now this starts becoming interesting (why did it take so long to come
here?). As soon as I finish the urgent MSM tasks waiting for action,
I'll give it a try.

Again cool stuff, thanks :)

Christophe


Proto list run by eric at boostpro.com