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(:foo) >> 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(:bar) >> @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(:foo) >> 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