module MIKU

Public Class Methods

_after(s, r) click to toggle source
# File core/miku/parser.rb, line 52
def self._after(s, r)
  read_to(s){ |c| not(c =~ /[\t ]/) }
  skipped = s.getc
  if skipped.respond_to?(:chr) and skipped.chr == "["
    pos = s.staticcode_dump
    return _after(s, Cons.new(r, _list(s, ']').extend(StaticCode).staticcode_copy_info(pos)
                              ).extend(StaticCode).staticcode_copy_info(pos))
  else
    s.ungetc(skipped) if skipped
  end
  r
end
_comment(s) click to toggle source
# File core/miku/parser.rb, line 65
def self._comment(s)
  read_to(s){ |c| c == "\n" }
end
_list(s, pend=')') click to toggle source
# File core/miku/parser.rb, line 92
def self._list(s, pend=')')
  scd = s.staticcode_dump
  c = s.getc.chr
  return nil if c == pend
  s.ungetc(c[0])
  car = _parse(s)
  c = skipspace(s)
  if(c == '.') then
    cdr = _parse(s)
    s.ungetc(skipspace(s)[0])
    raise SyntaxError.new('ドット対がちゃんと終わってないよ',s) if(s.getc.chr != pend)
    return Cons.new(car, cdr).extend(StaticCode).staticcode_copy_info(scd)
  else
    s.ungetc(c[0])
    return Cons.new(car, _list(s, pend)).extend(StaticCode).staticcode_copy_info(scd)
  end
end
_parse(s) click to toggle source
# File core/miku/parser.rb, line 19
def self._parse(s)
  while(true) do
    c = skipspace(s)
    if c == ';'
      _comment(s)
    else
      break end end
  pos = s.staticcode_dump
  r = case c
      when '(' then
        _list(s)
      when '#' then
        _structure(s)
      when '"' then
        _string(s)
      when '`' then
        Cons.list(:backquote, _parse(s)).extend(StaticCode).staticcode_copy_info(pos)
      when ',' then
        c = s.getc.chr
        if c == '@' then
          Cons.list(:comma_at, _parse(s)).extend(StaticCode).staticcode_copy_info(pos)
        else
          s.ungetc(c[0])
          Cons.list(:comma, _parse(s)).extend(StaticCode).staticcode_copy_info(pos)
        end
      when '\' then
        Cons.list(:quote, _parse(s)).extend(StaticCode).staticcode_copy_info(pos)
      else
        _symbol(c, s)
      end
  _after(s, r)
end
_string(s) click to toggle source
# File core/miku/parser.rb, line 110
def self._string(s)
  result = read_to(s){ |c| c == '"' }
  s.getc
  result.extend(StaticCode).staticcode_copy_info(s)
end
_structure(s) click to toggle source
# File core/miku/parser.rb, line 69
def self._structure(s)
  c = skipspace(s)
  pos = s.staticcode_dump
  if(c == '(')
    Cons.new(:lambda, _list(s)).extend(StaticCode).staticcode_copy_info(pos)
  else
    type = _symbol(c, s)
    c = skipspace(s)
    if c != '('
      raise SyntaxError.new("##{type}の後に文字#{c}があります。必ず中括弧をおいてください",s)
    end
    pos = s.staticcode_dump
    lst = _list(s).extend(StaticCode).staticcode_copy_info(pos)
    case
    when [:array, :a].include?(type)
      lst.to_a.extend(StaticCode).staticcode_copy_info(pos)
    when [:hash, :h].include?(type)
      genlist = Cons.new(:list, lst).extend(StaticCode).staticcode_copy_info(pos)
      Cons.list(:to_hash, genlist).extend(StaticCode).staticcode_copy_info(pos)
      # Hash[*lst.to_a].extend(StaticCode).staticcode_copy_info(pos)
    when [:lambda, :function, :func, :f].include?(type)
      Cons.new(:lambda, lst).extend(StaticCode).staticcode_copy_info(pos) end end end
_symbol(c, s) click to toggle source
# File core/miku/parser.rb, line 116
def self._symbol(c, s)
  sym = c + read_to(s){ |c| not(c =~ /[^\(\)\{}\[\].',#\s]/) }
  raise SyntaxError.new('### 深刻なエラーが発生しました ###',s) if not(sym)
  if(sym =~ /^-?[0-9]+$/) then
    sym.to_i
  elsif(sym =~ /^-?[0-9]+\.[0-9]+$/) then
    sym.to_f
  elsif(sym == 'nil') then
    nil
  elsif(sym == '')
    raise MIKU::EndofFile
  else
    sym.to_sym
  end
end
parse(str) click to toggle source
# File core/miku/parser.rb, line 9
def self.parse(str)
  if(str.is_a?(String))
    _parse(StringIO.new(str, 'r').extend(StaticCode))
  else
    str.extend(StaticCode) if not str.is_a? StaticCode
    str.staticcode_file = str.path if defined? str.path
    _parse(str)
  end
end
read_to(s, escape=false, &cond) click to toggle source
# File core/miku/parser.rb, line 132
def self.read_to(s, escape=false, &cond)
  c = s.getc
  return '' if not c
  c = c.chr
  if !escape and cond.call(c)
    s.ungetc(c[0])
    return '' end
  case
  when '\' == c
    read_to(s, true, &cond)
  when ('n' == c) && escape
    "\n" + read_to(s, &cond)
  else
    c + read_to(s, &cond) end
end
skipspace(s) click to toggle source
# File core/miku/parser.rb, line 148
def self.skipspace(s)
  c = s.getc
  return '' if not c
  c = c.chr
  s.staticcode_line += 1 if c == "\n"
  return skipspace(s) if(c =~ /\s/)
  c
end
unparse(val) click to toggle source
# File core/miku/parser.rb, line 157
def self.unparse(val)
  if val === nil
    'nil'
  elsif(val.is_a?(List))
    val.unparse
  elsif(val.is_a?(String))
    '"' + val.dup.gsub("\n", '\n').gsub('"', '\"') + '"'
  elsif(val.respond_to?(:unparse))
    val.unparse
  else
    val.inspect end end

Public Instance Methods

parse_caller(at) click to toggle source
# File core/miku/error.rb, line 37
def parse_caller(at)
  if /^(.+?):(\d+)(?::in `(.*)')?/ =~ at
    file = $1
    line = $2.to_i
    method = $3
    [file, line, method]
  end
end