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 { |token_type|
      s.match?(token_type.regex)
    }

    token =
        if current_match.nil?
          # No regex matches here. Find the earliest match.
          next_match_indexes = @token_types.map { |token_type|
            next_match = s.check_until(token_type.regex)
            if next_match.nil?
              nil
            else
              next_match.length - s.matched.length
            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

    self.parse_scanner(s) << token
  end
end