Module: Parby

Defined in:
lib/parby/parser.rb,
lib/parby/result.rb,
lib/parby/version.rb,
lib/parby/combinators.rb

Defined Under Namespace

Classes: Failure, Parser, Result, Success

Constant Summary collapse

VERSION =
"0.2.0"

Class Method Summary collapse

Class Method Details

.allObject



85
86
87
88
89
# File 'lib/parby/combinators.rb', line 85

def self.all
  Parser.new do |input, index|
    Success.new(index, input, nil)
  end
end

.none_of(characters) ⇒ Object



55
56
57
# File 'lib/parby/combinators.rb', line 55

def self.none_of(characters)
  test(Proc.new { |c| !characters.include?(c) }, ["None of #{characters}"])
end

.of(value) ⇒ Object

Always yields the value passed to it, no matter the input



5
6
7
# File 'lib/parby/combinators.rb', line 5

def self.of(value)
  Parser.new { |input, index| Success.new(index, value, input) }
end

.one_of(characters) ⇒ Object

Searches in the input for one of the given characters (characters can be either a string or an array), and yields it



50
51
52
53
# File 'lib/parby/combinators.rb', line 50

def self.one_of(characters)
  expected = if characters.is_a?(Array) then characters else characters.split('') end
  test(Proc.new { |c| expected.include?(c) }, expected)
end

.regex(regex) ⇒ Object



45
46
47
# File 'lib/parby/combinators.rb', line 45

def self.regex(regex)
  return self.regexp(regex)
end

.regexp(regex) ⇒ Object

Yields the input, if it matches the regex passed to it



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/parby/combinators.rb', line 29

def self.regexp(regex)
  # We have to match from the beginning
  real_regex = /^#{regex}/

  Parser.new do |input, index|
    match_data = real_regex.match(input)

    if match_data.nil?
      # We did not even match one letter
      Failure.new(index, [regex], input)
    else
      Success.new(index, match_data[0], input)
    end
  end
end

.string(str) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/parby/combinators.rb', line 59

def self.string(str)
  Parser.new do |input, index|
    furthest = -1

    str.split('').each_with_index do |expected_character, expected_index|
      actual_character = input[expected_index]

      if actual_character.nil?
        # This means that the input is smaller than the expected string
        furthest = expected_index - 1
        break
      elsif actual_character != expected_character
        # This means the input does not match exactly the string
        furthest = expected_index
        break
      end
    end

    if furthest == -1
      Success.new(index, str)
    else
      Failure.new(furthest, [str])
    end
  end
end

.test(predicate, description = nil) ⇒ Object

Yields the first character that matches predicate, it fails with the given message, otherwise a generic one



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/parby/combinators.rb', line 10

def self.test(predicate, description = nil)
  Parser.new do |input, index|
    found = nil
    input.split('').each do |character|
      if predicate.call(character)
        found = character
        break
      end
    end

    if found
      Success.new(index, found, input)
    else
      Failure.new(index, [description || 'Matching a predicate'], input)
    end
  end
end