Sha256: a02f264e7cde17596df9ae8b315025b37629bc01e6e5d7aac7da9524da6fa84b

Contents?: true

Size: 1.71 KB

Versions: 5

Compression:

Stored size: 1.71 KB

Contents

require 'ripper'

module Hamlit::StringInterpolation
  class << self
    # `code` param must be valid string literal
    def compile(code)
      [].tap do |exps|
        tokens = Ripper.lex(code.strip)
        tokens.pop while tokens.last && %i[on_comment on_sp].include?(tokens.last[1])

        if tokens.size < 2
          raise Hamlit::InternalError.new("Expected token size >= 2 but got: #{tokens.size}")
        end
        compile_tokens!(exps, tokens)
      end
    end

    private

    def strip_quotes!(tokens)
      _, type, beg_str = tokens.shift
      if type != :on_tstring_beg
        raise Hamlit::InternalError.new("Expected :on_tstring_beg but got: #{type}")
      end

      _, type, end_str = tokens.pop
      if type != :on_tstring_end
        raise Hamlit::InternalError.new("Expected :on_tstring_end but got: #{type}")
      end

      [beg_str, end_str]
    end

    def compile_tokens!(exps, tokens)
      beg_str, end_str = strip_quotes!(tokens)

      until tokens.empty?
        _, type, str = tokens.shift

        case type
        when :on_tstring_content
          exps << [:static, eval("#{beg_str}#{str}#{end_str}")]
        when :on_embexpr_beg
          embedded = shift_balanced_embexpr(tokens)
          exps << [:dynamic, embedded] unless embedded.empty?
        end
      end
    end

    def shift_balanced_embexpr(tokens)
      String.new.tap do |embedded|
        embexpr_open = 1

        until tokens.empty?
          _, type, str = tokens.shift
          case type
          when :on_embexpr_beg
            embexpr_open += 1
          when :on_embexpr_end
            embexpr_open -= 1
            break if embexpr_open == 0
          end

          embedded << str
        end
      end
    end
  end
end

Version data entries

5 entries across 5 versions & 1 rubygems

Version Path
hamlit-2.1.2 lib/hamlit/string_interpolation.rb
hamlit-2.1.1 lib/hamlit/string_interpolation.rb
hamlit-2.1.0 lib/hamlit/string_interpolation.rb
hamlit-2.0.2 lib/hamlit/string_interpolation.rb
hamlit-2.0.1 lib/hamlit/string_interpolation.rb