From 24a4cfe521c64739ee26b75873e9fe9aa5fd36ef Mon Sep 17 00:00:00 2001 From: Jorge Luis Martinez Gomez Date: Tue, 15 Sep 2020 00:39:07 -0700 Subject: [PATCH] add section on defining parsers as modules --- README.md | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/README.md b/README.md index 2424ec0..7abb4ab 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,69 @@ between(lit("<"), lit(">"), lit("foo")).label.to_s => "" ``` +## Defining parsers as modules + +The typical pattern I use is something like this: + +```ruby +module FoobarParser + include Parsby::Combinators + extend self + + # Entrypoint for reader to know where to start looking + def parse(s) + foobar.parse s + end + + define_combinator :foobar do + foo + bar + end + + define_combinator :foo do + lit("foo") + end + + define_combinator :bar do + lit("bar") + end +end +``` + +From that, you can use it directly as: + +```ruby +FoobarParser.parse "foobar" +FoobarParser.foo.parse "foo" +``` + +Being able to use subparsers directly is useful for when you want to e.g. +parse JSON array, instead of any JSON value. + +Writing the parser as a module like that also makes it easy to make a new +parser based on it: + +```ruby +module FoobarbazParser + include FoobarParser + extend self + + def parse(s) + foobarbaz.parse s + end + + define_combinator :foobarbaz do + foobar + baz + end + + define_combinator :baz do + lit("baz") + end +end +``` + +You can also define such a module to hold your own project's combinators to +use in multiple parsers. + ## `ExpectationFailed` Here's an example of an error, when parsing fails: