DSLs are designed to solve a particular kind of problem. Implementation DSLs as internal DSLs in Ruby is getting popular. Jim Freeze in his article
Creating DSLs with Ruby use "Interpret" pattern to implement DSL. According the article a problem will be solved by using instance of a Class Machine. The Machine has class method load that create an instance of the Class Machine and load a file containing machine's instructions writen in DSL. The Machine also has instance method process, that run loaded instructions with specified data. A Ruby implementation can be as follow
class Machine
def self.load(filename)
machine = Machine.new
machine.instance_eval(File.read(filename),
filename)
machine
end
def process(*arg)
#...
end
end
Using this pattern, in
The ruby implementation of an example in Martin Fowler's Language Workbenches article the Reader class can be modified as follows
class Reader
#...
def self.load dsl_file_name
reader = Reader.new
reader.instance_eval(File.read(dsl_file_name),
dsl_file_name)
reader
end
def process data_file_name
File.open(data_file_name,'r') do |file|
while line = file.gets
process_line line
end
end
end
#...
def mapping type_code, type, &block
@strategies[type_code] =
ReaderStrategy.new type_code, type, &block
end
end
#dsl.txt
mapping('SVCL', ServiceCall) do
extract 4..18, 'customer_name'
extract 19..23, 'customer_ID'
extract 24..27, 'call_type_code'
extract 28..35, 'date_of_call_string'
end
mapping('USGE', Usage) do
extract 9..22, 'customer_name'
extract 4..8, 'customer_ID'
extract 30..30, 'cycle'
extract 31..36, 'read_date'
end
#load_dsl.rb
require 'test/unit'
require File.join(File.dirname(__FILE__),
'..', 'lib', 'data')
require File.join(File.dirname(__FILE__),
'..', 'lib', 'data_reader')
require File.join(File.dirname(__FILE__),
'..', 'lib', 'data_reader_strategy')
class TestLoadDsl < Test::Unit::TestCase
def test_read_file_load_dsl
dsl_file_name = File.join(File.dirname(__FILE__),
'dsl.txt')
reader = Reader.load dsl_file_name
data_file_name = File.join(File.dirname(__FILE__),
'sample.txt')
reader.process data_file_name
assert_equal 4, reader.result.size
end
end
No comments:
Post a Comment