module BaseParsers
Public Instance Methods
anyChar(chars)
click to toggle source
# File lib/base_parsers.rb, line 151 def anyChar(chars) Parser.new do |input| first_char = input[0] result = ParserResult.fail(input) chars.each do |char| if first_char == char result = ParserResult.ok(matched: char, remaining: input[1..-1]) break end end result end end
anyCharBut(chars)
click to toggle source
# File lib/base_parsers.rb, line 167 def anyCharBut(chars) Parser.new do |input| first_char = input[0] result = ParserResult.ok(matched: first_char, remaining: input[1..-1]) if !(input == "" || input.nil?) chars.each do |char| if first_char == char result = ParserResult.fail(input) break end end else result = ParserResult.fail(input) end result end end
anyLetter()
click to toggle source
# File lib/base_parsers.rb, line 44 def anyLetter anyChar(('a'..'z').to_a + ('A'..'Z').to_a) end
anyNumber()
click to toggle source
# File lib/base_parsers.rb, line 48 def anyNumber anyChar ('0'..'9').to_a end
empty()
click to toggle source
# File lib/base_parsers.rb, line 14 def empty Parser.new do |input| ParserResult.ok(matched: "", remaining: input) end end
eof()
click to toggle source
# File lib/base_parsers.rb, line 4 def eof Parser.new do |input| if input == "" || input.nil? ParserResult.ok(matched: "", remaining: input) else ParserResult.fail(input) end end end
exactly(n, &wrapper)
click to toggle source
# File lib/base_parsers.rb, line 187 def exactly(n, &wrapper) parser = wrapper.call Parser.new do |input| matched = "" remaining = input success = true n.to_i.times do result = parser.run(remaining) if result.fail? success = false break end matched = matched + result.matched remaining = result.remaining end if success ParserResult.ok(matched: matched, remaining: remaining) else ParserResult.fail(input) end end end
many0(&wrapper)
click to toggle source
# File lib/base_parsers.rb, line 74 def many0(&wrapper) Parser.new do |input| if input.nil? || input == "" ParserResult.ok(matched: "", remaining: input) else many1(&wrapper).run(input) end end end
many1(&wrapper)
click to toggle source
# File lib/base_parsers.rb, line 52 def many1(&wrapper) Parser.new do |input| matched = "" output = [] remaining = input parser = wrapper.call loop do result = parser.run(remaining) break if remaining.nil? || result.fail? matched = matched + result.matched output += result.output unless (result.output.length == 1 and result.output[0].length == 1) remaining = result.remaining end #puts "output: " + output.to_s unless output.empty? output = nil if output.empty? ParserResult.new(!matched.empty?, remaining, matched, output) end end
match(rule, between:)
click to toggle source
# File lib/base_parsers.rb, line 129 def match(rule, between:) first, last = between Parser.new do |input| lhs = first.run(input) if lhs.ok? middle = rule.run(lhs.remaining) if middle.ok? rhs = last.run(middle.remaining) if rhs.ok? rhs else ParserResult.fail(input) end else ParserResult.fail(input) end else ParserResult.fail(input) end end end
one(char)
click to toggle source
# File lib/base_parsers.rb, line 24 def one(char) Parser.new do |input| if input[0] == char ParserResult.ok(matched: char, remaining: input[1..-1]) else ParserResult.fail(input) end end end
regex(re)
click to toggle source
# File lib/base_parsers.rb, line 123 def regex(re) Parser.new do |input| test regex: re, with: input end end
satisfy(&wrapper)
click to toggle source
This is just an alias of lambda in the DSL. See specs for more on this.
# File lib/base_parsers.rb, line 117 def satisfy(&wrapper) Parser.new do |input| wrapper.call(input) end end
seq(*args)
click to toggle source
# File lib/base_parsers.rb, line 84 def seq(*args) callback = args[-1] parsers = args[0..(args.length - 2)] raise "Seq expects at least a parser and a callback." if callback.nil? || parsers.empty? Parser.new do |input| remaining = input matched = "" fail = nil new_args = parsers.map do |parser| result = parser.run(remaining) unless result.ok? fail = ParserResult.fail(input) break end remaining = result.remaining matched += result.matched result.output end if fail.nil? output = callback.call(*new_args) ParserResult.ok(output, matched: matched, remaining: remaining) else fail end end end
str(string)
click to toggle source
# File lib/base_parsers.rb, line 34 def str(string) Parser.new do |input| if input.start_with?(string) ParserResult.ok(matched: string, remaining: input[string.length..-1]) else ParserResult.fail(input) end end end
whitespace()
click to toggle source
# File lib/base_parsers.rb, line 20 def whitespace many0 { anyChar([" ", "\b", "\f", "\n", "\r", "\t"]) } end
Private Instance Methods
test(regex:, with:)
click to toggle source
Test against a simple regex, no groups. It would be possible to pass a callback to the regex, in order to work with groups. #MAYBE #TODO
# File lib/base_parsers.rb, line 216 def test(regex:, with:) match = regex.match(with) return ParserResult.fail(with) if match.nil? matched = match[0] ParserResult.ok(matched: matched, remaining: with[matched.length..-1]) end