Class: DSL
- Inherits:
- 
      Object
      
        - Object
- DSL
 
- Defined in:
- tools/dsl.rb
Overview
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. 
Defined Under Namespace
Classes: Var
Constant Summary collapse
- TAG_PATTERN =
- /(?><[a-zA-Z0-9_]+>)/.source 
- NAME_PATTERN =
- /(?>\$|\d+|[a-zA-Z_][a-zA-Z0-9_]*|\[[a-zA-Z_.][-a-zA-Z0-9_.]*\])(?>(?:\.|->)[a-zA-Z_][a-zA-Z0-9_]*)*/.source 
- NOT_REF_PATTERN =
- /(?>\#.*|[^\"$@]*|"(?>\\.|[^\"])*")/.source 
Instance Attribute Summary collapse
- 
  
    
      #events  ⇒ Object 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Returns the value of attribute events. 
Class Method Summary collapse
- .comma_split(str) ⇒ Object
- .const_missing(name) ⇒ Object
- .line?(line, lineno = nil, indent: nil) ⇒ Boolean
Instance Method Summary collapse
- #add_event(event, args) ⇒ Object
- #dsl_binding(p = "p") ⇒ Object
- #generate ⇒ Object
- 
  
    
      #initialize(code, options, lineno = nil, indent: "\t\t\t")  ⇒ DSL 
    
    
  
  
  
    constructor
  
  
  
  
  
  
  
    A new instance of DSL. 
- #method_missing(event, *args) ⇒ Object
Constructor Details
#initialize(code, options, lineno = nil, indent: "\t\t\t") ⇒ DSL
Returns a new instance of DSL.
| 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | # File 'tools/dsl.rb', line 108 def initialize(code, , lineno = nil, indent: "\t\t\t") @lineno = lineno @indent = indent @events = {} @error = .include?("error") if .include?("final") @final = "p->result" else @final = (.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 | 
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(event, *args) ⇒ Object
| 168 169 170 171 172 173 174 175 176 | # File '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 | 
Instance Attribute Details
#events ⇒ Object (readonly)
Returns the value of attribute events.
| 141 142 143 | # File 'tools/dsl.rb', line 141 def events @events end | 
Class Method Details
.comma_split(str) ⇒ Object
| 29 30 31 32 | # File 'tools/dsl.rb', line 29 def self.comma_split(str) str or return [] str.scan(/(([^(,)]+|\((?:,|\g<0>)*\))+)/).map(&:first) end | 
.const_missing(name) ⇒ Object
| 178 179 180 | # File 'tools/dsl.rb', line 178 def self.const_missing(name) name end | 
.line?(line, lineno = nil, indent: nil) ⇒ Boolean
| 23 24 25 26 27 | # File '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 | 
Instance Method Details
#add_event(event, args) ⇒ Object
| 157 158 159 160 161 162 163 164 165 166 | # File '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") ⇒ Object
| 136 137 138 139 | # File 'tools/dsl.rb', line 136 def dsl_binding(p = "p") # struct parser_params *p binding end | 
#generate ⇒ Object
| 147 148 149 150 151 152 153 154 155 | # File '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 |