class Rufo::Parser

def self.detect_unparsable_code_type(code)

def self.detect_unparsable_code_type(code)
  tokens = self.lex(code)
  token = tokens.find { |_, kind| kind != :on_sp && kind != :on_ignored_nl }
  case token
  in [_, :on_kw, "yield" | "next" | "break" | "retry" | "redo" => kw, _]
    kw.to_sym
  else
    nil
  end
end

def self.extract_original_code_sexp(decorated_code, extractor)

def self.extract_original_code_sexp(decorated_code, extractor)
  sexp = self.sexp(decorated_code)
  return nil unless sexp
  # [:program, [exp]]
  exp = sexp[1][0]
  code_exps = extractor.call(exp)
  [:program, code_exps]
end

def self.sexp_unparsable_code(code)

def self.sexp_unparsable_code(code)
  code_type = detect_unparsable_code_type(code)
  case code_type
  when :yield
    extract_original_code_sexp(
      "def __rufo_dummy; #{code}; end",
      ->(exp) { exp => [:def, *, [:bodystmt, exps, *]]; exps }
    )
  when :next, :break, :redo
    extract_original_code_sexp(
      "loop do; #{code}; end",
      ->(exp) { exp => [:method_add_block, *, [:do_block, nil, [:bodystmt, [[:void_stmt], *exps], *]]]; exps }
    )
  when :retry
    extract_original_code_sexp(
      "begin; rescue; #{code}; end",
      ->(exp) { exp => [:begin, [:bodystmt, Array, [:rescue, nil, nil, exps, *], *]]; exps }
    )
  end
end

def compile_error(msg)

def compile_error(msg)
  raise ::Rufo::SyntaxError.new(msg, lineno)
end

def on_parse_error(msg)

def on_parse_error(msg)
  raise ::Rufo::SyntaxError.new(msg, lineno)
end