class PuppetLint::Lexer::StringSlurper
Document this TODO
Constants
- END_INTERP_PATTERN
- END_STRING_PATTERN
- ESC_DQUOTE_PATTERN
- LBRACE_PATTERN
- START_INTERP_PATTERN
- UNENC_VAR_PATTERN
Attributes
interp_stack[RW]
results[RW]
scanner[RW]
Public Class Methods
new(string)
click to toggle source
# File lib/puppet-lint/lexer/string_slurper.rb, line 21 def initialize(string) @scanner = StringScanner.new(string) @results = [] @interp_stack = [] @segment = [] end
Public Instance Methods
consumed_chars()
click to toggle source
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
# File lib/puppet-lint/lexer/string_slurper.rb, line 110 def consumed_chars return scanner.charpos if scanner.respond_to?(:charpos) (scanner.pre_match + scanner.matched).scan(%r{.}mu).length end
end_heredoc(pattern)
click to toggle source
# File lib/puppet-lint/lexer/string_slurper.rb, line 158 def end_heredoc(pattern) results << [:HEREDOC, @segment.join] results << [:HEREDOC_TERM, scanner.scan(pattern)] end
end_interp()
click to toggle source
# File lib/puppet-lint/lexer/string_slurper.rb, line 133 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
end_string()
click to toggle source
# File lib/puppet-lint/lexer/string_slurper.rb, line 163 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
parse()
click to toggle source
# File lib/puppet-lint/lexer/string_slurper.rb, line 28 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
parse_heredoc(heredoc_tag)
click to toggle source
# File lib/puppet-lint/lexer/string_slurper.rb, line 61 def parse_heredoc(heredoc_tag) heredoc_name = heredoc_tag[%r{\A"?(.+?)"?(:.+?)?#{PuppetLint::Lexer::WHITESPACE_RE}*(/.*)?\Z}, 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
read_char()
click to toggle source
# File lib/puppet-lint/lexer/string_slurper.rb, line 88 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
start_interp()
click to toggle source
# File lib/puppet-lint/lexer/string_slurper.rb, line 116 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
unenclosed_variable()
click to toggle source
# File lib/puppet-lint/lexer/string_slurper.rb, line 150 def unenclosed_variable read_char if scanner.match?(%r{.\$}) results << [@segment_type, @segment.join] results << [:UNENC_VAR, scanner.scan(UNENC_VAR_PATTERN)] @segment = [] end
unenclosed_variable?()
click to toggle source
# File lib/puppet-lint/lexer/string_slurper.rb, line 55 def unenclosed_variable? interp_stack.empty? && scanner.match?(UNENC_VAR_PATTERN) && (@segment.last.nil? ? true : !@segment.last.end_with?('\\')) end