> // 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 mailing list proto@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/proto