mirror of
https://github.com/haml/haml.git
synced 2022-11-09 12:33:31 -05:00
Invent Hamlit::StringInterpolation.compile
This commit is contained in:
parent
9d4a065181
commit
b6c645260f
3 changed files with 102 additions and 0 deletions
|
@ -1,4 +1,5 @@
|
|||
require 'hamlit/static_analyzer'
|
||||
require 'hamlit/string_interpolation'
|
||||
|
||||
module Hamlit
|
||||
class Compiler
|
||||
|
|
60
lib/hamlit/string_interpolation.rb
Normal file
60
lib/hamlit/string_interpolation.rb
Normal file
|
@ -0,0 +1,60 @@
|
|||
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)
|
||||
|
||||
raise Hamlit::InternalError if tokens.size < 2
|
||||
strip_quotes!(tokens)
|
||||
|
||||
compile_tokens!(exps, tokens)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def strip_quotes!(tokens)
|
||||
_, type, _ = tokens.shift
|
||||
raise Hamlit::InternalError if type != :on_tstring_beg
|
||||
|
||||
_, type, _ = tokens.pop
|
||||
raise Hamlit::InternalError if type != :on_tstring_end
|
||||
end
|
||||
|
||||
def compile_tokens!(exps, tokens)
|
||||
until tokens.empty?
|
||||
_, type, str = tokens.shift
|
||||
|
||||
case type
|
||||
when :on_tstring_content
|
||||
exps << [:static, 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
|
41
test/hamlit/string_interpolation_test.rb
Normal file
41
test/hamlit/string_interpolation_test.rb
Normal file
|
@ -0,0 +1,41 @@
|
|||
describe Hamlit::StringInterpolation do
|
||||
describe '.compile' do
|
||||
def assert_compile(expected, code)
|
||||
actual = Hamlit::StringInterpolation.compile(code)
|
||||
assert_equal expected, actual
|
||||
end
|
||||
|
||||
it { assert_compile([], %q|''|) }
|
||||
it { assert_compile([], %q|""|) }
|
||||
it { assert_compile([[:static, 'hello']], %q|"hello"|) }
|
||||
it { assert_compile([[:static, 'hello '], [:static, 'world']], %q|"hello #{}world"|) }
|
||||
it { assert_compile([[:dynamic, 'hello']], %q|"#{hello}"|) }
|
||||
it { assert_compile([[:static, 'nya'], [:dynamic, '123']], %q|"nya#{123}"|) }
|
||||
it { assert_compile([[:dynamic, '()'], [:static, '()']], %q|"#{()}()"|) }
|
||||
it { assert_compile([[:static, ' '], [:dynamic, %q[ " #{ '#{}' } " ]]], %q|" #{ " #{ '#{}' } " }"|) }
|
||||
it { assert_compile([[:static, 'a'], [:dynamic, 'b'], [:static, 'c'], [:dynamic, 'd'], [:static, 'e']], %q|%Q[a#{b}c#{d}e]|) }
|
||||
it { assert_compile([[:static, 'a#{b}c#{d}e']], %q|%q[a#{b}c#{d}e]|) }
|
||||
it { assert_compile([[:static, '\#{}'], [:dynamic, '123']], %q|"\#{}#{123}"|) }
|
||||
it { assert_compile([[:dynamic, " '}' "]], %q|"#{ '}' }"|) }
|
||||
|
||||
describe 'invalid argument' do
|
||||
it 'raises internal error' do
|
||||
assert_raises Hamlit::InternalError do
|
||||
Hamlit::StringInterpolation.compile('1')
|
||||
end
|
||||
end
|
||||
|
||||
it 'raises internal error' do
|
||||
assert_raises Hamlit::InternalError do
|
||||
Hamlit::StringInterpolation.compile('[]')
|
||||
end
|
||||
end
|
||||
|
||||
it 'raises internal error' do
|
||||
assert_raises Hamlit::InternalError do
|
||||
Hamlit::StringInterpolation.compile('"]')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Reference in a new issue