For that matter, I've been wondering. Is:

rule :foobar do
   stuff
end

Really just syntactic sugar for exactly:

def foobar
  stuff
end

?

Either way, can you compose simply using ruby modules instead?

module Foo
   rule :foobar do
     stuff
   end
end

class FooBar < Parslet::Parser
   include Foo
....
end

?

I guess that would require using non-conflicting rules for your names in Foo and Bar, if it works at all.


On 5/7/2011 10:25 AM, Ant Skelton wrote:
Hi,

I have a complex application that originally included two treetop grammars; one for a C like language, and another for a Ruty style templating engine. I have split the former into a language grammar and an infix notation expression grammar, so I need to "compose" these, by which I mean include the expression grammar into the language grammar. My ultimate goal is to reuse the expression grammar in the templating grammar also, to give my template syntax more oomph.

The approved way to do this, as per the rdocs, is something like:

    class FooBarParser < Parslet::Parser
        root(:foobar)

        rule(:foobar) do
    FooParser.new.as <http://FooParser.new.as>(:foo) >>
    BarParser.new.as <http://BarParser.new.as>(:bar)
        end
    end

But I was wondering if there were any disadvantages to reusing the same parser object, like this:

    class BarFooParser < Parslet::Parser

        def initialize(*args)
            super(*args)
            @foo = FooParser.new
            @bar = BarParser.new
        end

        root(:barfoo)

        rule(:barfoo) do
            @bar.as <http://bar.as>(:bar) >> @foo.as
    <http://foo.as>(:foo)
        end
    end

or even this:

    class FooBazParser < Parslet::Parser
        class << self; attr_accessor :foo, :baz; end

        def initialize(*args)
            super(*args)
            self.class.foo ||= FooParser.new
            self.class.baz ||= BazParser.new
        end

        root(:foobaz)

        rule(:foobaz) do
    self.class.foo.as <http://self.class.foo.as>(:foo) >>
    self.class.baz.as <http://self.class.baz.as>(:baz)
        end
    end

These all work ok in my simple test cases, but I'm wondering if parsers store any state which might make this approach go wrong once the parser instance is referenced in multiple rules, or on multiple branches of an ordered choice expression? And what's the overhead of a Parser.new ? Is it even worth bothering?

cheers
ant

Reply via email to