From: Clifford Heath Date: 2008-01-28T20:34:57+09:00 Subject: Re: Treetop parser (or PEG in general?) questions Phrogz wrote: > An additional Treetop question that has me stumped: > > I have a simple grammar as listed at the end of this post. In the > following code, why can I not get the 'to_xml' method to flow through > the 'inline_atom' rule, to use the to_xml of the underlying wrrd and > numz classes? I'll make a commentary first, leading up to your answer :-). In inline_content, you have a sequence containing a sequence: > items:( item:inline_atom wspace )* last_item:inline_atom {... which creates *two* SyntaxNodes. Your code block is emitted into the module InlineContent2, which is extended into the outer SyntaxNode, as you see in the dump of the syntax tree. The notation: SyntaxNode+InlineContent2+InlineContent1 in the dump says that the object is of class SyntaxNode, but is extended with the two modules named. The dump also shows the interesting methods that have been added to your nodes... cute, eh? This code block does: methods.include?('first_item') which will always fail, since first_item is nowhere defined. I think you meant to say: def all_items items.elements.map{ |e| e.item } + [last_item] end You should use respond_to?. not methods.include? anyhow if you want to test for an alternative being taken - this saves building an array just to see whether it contains your element. > Why does inline_atom not provide the #wrrd and #numz > SyntaxNode methods inside the handlers for inline_atom? How can I > rewrite inline_atom to allow the flow through? The alternative that contains wrrd has only that element, i.e. it's not a sequence or a repetition, so it doesn't get a SyntaxNode of its own. Any code block you add is a module that gets extended into the node returned from the wrrd rule (and must refer to that node as self, not by the name wrrd), as you'll see in the dump: the SyntaxNode which is extended with the Wrrd0 module (which is created by the wrrd rule) is a direct child of the inline_content node. So in this case, you can remove the two code blocks in the inline_atom rule and your program just works. Note that you can have a code block on each alternative as well as the rule as a whole: rule inline_atom ( numz / wrrd { def bar; ... end } ) { def foo; ... end} end This adds the method foo to whichever alternative was taken, but the method bar only if wrrd was taken. In both cases, the methods are defined in a module that is extended into the node; no additional nodes are created by this rule. Phil's advice is good - run tt and read the emitted code - it's not difficult and will help you understand whas going on. Clifford Heath.