Class: Hiera::Backend::Eyaml::Parser::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/hiera/backend/eyaml/parser/parser.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(token_types) ⇒ Parser

Returns a new instance of Parser.



31
32
33
# File 'lib/hiera/backend/eyaml/parser/parser.rb', line 31

def initialize(token_types)
  @token_types = token_types
end

Instance Attribute Details

#token_typesObject (readonly)

Returns the value of attribute token_types.



29
30
31
# File 'lib/hiera/backend/eyaml/parser/parser.rb', line 29

def token_types
  @token_types
end

Instance Method Details

#parse(text) ⇒ Object



35
36
37
# File 'lib/hiera/backend/eyaml/parser/parser.rb', line 35

def parse(text)
  parse_scanner(StringScanner.new(text)).reverse
end

#parse_scanner(s) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/hiera/backend/eyaml/parser/parser.rb', line 39

def parse_scanner(s)
  if s.eos?
    []
  else
    # Check if the scanner currently matches a regex
    current_match = @token_types.find do |token_type|
      s.match?(token_type.regex)
    end

    token =
      if current_match.nil?
        # No regex matches here. Find the earliest match.
        next_match_indexes = @token_types.map do |token_type|
          next_match = s.check_until(token_type.regex)
          if next_match.nil?
            nil
          else
            next_match.length - s.matched.length
          end
        end.reject { |i| i.nil? }
        non_match_size =
          if next_match_indexes.length == 0
            s.rest_size
          else
            next_match_indexes.min
          end
        non_match = s.peek(non_match_size)
        # advance scanner
        s.pos = s.pos + non_match_size
        NonMatchToken.new(non_match)
      else
        # A regex matches so create a token and do a recursive call with the advanced scanner
        current_match.create_token s.scan(current_match.regex)
      end

    parse_scanner(s) << token
  end
end