module Combinators
Combinators
allow us to “combine” parsers together. For example: run this parser first, if it fails, run this other one
run this parser first, and then run this other parser
Public Instance Methods
!=(other)
click to toggle source
other needs to fail for this to succeed; other is only peeking, not consuming
# File lib/combinators.rb, line 164 def !=(other) Parser.new do |input| second = other.run(input) if second.ok? ParserResult.fail(input) else run(input) end end end
*(other)
click to toggle source
Match other, this is QUIETLY consumed
# File lib/combinators.rb, line 143 def *(other) Parser.new do |input| first = run(input) matched = "" if first.ok? matched += first.matched second = other.run(first.remaining) if second.ok? matched += second.matched ParserResult.ok(second.output, matched: matched, remaining: second.remaining) else ParserResult.fail(input) end else first end end end
/(other)
click to toggle source
Match this, other is QUIETLY consumed
# File lib/combinators.rb, line 123 def /(other) Parser.new do |input| first = run(input) matched = "" if first.ok? matched = matched + first.matched second = other.run(first.remaining) if second.ok? matched = matched + second.matched ParserResult.ok(first.output, matched: matched, remaining: second.remaining) else ParserResult.fail(input) end else first end end end
<(other)
click to toggle source
Match other, this is optional
# File lib/combinators.rb, line 70 def <(other) Parser.new do |input| first = run(input) matched = "" output = [] remaining = input if first.ok? matched = first.matched output += first.output remaining = first.remaining end second = other.run(remaining) if second.ok? matched = matched + second.matched output = [*output, second.output] ParserResult.ok(output, matched: matched, remaining: second.remaining) else ParserResult.fail(input) end end end
<=(other)
click to toggle source
Match other, this is ignored but consumed
# File lib/combinators.rb, line 112 def <=(other) Parser.new do |input| first = run(input) remaining = input remaining = first.remaining if first.ok? second = other.run(remaining) second.ok? ? second : ParserResult.fail(input) end end
>(other)
click to toggle source
Match this, other is optional
# File lib/combinators.rb, line 47 def >(other) Parser.new do |input| first = run(input) matched = "" output = [] if first.ok? matched = first.matched output += first.output second = other.run(first.remaining) if second.ok? matched = matched + second.matched output = [*output, second.output] ParserResult.ok(output, matched: matched, remaining: second.remaining) else first end else ParserResult.fail(input) end end end
>=(other)
click to toggle source
Match this, other is ignored but consumed
# File lib/combinators.rb, line 95 def >=(other) Parser.new do |input| first = run(input) if first.ok? second = other.run(first.remaining) if second.ok? ParserResult.ok(first.output, matched: first.matched, remaining: second.remaining) else first end else ParserResult.fail(input) end end end
>>(other)
click to toggle source
Logical AND. Usage:
myParser >> otherParser
# File lib/combinators.rb, line 24 def >>(other) Parser.new do |input| first = run(input) matched = "" output = [] if first.ok? matched = matched + first.matched output += first.output second = other.run(first.remaining) if second.ok? matched = matched + second.matched output = [*output, second.output] ParserResult.ok(output, matched: matched, remaining: second.remaining) else ParserResult.fail(input) end else first end end end
|(other)
click to toggle source
Logical OR. Usage:
myParser | otherParser
# File lib/combinators.rb, line 9 def |(other) Parser.new do |input| first = run(input) if first.ok? first else other.run(input) end end end