Hi Ant, > 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
This should work well: all parsers are atoms as well, so you just concatenate them. And since rules memoize the parsers generated anyway, you'll only create one instance per FooBarParser instance. This means that the following tricks are not needed! > But I was wondering if there were any disadvantages to reusing the same > parser object, like this: > [snipped: Instance variable example] [snipped: Class variable example] > 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? Parsers (Parslet::Parser) have practically no state unless used. Then they keep a memoize structure of <rule_name, parser atom> tuples around. Parslet atoms have some state, like the last error that occurred in them. This is very limited and only created once a parse is attempted. Nothing that prohibits reuse of instances. Most state is passed through the parser tree during the parse and thrown away afterwards. You can look at it that way: If creating parsers were costly, you could not create hundreds of them on the first parse... every rule creates a parser object. Parsers can also more clumsily be composed through module inclusion, see ip_address.rb in the examples directory. Generally speaking, I would go with the pattern that you cite first and not worry too much. If you hit a bottleneck, post the code here and we'll try to find the problem. Elegant and readable should be good as well with parslet. best regards, kaspar
