class Haml::AttributeParser
def self.available?
-
(TrueClass, FalseClass)
- - return true if AttributeParser.parse can be used.
def self.available? # TruffleRuby doesn't have Ripper.lex defined?(Ripper) && Ripper.respond_to?(:lex) && Temple::StaticAnalyzer.available? end
def self.parse(text)
def self.parse(text) self.new.parse(text) end
def assert_type!(token, type)
def assert_type!(token, type) raise ParseSkip if token[1] != type end
def each_attr(tokens)
def each_attr(tokens) attr_tokens = [] open_tokens = Hash.new { |h, k| h[k] = 0 } tokens.each do |token| _, type, _ = token case type when :on_comma if open_tokens.values.all?(&:zero?) yield(attr_tokens) attr_tokens = [] next end when :on_lbracket open_tokens[:array] += 1 when :on_rbracket open_tokens[:array] -= 1 when :on_lbrace open_tokens[:block] += 1 when :on_rbrace open_tokens[:block] -= 1 when :on_lparen open_tokens[:paren] += 1 when :on_rparen open_tokens[:paren] -= 1 when :on_embexpr_beg open_tokens[:embexpr] += 1 when :on_embexpr_end open_tokens[:embexpr] -= 1 when :on_sp next if attr_tokens.empty? end attr_tokens << token end yield(attr_tokens) unless attr_tokens.empty? end
def parse(text)
def parse(text) exp = wrap_bracket(text) return if Temple::StaticAnalyzer.syntax_error?(exp) hash = {} tokens = Ripper.lex(exp)[1..-2] || [] each_attr(tokens) do |attr_tokens| key = parse_key!(attr_tokens) hash[key] = attr_tokens.map { |t| t[2] }.join.strip end hash rescue ParseSkip nil end
def parse_key!(tokens)
def parse_key!(tokens) _, type, str = tokens.shift case type when :on_sp parse_key!(tokens) when :on_label str.tr(':', '') when :on_symbeg _, _, key = tokens.shift assert_type!(tokens.shift, :on_tstring_end) if str != ':' skip_until_hash_rocket!(tokens) key when :on_tstring_beg _, _, key = tokens.shift next_token = tokens.shift unless next_token[1] == :on_label_end assert_type!(next_token, :on_tstring_end) skip_until_hash_rocket!(tokens) end key else raise ParseSkip end end
def skip_until_hash_rocket!(tokens)
def skip_until_hash_rocket!(tokens) until tokens.empty? _, type, str = tokens.shift break if type == :on_op && str == '=>' end end
def wrap_bracket(text)
def wrap_bracket(text) text = text.strip return text if text[0] == '{' "{#{text}}" end