とんちゃんといっしょ

Cloudに関する技術とか日常とかについて書いたり書かなかったり

ore言語実装講習会

Pascalがやるといってたore言語実装講習会に1時間遅れで参加。
最近は研究でRacc使ってParser書いてるから内容がよく分かる。


昼まで四則演算が出来る程度のParserを書いてから御飯を食べに学食へ。
N嶋研のM2の人々がいたので合流して御飯を食べた。


昼からも参加しようとしたのだが、
無性に眠かったのとノートPCのバッテリーがもたないので研究室へ行くことに。
研究室でまた少しParserを書いて、意識が飛びそうになるので仮眠をとる。


予定より30分長く寝た。
おかげですっきりした。


参考サイト:
Racc ユーザマニュアル
Racc で遊ぼう
RaccでSchemeパーサを作る - 趣味的にっき


参考図書:

Rubyを256倍使うための本 無道編
青木 峰郎
アスキー
売り上げランキング: 279104


今日の成果物 calc.y

#racc calc.y -o calc.rb

class Calcp
  prechigh
    nonassoc UMINUS
    left '*' '/'
    left '+' '-'
  preclow

  rule
    target: exp
          | /* none */ { result = 0 }

    exp: exp '+' exp { result += val[2] }
       | exp '-' exp { result -= val[2] }
       | exp '*' exp { result *= val[2] }
       | exp '/' exp { result /= val[2] }
       | '(' exp ')' { result = val[1] }
       | '-' NUMBER  =UMINUS { result = -val[1] }
       | NUMBER
  end

---- header
  require 'strscan'

---- inner
  
  def parse(str)
    @tokens = StringScanner.new(str).collect_token do |scanner|
    case
    when scanner.skip(/\s+/)
    when scanner.scan(/\d+/)
      [:NUMBER, scanner[0].to_i]
    when scanner.scan(/\A.|\n/o)
      s = scanner[0]
      [s, s]
    else
      raise RuntimeError, 'must not happen!'
    end
  end
  #p @tokens
  do_parse
end

def next_token
  @tokens.shift
end

---- footer
class StringScanner
  def collect_token
    tokens = []
    until eos?
      token = yield(self)
      tokens << token if token
    end
    tokens
  end
end

parser = Calcp.new
puts
puts 'type "Q or q" to quit.'
puts
while true
  puts
  print '? '
  str = gets.chop!
  break if /q/i =~ str
  begin
    puts "= #{parser.parse(str)}"
  rescue ParseError
    puts $!
  end
end