2018-01-19 05:48:08 -05:00
|
|
|
# Simple DSL implementation for Ripper code generation
|
|
|
|
#
|
|
|
|
# input: /*% ripper: stmts_add(stmts_new, void_stmt) %*/
|
|
|
|
# output: $$ = dispatch2(stmts_add, dispatch0(stmts_new), dispatch0(void_stmt))
|
|
|
|
|
|
|
|
class DSL
|
|
|
|
def initialize(code, options)
|
|
|
|
@events = {}
|
|
|
|
@error = options.include?("error")
|
|
|
|
@brace = options.include?("brace")
|
2018-01-19 10:43:42 -05:00
|
|
|
@final = options.include?("final")
|
2018-01-19 11:24:07 -05:00
|
|
|
@var_field_1 = options.include?("var_field_1")
|
2018-01-19 05:48:08 -05:00
|
|
|
|
|
|
|
# create $1 == "$1", $2 == "$2", ...
|
|
|
|
re, s = "", ""
|
|
|
|
1.upto(9) do |n|
|
|
|
|
re << "(..)"
|
|
|
|
s << "$#{ n }"
|
|
|
|
end
|
|
|
|
/#{ re }/ =~ s
|
|
|
|
|
|
|
|
@code = eval(code)
|
|
|
|
end
|
|
|
|
|
|
|
|
attr_reader :events
|
|
|
|
|
|
|
|
undef lambda
|
|
|
|
undef hash
|
|
|
|
undef class
|
|
|
|
|
|
|
|
def generate
|
|
|
|
s = "$$"
|
2018-01-19 10:43:42 -05:00
|
|
|
s = "p->result" if @final
|
2018-01-20 00:39:00 -05:00
|
|
|
s = "#{ s } = #@code;"
|
2018-01-19 05:48:08 -05:00
|
|
|
s << "ripper_error(p);" if @error
|
|
|
|
s = "{#{ s }}" if @brace
|
2018-01-19 11:24:07 -05:00
|
|
|
s = "$1 = var_field(p, $1);" + s if @var_field_1
|
2018-01-20 00:39:00 -05:00
|
|
|
"\t\t\t#{s}"
|
2018-01-19 05:48:08 -05:00
|
|
|
end
|
|
|
|
|
2018-01-19 10:22:36 -05:00
|
|
|
def method_missing(event, *args)
|
|
|
|
if event.to_s =~ /!\z/
|
|
|
|
event = $`
|
|
|
|
@events[event] = args.size
|
|
|
|
"dispatch#{ args.size }(#{ [event, *args].join(", ") })"
|
2018-01-20 00:39:02 -05:00
|
|
|
elsif args.empty? and /\Aid[A-Z]/ =~ event.to_s
|
|
|
|
event
|
2018-01-19 05:48:08 -05:00
|
|
|
else
|
2018-01-19 10:22:36 -05:00
|
|
|
"#{ event }(#{ args.join(", ") })"
|
2018-01-19 05:48:08 -05:00
|
|
|
end
|
|
|
|
end
|
2018-01-20 00:39:01 -05:00
|
|
|
|
|
|
|
def self.const_missing(name)
|
|
|
|
name
|
|
|
|
end
|
2018-01-19 05:48:08 -05:00
|
|
|
end
|
|
|
|
|