# Martin Fowler's Reader Framework example from his "Language Workbenches"
# and "Generating Code for DSLs" papers.  
# H. Conrad Cunningham 
# Original:  9 October 2006
# Revision: 10 October 2006

# INTERNAL DSL IN RUBY

require 'ReaderFramework'

# Class BuilderRubyDSL encapsulates a processor for a Ruby-based internal
# DSL with the following syntax and Ruby semantics:

# 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

class BuilderRubyDSL

  def initialize(filename)
    @rb_dsl_file = filename
  end

  def configure(reader)
    @reader = reader
    rb_file = File.new(@rb_dsl_file)
    instance_eval(rb_file.read, @rb_dsl_file) # load and evaluate in context
    rb_file.close                             #  of this object
  end            

  def mapping(code,target)
    @cur_mapping = ReaderFramework::ReaderStrategy.new(code,target)
    @reader.add_strategy(@cur_mapping)
    yield  # calls body of mapping's block in the DSL
  end
    
  def extract(range,field_name)
    begin_col = range.begin
    end_col = range.end
    end_col -= 1 if range.exclude_end? 
    @cur_mapping.add_field_extractor(begin_col,end_col,field_name)
  end

end#BuilderRubyDSL


# Classes used to hold the data read

class ServiceCall
end#ServiceCall

class Usage
end#Usage


# TESTING THE RUBY DSL

class TestRubyDSL

  def TestRubyDSL.run
    puts "\nTesting Ruby DSL."
    rdr = ReaderFramework::Reader.new
    cfg = BuilderRubyDSL.new("dslinput.rb")
    cfg.configure(rdr)
    inp = File.new("fowlerdata.txt")
    res = rdr.process(inp)
    inp.close
    res.each {|o| puts o.inspect}
  end

end#TestRubyDSL
