On 1/30/08, Clifford Heath <no / spam.please.net> wrote: > Phil Tomson wrote: > > What do you think would be involved to create this framework for > > multiple output langauages? Any design docs? > > No design docs, but the Ruby text is built using a Ruby builder, > which makes it sound fine and ready to go... except that the API > to the builder allows arbitrary text strings to be appended, and > the API assumes modules and extend() etc... Basically the builder > API needs to be cleaned up to encapsulate the semantics and to not > assume Ruby. Then when doing the first *other* language, cleaned > up some more to catch the things you missed the first time. :-) > Yeah, I noticed the Builder stuff. I did some changes (experimentally) to my local version of TreeTop to add an on_success_callback that gets called when a rule parses successfully... turns out I didn't need that functionality just now, but it did get me familiar with some of the inards. Thinking out loud here... So let's aay somebody did a C++ backend. As has been mentioned, the current builder makes use of Ruby's extend functionality quite heavily - modules get built for each alternative and then get mixed in as needed. To get the functionality in C++ I suppose you could just build new classes for each rule alternative. For example the following snippet from tt: module TopLevelSav1 def get_ports puts "unknown ports" end def port_decl? false end def entity_decl? puts "Not an entity decl!" false end end def _nt_top_level_sav start_index = index cached = node_cache[:top_level_sav][index] if cached @index = cached.interval.end return cached end i0, nr0 = index, [] r1 = _nt_entity_decl r1.extend(TopLevelSav0) nr0 << r1 if r1.success? r0 = r1 r1.update_nested_results(nr0) else s2, nr2, i2 = [], [], index loop do r3 = parse_anything(SyntaxNode) nr2 << r3 if r3.success? s2 << r3 else break end end r2 = AnyNode.new(input, i2...index, s2, nr2) r2.extend(TopLevelSav1) .... The second extend there seems fairly straighforward: when you generate the AnyNode class, generate a subclass that includes the methods defined in TopLevelSav1. The first extend seems a bit more problematic. We get a SyntaxNode object back from the _nt_entity_decl. We could define a class TopLevelSav0 that includes the methods defined in that module and then pass the SyntaxNode in and construct it like so: class TopLevelSav1 : public SyntaxNode { public: vector< Port* > getports(); bool port_decl(); bool entity_decl(); TopLevelSav1(SyntaxNode* sn); } ... later: SytaxNode* r1; ... r1 = _nt_entity_decl(); r1 = new TopLevelSav1(r1); Or maybe better yet: r1 = dynamic_cast<TopLevelSav1*>(_nt_entity_decl()); Thoughts? Oh, BTW: right now we allow Ruby code in rules: rule foo 'something' { def got_something? true end } end How would we go about this for other languages? rule foo 'something' { #C++ code: bool got_something() { return true; } // but how would you handle scoping here? } end It seems to me that I'd like to prototype the grammar in Ruby and then transfer it over to C++ (or ObjC ) later on after I'm sure everything is working. How could we make this multi-language targetting easier? Phil