class DSL
Simple DSL
implementation for Ripper
code generation
input: /*% ripper: stmts_add!(stmts_new!, void_stmt!) %*/ output:
VALUE v1, v2; v1 = dispatch0(stmts_new); v2 = dispatch0(void_stmt); $$ = dispatch2(stmts_add, v1, v2);
-
The code must be a single line.
-
The code is basically Ruby code, even if it appears like in C and the result will be processed as C. e.g., comments need to be in Ruby style.
Constants
- NAME_PATTERN
- NOT_REF_PATTERN
- TAG_PATTERN
Attributes
events[R]
Public Class Methods
comma_split(str)
click to toggle source
# File ripper/tools/dsl.rb, line 29 def self.comma_split(str) str or return [] str.scan(/(([^(,)]+|\((?:,|\g<0>)*\))+)/).map(&:first) end
const_missing(name)
click to toggle source
# File ripper/tools/dsl.rb, line 178 def self.const_missing(name) name end
line?(line, lineno = nil, indent: nil)
click to toggle source
# File ripper/tools/dsl.rb, line 23 def self.line?(line, lineno = nil, indent: nil) if %r<(?<space>\s*)/\*% *ripper(?:\[(?<option>.*?)\])?: *(?<code>.*?) *%\*/> =~ line new(code, comma_split(option), lineno, indent: indent || space) end end
new(code, options, lineno = nil, indent: "\t\t\t")
click to toggle source
# File ripper/tools/dsl.rb, line 108 def initialize(code, options, lineno = nil, indent: "\t\t\t") @lineno = lineno @indent = indent @events = {} @error = options.include?("error") if options.include?("final") @final = "p->result" else @final = (options.grep(/\A\$#{NAME_PATTERN}\z/o)[0] || "p->s_lvalue") end bind = dsl_binding @var_table = Var::Table.new {|arg| "get_value(#{arg})"} code = code.gsub(%r[\G#{NOT_REF_PATTERN}\K(\$|\$:|@)#{TAG_PATTERN}?#{NAME_PATTERN}]o) { if (arg = $&) == "$:$" '"p->s_lvalue"' elsif arg.start_with?("$:") "(#{@var_table[arg]}=@var_table[#{arg.dump}])" else arg.dump end } @last_value = bind.eval(code) rescue SyntaxError $stderr.puts "error on line #{@lineno}" if @lineno raise end
Public Instance Methods
add_event(event, args)
click to toggle source
# File ripper/tools/dsl.rb, line 157 def add_event(event, args) event = event.to_s.sub(/!\z/, "") @events[event] = args.size vars = [] args.each do |arg| arg = @var_table.add {arg} unless Var === arg vars << arg end @var_table.add {"dispatch#{ args.size }(#{ [event, *vars].join(",") })"} end
dsl_binding(p = "p")
click to toggle source
# File ripper/tools/dsl.rb, line 136 def dsl_binding(p = "p") # struct parser_params *p binding end
generate()
click to toggle source
# File ripper/tools/dsl.rb, line 147 def generate s = "#@final=#@last_value;" s << "ripper_error(p);" if @error unless @var_table.empty? vars = @var_table.map {|_, v| "#{v.var}=#{v.value}"}.join(", ") s = "VALUE #{ vars }; #{ s }" end "#{@indent}{#{s}}" end
method_missing(event, *args)
click to toggle source
# File ripper/tools/dsl.rb, line 168 def method_missing(event, *args) if event.to_s =~ /!\z/ add_event(event, args) elsif args.empty? and (/\Aid[A-Z_]/ =~ event or @var_table.defined?(event)) event else "#{ event }(#{ args.map(&:to_s).join(", ") })" end end
to_s()
click to toggle source
# File ripper/tools/dsl.rb, line 36 def to_s if empty? "rb_ary_new()" else "rb_ary_new_from_args(#{size}, #{map(&:to_s).join(', ')})" end end