|
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