Class: Parsby
- Inherits:
-
Object
- Object
- Parsby
- Includes:
- Combinators
- Defined in:
- lib/parsby.rb,
lib/parsby/version.rb,
lib/parsby/combinators.rb
Defined Under Namespace
Modules: Combinators, Example, Tree Classes: BackedIO, Backup, Context, Error, ExpectationFailed, ParsedRange, PosRange, Splicer
Constant Summary collapse
- VERSION =
"1.1.1"
Instance Attribute Summary collapse
-
#label ⇒ Object
The parser’s label.
Instance Method Summary collapse
-
#%(name) ⇒ Object
Set the label and return self.
-
#*(n) ⇒ Object
p * n, runs parser p n times, grouping results in an array.
-
#+(p) ⇒ Object
x + y does + on the results of x and y.
-
#<(p) ⇒ Object
x < y runs parser x then y and returns x.
-
#<<(p) ⇒ Object
xs << x appends result of parser x to list result of parser xs.
-
#>(p) ⇒ Object
x > y runs parser x then y and returns y.
-
#fmap(&b) ⇒ Object
Like map for arrays, this lets you work with the value “inside” the parser, i.e.
-
#initialize(label = nil, &b) ⇒ Parsby
constructor
Initialize parser with optional label argument, and parsing block.
-
#parse(src) ⇒ Object
Parse a String or IO object.
-
#peek(src) ⇒ Object
Parses without consuming input.
-
#that_fails(p) ⇒ Object
(also: #that_fail)
x.that_fails(y)
will tryy
, fail ify
succeeds, or parse withx
ify
fails. -
#then(&b) ⇒ Object
Pass result of self parser to block to construct the next parser.
-
#|(p) ⇒ Object
x | y
tries y if x fails. - #~ ⇒ Object
Methods included from Combinators
Methods included from Combinators::ModuleMethods
Constructor Details
#initialize(label = nil, &b) ⇒ Parsby
Initialize parser with optional label argument, and parsing block. The parsing block is given an IO as argument, and its result is the result when parsing.
606 607 608 609 |
# File 'lib/parsby.rb', line 606 def initialize(label = nil, &b) self.label = label if label @parser = b end |
Instance Attribute Details
#label ⇒ Object
The parser’s label. It’s an “unknown” token by default.
597 598 599 |
# File 'lib/parsby.rb', line 597 def label @label || "unknown" end |
Instance Method Details
#%(name) ⇒ Object
Set the label and return self.
709 710 711 712 |
# File 'lib/parsby.rb', line 709 def %(name) self.label = name self end |
#*(n) ⇒ Object
p * n, runs parser p n times, grouping results in an array.
684 685 686 687 688 |
# File 'lib/parsby.rb', line 684 def *(n) Parsby.new "(#{label} * #{n})" do |c| n.times.map { parse c } end end |
#+(p) ⇒ Object
x + y does + on the results of x and y. This is mostly meant to be used with arrays, but it would work with numbers and strings too.
692 693 694 695 696 |
# File 'lib/parsby.rb', line 692 def +(p) group(self, p) .fmap {|(x, y)| x + y } .tap {|r| r.label = "(#{label} + #{p.label})" } end |
#<(p) ⇒ Object
x < y runs parser x then y and returns x.
659 660 661 662 663 |
# File 'lib/parsby.rb', line 659 def <(p) ~splicer.start do |m| m.end(self).then {|r| m.end(p).then { pure r } } end % "(#{label} < #{p.label})" end |
#<<(p) ⇒ Object
xs << x appends result of parser x to list result of parser xs.
699 700 701 702 703 704 705 706 |
# File 'lib/parsby.rb', line 699 def <<(p) Parsby.new "(#{label} << #{p.label})" do |c| x = parse c y = p.parse c # like x << y, but without modifying x. x + [y] end end |
#>(p) ⇒ Object
x > y runs parser x then y and returns y.
666 667 668 |
# File 'lib/parsby.rb', line 666 def >(p) self.then { p } % "(#{label} > #{p.label})" end |
#fmap(&b) ⇒ Object
Like map for arrays, this lets you work with the value “inside” the parser, i.e. the result.
Example:
decimal.fmap {|x| x + 1}.parse("2")
=> 3
721 722 723 724 725 |
# File 'lib/parsby.rb', line 721 def fmap(&b) Parsby.new "#{label}.fmap" do |c| b.call parse c end end |
#parse(src) ⇒ Object
Parse a String or IO object.
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 |
# File 'lib/parsby.rb', line 612 def parse(src) ctx = src.is_a?(Context) ? src : Context.new(src) parsed_range = ParsedRange.new(ctx.bio.pos, ctx.bio.pos, label) ctx.parsed_ranges << parsed_range if ctx.parsed_ranges parent_parsed_range = ctx.parsed_ranges ctx.parsed_ranges = parsed_range begin r = @parser.call ctx rescue ExpectationFailed => e ctx.parsed_ranges.end = ctx.bio.pos ctx.parsed_ranges.failed = true ctx.bio.restore_to ctx.parsed_ranges.start raise else ctx.parsed_ranges.end = ctx.bio.pos r ensure # Keep the root one for use in ExceptionFailed#message if parent_parsed_range ctx.parsed_ranges = parent_parsed_range end end end |
#peek(src) ⇒ Object
Parses without consuming input.
637 638 639 640 641 642 643 644 645 |
# File 'lib/parsby.rb', line 637 def peek(src) ctx = src.is_a?(Context) ? src : Context.new(src) starting_pos = ctx.bio.pos begin parse ctx ensure ctx.bio.restore_to starting_pos end end |
#that_fails(p) ⇒ Object Also known as: that_fail
x.that_fails(y)
will try y
, fail if y
succeeds, or parse with x
if y
fails.
Example:
decimal.that_fails(string("10")).parse "3"
=> 3
decimal.that_fails(string("10")).parse "10"
Parsby::ExpectationFailed: line 1:
10
\/ expected: (not "10")
762 763 764 765 766 767 768 769 770 771 772 773 774 |
# File 'lib/parsby.rb', line 762 def that_fails(p) Parsby.new "#{label}.that_fails(#{p.label})" do |c| orig_pos = c.bio.pos begin r = p.parse c.bio rescue Error c.bio.restore_to orig_pos parse c.bio else raise ExpectationFailed.new c end end end |
#then(&b) ⇒ Object
744 745 746 747 748 |
# File 'lib/parsby.rb', line 744 def then(&b) Parsby.new "#{label}.then" do |c| b.call(parse(c)).parse(c) end end |