class MinRubyParser

Public Class Methods

minruby_parse(program) click to toggle source
# File lib/minruby.rb, line 5
def self.minruby_parse(program)
  MinRubyParser.new.minruby_parse(program)
end

Public Instance Methods

make_stmts(exps) click to toggle source
# File lib/minruby.rb, line 158
def make_stmts(exps)
  exps = exps.map {|exp| simplify(exp) }
  exps.size == 1 ? exps[0] : ["stmts", *exps]
end
minruby_parse(program) click to toggle source
# File lib/minruby.rb, line 9
def minruby_parse(program)
  simplify(Ripper.sexp(program))
end
simplify(exp) click to toggle source
# File lib/minruby.rb, line 13
def simplify(exp)
  case exp[0]
  when :program, :bodystmt
    make_stmts(exp[1])
  when :def
    name = exp[1][1]
    params = exp[2]
    params = params[1] if params[0] == :paren
    params = (params[1] || []).map {|a| a[1] }
    body = simplify(exp[3])
    ["func_def", name, params, body]
  when :call
    recv = simplify(exp[1])
    name = exp[3][1]
    ["method_call", recv, name, []]
  when :fcall
    name = exp[1][1]
    ["func_call", name]
  when :method_add_arg
    call = simplify(exp[1])
    e = exp[2]
    e = e[1] || [] if e[0] == :arg_paren
    e = e[1] || [] if e[0] == :args_add_block
    e = e.map {|e_| simplify(e_) }
    call[(call[0] == "func_call" ? 2 : 3)..-1] = e
    call
  when :command
    name = exp[1][1]
    args = exp[2][1].map {|e_| simplify(e_) }
    ["func_call", name, *args]
  when :if, :elsif
    cond_exp = simplify(exp[1])
    then_exp = make_stmts(exp[2])
    if exp[3]
      if exp[3][0] == :elsif
        else_exp = simplify(exp[3])
      else
        else_exp = make_stmts(exp[3][1])
      end
    end
    ["if", cond_exp, then_exp, else_exp]
  when :ifop
    cond_exp = simplify(exp[1])
    then_exp = simplify(exp[2])
    else_exp = simplify(exp[3])
    ["if", cond_exp, then_exp, else_exp]
  when :if_mod
    cond_exp = simplify(exp[1])
    then_exp = make_stmts([exp[2]])
    ["if", cond_exp, then_exp, nil]
  when :while
    cond_exp = simplify(exp[1])
    body_exp = make_stmts(exp[2])
    ["while", cond_exp, body_exp]
  when :while_mod
    cond_exp = simplify(exp[1])
    body_exp = make_stmts(exp[2][1][1])
    ["while2", cond_exp, body_exp]
  when :binary
    exp1 = simplify(exp[1])
    op = exp[2]
    exp2 = simplify(exp[3])
    [op.to_s, exp1, exp2]
  when :var_ref
    case exp[1][0]
    when :@kw
      case exp[1][1]
      when "nil" then ["lit", nil]
      when "true" then ["lit", true]
      when "false" then ["lit", false]
      else
        raise
      end
    when :@ident
      ["var_ref", exp[1][1]]
    when :@const
      ["const_ref", exp[1][1]]
    end
  when :@int
    ["lit", exp[1].to_i]
  when :unary
    v = simplify(exp[2])
    raise if v[0] != "lit"
    ["lit", -v[1]]
  when :string_literal
    ["lit", exp[1][1] ? exp[1][1][1] : ""]
  when :symbol_literal
    ["lit", exp[1][1][1].to_sym]
  when :assign
    case exp[1][0]
    when :var_field
      ["var_assign", exp[1][1][1], simplify(exp[2])]
    when :aref_field
      ["ary_assign", simplify(exp[1][1]), simplify(exp[1][2][1][0]), simplify(exp[2])]
    else
      raise
    end
  when :case
    arg = simplify(exp[1])
    when_clauses = []
    exp = exp[2]
    while exp && exp[0] == :when
      pat = exp[1].map {|e_| simplify(e_) }
      when_clauses << [pat, make_stmts(exp[2])]
      exp = exp[3]
    end
    else_clause = make_stmts(exp[1]) if exp
    #["case", arg, when_clauses, else_clause]

    exp = else_clause
    when_clauses.reverse_each do |patterns, stmts|
      patterns.each do |pattern|
        exp = ["if", ["==", arg, pattern], stmts, exp]
      end
    end
    exp
  when :method_add_block
    call = simplify(exp[1])
    blk_params = exp[2][1][1][1].map {|a| a[1] }
    blk_body = exp[2][2].map {|e_| simplify(e_) }
    call << blk_params << blk_body
  when :aref
    ["ary_ref", simplify(exp[1]), *exp[2][1].map {|e_| simplify(e_) }]
  when :array
    ["ary_new", *(exp[1] ? exp[1].map {|e_| simplify(e_) } : [])]
  when :hash
    kvs = ["hash_new"]
    if exp[1]
      exp[1][1].each do |e_|
        key = simplify(e_[1])
        val = simplify(e_[2])
        kvs << key << val
      end
    end
    kvs
  when :void_stmt
    ["lit", nil]
  when :paren
    simplify(exp[1][0])
  else
    pp exp
    raise "unsupported node: #{ exp[0] }"
  end
end