Skip to content

Instantly share code, notes, and snippets.

@jsl
Last active August 29, 2015 13:56
Show Gist options
  • Save jsl/8985707 to your computer and use it in GitHub Desktop.
Save jsl/8985707 to your computer and use it in GitHub Desktop.
Dictionary Replacer
require 'minitest/autorun'
require 'stringio'
class DictionaryReplacer
MARK = '$'
ESCAPE = '\\'
def initialize(to_replace, dictionary)
@to_replace = StringIO.new(to_replace)
@dictionary = dictionary
end
def translate
result = ''
key = ''
in_match = false
escaping = false
while c = @to_replace.getc
if c == ESCAPE
escaping = true
result += c
elsif escaping
result += c
escaping = false
elsif c == MARK
in_match = !in_match
if in_match
key = ''
else
if translation = @dictionary[key.to_sym]
result += translation
else
raise SyntaxError
end
end
else
if in_match
key += c
else
result += c
end
end
end
raise SyntaxError if in_match
result
end
end
describe "dictionary replacement" do
describe "converting strings" do
it "converts matching strings" do
DictionaryReplacer.new('foo $bar$', {bar: 'baz'}).translate.
must_equal 'foo baz'
end
it "doesn't consider escaped MARKs as tokens" do
DictionaryReplacer.new('foo\$ $bar$', {bar: 'baz'}).translate.
must_equal 'foo\$ baz'
end
it "converts strings with two substitutions" do
DictionaryReplacer.new('foo $bar$ what $fizz$',
{bar: 'baz', fizz: 'faz'}).translate.
must_equal 'foo baz what faz'
end
it "raises a SyntaxError when the token is not found in the dictionary" do
-> { DictionaryReplacer.new('$foo$',{ }).translate }.
must_raise SyntaxError
end
it "raises an error if the input string is invalid" do
-> { DictionaryReplacer.new('$foo$ $', {foo: 'bar'}).translate }.
must_raise(SyntaxError)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment