Created
September 25, 2012 13:20
-
-
Save clicube/3781776 to your computer and use it in GitHub Desktop.
DSL generator for ruby
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class DSLObject < BasicObject | |
include ::Kernel | |
end | |
class DSLContext | |
attr_reader :params | |
def initialize &block | |
@params = {} | |
@obj = DSLObject.new | |
@obj_class = class << @obj; self end; | |
instance_eval &block if block | |
end | |
def define_method name, &block | |
@obj_class.class_eval do | |
define_method name, &block | |
end | |
end | |
def define_param name | |
param_proc = proc do |val| | |
if !val || val.length == 0 | |
@params[name] | |
elsif val.length == 1 | |
@params[name] = val[0] | |
else | |
@params[name] = val | |
end | |
end | |
@obj_class.class_eval do | |
define_method name do |*args| | |
param_proc.call args | |
end | |
end | |
end | |
def define_context name, &block | |
param_proc = proc do |args, &block2| | |
c = DSLContext.new | |
class << c | |
def define_pre_method &block | |
@pre_method_proc = block | |
end | |
def pre_method | |
@pre_method_proc.call @params if @pre_method_proc | |
end | |
def define_post_method &block | |
@post_method_proc = block | |
end | |
def post_method | |
@post_method_proc.call @params if @post_method_proc | |
end | |
end | |
c.instance_eval &block | |
c.pre_method | |
c.eval &block2 | |
c.post_method | |
@params[name] ||= [] | |
if !args || args.length == 0 | |
@params[name] << c.params | |
elsif args.length == 1 | |
@params[name] << [args[0], c.params] | |
else | |
@params[name] << [args, c.params] | |
end | |
end | |
@obj_class.class_eval do | |
define_method name do |*args, &block| | |
param_proc.call *args, &block | |
end | |
end | |
end | |
def eval *args, &block | |
if block | |
@obj.instance_eval &block | |
else | |
@obj.instance_eval args[0] | |
end | |
end | |
end | |
if __FILE__ == $0 | |
dsl = DSLContext.new do | |
define_param "simple_param" | |
define_context "multi_param" do | |
define_param "mp_1" | |
define_param "mp_2" | |
define_post_method do |params| | |
puts "(post_method) params: #{params}" | |
end | |
end | |
define_method "say" do |val| | |
puts "#{val}!! "*10 | |
end | |
end | |
str = <<-EOS | |
simple_param "nyan" | |
multi_param { | |
mp_1 "nyan1" | |
mp_2 "nyan2" | |
} | |
multi_param { | |
mp_1 "wan1" | |
mp_2 "wan2" | |
} | |
say "nyan" | |
EOS | |
dsl.eval str | |
puts "========" | |
puts "params:" | |
p dsl.params | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'stringio' | |
require_relative 'dsl' | |
if __FILE__ == $0 | |
html = StringIO.new | |
dsl = DSLContext.new do | |
define_context "html" do | |
define_pre_method { html.puts "<html>" } | |
define_post_method { html.puts "</html>" } | |
define_context "head" do | |
define_param "charset" | |
define_param "title" | |
define_context "css" do | |
define_param "href" | |
define_param "media" | |
end | |
define_context "script" do | |
define_param "src" | |
end | |
define_post_method do |param| | |
html.puts "<head>" | |
html.puts "<meta charset=\"#{param['charset']}\" />" | |
html.puts "<title>#{param['title']}</title>" | |
param['css'].each do |css| | |
html.puts "<link href=\"#{css['href']}\" rel=\"stylesheet\" media=\"#{css['media']}\" />" | |
end | |
param['script'].each do |script| | |
html.puts "<script type=\"text/javascript\" src=\"#{script['src']}\"></script>" | |
end | |
html.puts "</head>" | |
end | |
end | |
define_context "body" do | |
define_pre_method { html.puts "<body>" } | |
define_post_method { html.puts "</body>" } | |
%w[h1 h2 h3 h4 h5 p a pre div].each do |tag| | |
define_method tag do |*args, &block| | |
if args.length>0 | |
attr = "" | |
if args.length > 1 | |
args[1].each do |key,val| | |
attr << " #{key}=\"#{val}\"" | |
end | |
end | |
html.puts "<#{tag}#{attr}>#{args[0]}</#{tag}>" | |
elsif block | |
html.puts "<#{tag}>" | |
block.call | |
html.puts "</#{tag}>" | |
end | |
end | |
end | |
end | |
end | |
define_method "output" do | |
puts html.string | |
end | |
end | |
dsl_str = <<-EOS | |
html{ | |
head{ | |
charset "utf-8" | |
title "page title" | |
css{ | |
href "screen.css" | |
media "screen" | |
} | |
css{ | |
href "print.css" | |
media "print" | |
} | |
script{ | |
src "jquery.js" | |
} | |
script{ | |
src "some_script.js" | |
} | |
} | |
body{ | |
h1 "h1 title" | |
div{ | |
p "nyan nyan nyan" | |
p "wan wan wan" | |
} | |
a "hyper link text", "href"=>"http://nyan.cat/" | |
} | |
} | |
output | |
EOS | |
dsl.eval dsl_str | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment