class PuppetLint::Lexer::StringSlurper
Internal: A class for slurping strings from a Puppet manifest.
Constants
- END_INTERP_PATTERN
- END_STRING_PATTERN
- ESC_DQUOTE_PATTERN
- LBRACE_PATTERN
- START_INTERP_PATTERN
- UNENC_VAR_PATTERN
Attributes
Public Class Methods
Source
# File lib/puppet-lint/lexer/string_slurper.rb, line 16 def initialize(string) @scanner = StringScanner.new(string) @results = [] @interp_stack = [] @segment = [] end
Public Instance Methods
Source
# File lib/puppet-lint/lexer/string_slurper.rb, line 105 def consumed_chars return scanner.charpos if scanner.respond_to?(:charpos) (scanner.pre_match + scanner.matched).scan(%r{.}mu).length end
Get the number of characters consumed by the StringSlurper.
StringScanner from Ruby 2.0 onwards supports charpos which returns the number of characters and is multibyte character aware.
Prior to this, Ruby’s multibyte character support in Strings was a bit unusual and neither String#length nor String#split behave as expected, so we use String#scan to split all the consumed text using a UTF-8 aware regex and use the length of the result
Source
# File lib/puppet-lint/lexer/string_slurper.rb, line 153 def end_heredoc(pattern) results << [:HEREDOC, @segment.join] results << [:HEREDOC_TERM, scanner.scan(pattern)] end
Source
# File lib/puppet-lint/lexer/string_slurper.rb, line 128 def end_interp if interp_stack.empty? @segment << scanner.scan(END_INTERP_PATTERN) return else interp_stack.pop end if interp_stack.empty? results << [:INTERP, @segment.join] @segment = [] scanner.skip(END_INTERP_PATTERN) else @segment << scanner.scan(END_INTERP_PATTERN) end end
Source
# File lib/puppet-lint/lexer/string_slurper.rb, line 158 def end_string if interp_stack.empty? @segment << scanner.scan(END_STRING_PATTERN).gsub!(%r{"\Z}, '') results << [@segment_type, @segment.join] else @segment << scanner.scan(END_STRING_PATTERN) end end
Source
# File lib/puppet-lint/lexer/string_slurper.rb, line 23 def parse @segment_type = :STRING until scanner.eos? if scanner.match?(START_INTERP_PATTERN) start_interp elsif !interp_stack.empty? && scanner.match?(LBRACE_PATTERN) read_char elsif scanner.match?(END_INTERP_PATTERN) end_interp elsif unenclosed_variable? unenclosed_variable elsif scanner.match?(END_STRING_PATTERN) end_string break if interp_stack.empty? elsif scanner.match?(ESC_DQUOTE_PATTERN) @segment << scanner.scan(ESC_DQUOTE_PATTERN) else read_char end end raise UnterminatedStringError if results.empty? && scanner.matched? results end
Source
# File lib/puppet-lint/lexer/string_slurper.rb, line 56 def parse_heredoc(heredoc_tag) heredoc_name = heredoc_tag[%r{\A"?(.+?)"?(:.+?)?#{PuppetLint::Lexer::WHITESPACE_RE}*(/.*)?\Z}o, 1] end_heredoc_pattern = %r{^\|?\s*-?\s*#{Regexp.escape(heredoc_name)}$} interpolation = heredoc_tag.start_with?('"') @segment_type = :HEREDOC until scanner.eos? if scanner.match?(end_heredoc_pattern) end_heredoc(end_heredoc_pattern) break if interp_stack.empty? elsif interpolation && scanner.match?(START_INTERP_PATTERN) start_interp elsif interpolation && !interp_stack.empty? && scanner.match?(LBRACE_PATTERN) read_char elsif interpolation && unenclosed_variable? unenclosed_variable elsif interpolation && scanner.match?(END_INTERP_PATTERN) end_interp else read_char end end results end
Source
# File lib/puppet-lint/lexer/string_slurper.rb, line 83 def read_char @segment << scanner.getch return if interp_stack.empty? case @segment.last when '{' interp_stack.push(true) when '}' interp_stack.pop end end
Source
# File lib/puppet-lint/lexer/string_slurper.rb, line 111 def start_interp if @segment.last && @segment.last == '\\' read_char return end if interp_stack.empty? scanner.skip(START_INTERP_PATTERN) results << [@segment_type, @segment.join] @segment = [] else @segment << scanner.scan(START_INTERP_PATTERN) end interp_stack.push(true) end
Source
# File lib/puppet-lint/lexer/string_slurper.rb, line 145 def unenclosed_variable read_char if scanner.match?(%r{.\$}) results << [@segment_type, @segment.join] results << [:UNENC_VAR, scanner.scan(UNENC_VAR_PATTERN)] @segment = [] end
Source
# File lib/puppet-lint/lexer/string_slurper.rb, line 50 def unenclosed_variable? interp_stack.empty? && scanner.match?(UNENC_VAR_PATTERN) && (@segment.last.nil? ? true : !@segment.last.end_with?('\\')) end