#! /usr/bin/env ruby

# mml.ry: Written by Tadayoshi Funaba 1999-2003
# $Id: mml.ry,v 1.27 2003-08-12 05:06:21+09 tadf Exp $
#
# DO NOT MODIFY!!!!
# This file is automatically generated by racc 1.4.3
# from racc grammer file "mml.ry".
#
#
# mml.tab.rb: generated by racc (runtime embedded)
#

###### racc/parser.rb

unless $".index 'racc/parser.rb'
$".push 'racc/parser.rb'

self.class.module_eval <<'..end /usr/local/lib/ruby/site_ruby/1.8/racc/parser.rb modeval..id8b301b2307', '/usr/local/lib/ruby/site_ruby/1.8/racc/parser.rb', 1
#
# parser.rb
#
#   Copyright (c) 1999-2002 Minero Aoki <aamine@loveruby.net>
#
#   This program is free software.
#   You can distribute/modify this program under the same terms of ruby.
#
#   As a special exception, when this code is copied by Racc
#   into a Racc output file, you may use that output file
#   without restriction.
#
#   $Id: parser.rb,v 1.47 2002/11/15 08:08:38 aamine Exp $
#

unless defined? NotImplementedError
  NotImplementedError = NotImplementError
end


module Racc
  class ParseError < StandardError; end
end
unless defined? ::ParseError
  ParseError = Racc::ParseError
end


module Racc

  unless defined? Racc_No_Extentions
    Racc_No_Extentions = false
  end

  class Parser

    Racc_Runtime_Version = '1.4.3'
    Racc_Runtime_Revision = '$Revision: 1.47 $'.split(/\s+/)[1]

    Racc_Runtime_Core_Version_R = '1.4.3'
    Racc_Runtime_Core_Revision_R = '$Revision: 1.47 $'.split(/\s+/)[1]
    begin
      require 'racc/cparse'
    # Racc_Runtime_Core_Version_C  = (defined in extention)
      Racc_Runtime_Core_Revision_C = Racc_Runtime_Core_Id_C.split(/\s+/)[2]
      unless new.respond_to?(:_racc_do_parse_c, true)
        raise LoadError, 'old cparse.so'
      end
      if Racc_No_Extentions
        raise LoadError, 'selecting ruby version of racc runtime core'
      end

      Racc_Main_Parsing_Routine    = :_racc_do_parse_c
      Racc_YY_Parse_Method         = :_racc_yyparse_c
      Racc_Runtime_Core_Version    = Racc_Runtime_Core_Version_C
      Racc_Runtime_Core_Revision   = Racc_Runtime_Core_Revision_C
      Racc_Runtime_Type            = 'c'
    rescue LoadError
      Racc_Main_Parsing_Routine    = :_racc_do_parse_rb
      Racc_YY_Parse_Method         = :_racc_yyparse_rb
      Racc_Runtime_Core_Version    = Racc_Runtime_Core_Version_R
      Racc_Runtime_Core_Revision   = Racc_Runtime_Core_Revision_R
      Racc_Runtime_Type            = 'ruby'
    end

    def self.racc_runtime_type
      Racc_Runtime_Type
    end

    private

    def _racc_setup
      @yydebug = false unless self.class::Racc_debug_parser
      @yydebug = false unless defined? @yydebug
      if @yydebug
        @racc_debug_out = $stderr unless defined? @racc_debug_out
        @racc_debug_out ||= $stderr
      end
      arg = self.class::Racc_arg
      arg[13] = true if arg.size < 14
      arg
    end

    def _racc_init_sysvars
      @racc_state  = [0]
      @racc_tstack = []
      @racc_vstack = []

      @racc_t = nil
      @racc_val = nil

      @racc_read_next = true

      @racc_user_yyerror = false
      @racc_error_status = 0
    end


    ###
    ### do_parse
    ###

    def do_parse
      __send__ Racc_Main_Parsing_Routine, _racc_setup(), false
    end

    def next_token
      raise NotImplementedError, "#{self.class}\#next_token is not defined"
    end

    def _racc_do_parse_rb( arg, in_debug )
      action_table, action_check, action_default, action_pointer,
      goto_table,   goto_check,   goto_default,   goto_pointer,
      nt_base,      reduce_table, token_table,    shift_n,
      reduce_n,     use_result,   * = arg

      _racc_init_sysvars()
      tok = act = i = nil
      nerr = 0

      catch(:racc_end_parse) {
          while true
            if i = action_pointer[@racc_state[-1]]
              if @racc_read_next
                if @racc_t != 0   # not EOF
                  tok, @racc_val = next_token()
                  unless tok      # EOF
                    @racc_t = 0
                  else
                    @racc_t = (token_table[tok] or 1)   # error token
                  end
                  racc_read_token(@racc_t, tok, @racc_val) if @yydebug
                  @racc_read_next = false
                end
              end
              i += @racc_t
              if  i >= 0 and
                  act = action_table[i] and
                  action_check[i] == @racc_state[-1]
                ;
              else
                act = action_default[@racc_state[-1]]
              end
            else
              act = action_default[@racc_state[-1]]
            end
            while act = _racc_evalact(act, arg)
            end
          end
      }
    end


    ###
    ### yyparse
    ###

    def yyparse( recv, mid )
      __send__ Racc_YY_Parse_Method, recv, mid, _racc_setup(), true
    end

    def _racc_yyparse_rb( recv, mid, arg, c_debug )
      action_table, action_check, action_default, action_pointer,
      goto_table,   goto_check,   goto_default,   goto_pointer,
      nt_base,      reduce_table, token_table,    shift_n,
      reduce_n,     use_result,   * = arg

      _racc_init_sysvars
      tok = nil
      act = nil
      i = nil
      nerr = 0


      catch(:racc_end_parse) {
        until i = action_pointer[@racc_state[-1]]
          while act = _racc_evalact(action_default[@racc_state[-1]], arg)
          end
        end

        recv.__send__(mid) do |tok, val|
# $stderr.puts "rd: tok=#{tok}, val=#{val}"
          unless tok
            @racc_t = 0
          else
            @racc_t = (token_table[tok] or 1)   # error token
          end
          @racc_val = val
          @racc_read_next = false

          i += @racc_t
          if  i >= 0 and
              act = action_table[i] and
              action_check[i] == @racc_state[-1]
            ;
# $stderr.puts "01: act=#{act}"
          else
            act = action_default[@racc_state[-1]]
# $stderr.puts "02: act=#{act}"
# $stderr.puts "curstate=#{@racc_state[-1]}"
          end

          while act = _racc_evalact(act, arg)
          end

          while not (i = action_pointer[@racc_state[-1]]) or
                not @racc_read_next or
                @racc_t == 0   # $
            if i and i += @racc_t and
               i >= 0 and
               act = action_table[i] and
               action_check[i] == @racc_state[-1]
              ;
# $stderr.puts "03: act=#{act}"
            else
# $stderr.puts "04: act=#{act}"
              act = action_default[@racc_state[-1]]
            end

            while act = _racc_evalact(act, arg)
            end
          end
        end
      }
    end


    ###
    ### common
    ###

    def _racc_evalact( act, arg )
# $stderr.puts "ea: act=#{act}"
      action_table, action_check, action_default, action_pointer,
      goto_table,   goto_check,   goto_default,   goto_pointer,
      nt_base,      reduce_table, token_table,    shift_n,
      reduce_n,     use_result,   * = arg
nerr = 0   # tmp

      if act > 0 and act < shift_n
        #
        # shift
        #

        if @racc_error_status > 0
          @racc_error_status -= 1 unless @racc_t == 1   # error token
        end

        @racc_vstack.push @racc_val
        @racc_state.push act
        @racc_read_next = true

        if @yydebug
          @racc_tstack.push @racc_t
          racc_shift @racc_t, @racc_tstack, @racc_vstack
        end

      elsif act < 0 and act > -reduce_n
        #
        # reduce
        #

        code = catch(:racc_jump) {
            @racc_state.push _racc_do_reduce(arg, act)
            false
        }
        if code
          case code
          when 1 # yyerror
            @racc_user_yyerror = true   # user_yyerror
            return -reduce_n
          when 2 # yyaccept
            return shift_n
          else
            raise RuntimeError, '[Racc Bug] unknown jump code'
          end
        end

      elsif act == shift_n
        #
        # accept
        #

        racc_accept if @yydebug
        throw :racc_end_parse, @racc_vstack[0]

      elsif act == -reduce_n
        #
        # error
        #

        case @racc_error_status
        when 0
          unless arg[21]    # user_yyerror
            nerr += 1
            on_error @racc_t, @racc_val, @racc_vstack
          end
        when 3
          if @racc_t == 0   # is $
            throw :racc_end_parse, nil
          end
          @racc_read_next = true
        end
        @racc_user_yyerror = false
        @racc_error_status = 3

        while true
          if i = action_pointer[@racc_state[-1]]
            i += 1   # error token
            if  i >= 0 and
                (act = action_table[i]) and
                action_check[i] == @racc_state[-1]
              break
            end
          end

          throw :racc_end_parse, nil if @racc_state.size < 2
          @racc_state.pop
          @racc_vstack.pop
          if @yydebug
            @racc_tstack.pop
            racc_e_pop @racc_state, @racc_tstack, @racc_vstack
          end
        end

        return act

      else
        raise RuntimeError, "[Racc Bug] unknown action #{act.inspect}"
      end

      racc_next_state(@racc_state[-1], @racc_state) if @yydebug

      nil
    end

    def _racc_do_reduce( arg, act )
      action_table, action_check, action_default, action_pointer,
      goto_table,   goto_check,   goto_default,   goto_pointer,
      nt_base,      reduce_table, token_table,    shift_n,
      reduce_n,     use_result,   * = arg
      state = @racc_state
      vstack = @racc_vstack
      tstack = @racc_tstack

      i = act * -3
      len       = reduce_table[i]
      reduce_to = reduce_table[i+1]
      method_id = reduce_table[i+2]
      void_array = []

      tmp_t = tstack[-len, len] if @yydebug
      tmp_v = vstack[-len, len]
      tstack[-len, len] = void_array if @yydebug
      vstack[-len, len] = void_array
      state[-len, len]  = void_array

      # tstack must be updated AFTER method call
      if use_result
        vstack.push __send__(method_id, tmp_v, vstack, tmp_v[0])
      else
        vstack.push __send__(method_id, tmp_v, vstack)
      end
      tstack.push reduce_to

      racc_reduce(tmp_t, reduce_to, tstack, vstack) if @yydebug

      k1 = reduce_to - nt_base
      if i = goto_pointer[k1]
        i += state[-1]
        if i >= 0 and (curstate = goto_table[i]) and goto_check[i] == k1
          return curstate
        end
      end
      goto_default[k1]
    end

    def on_error( t, val, vstack )
      raise ParseError, sprintf("\nparse error on value %s (%s)",
                                val.inspect, token_to_str(t) || '?')
    end

    def yyerror
      throw :racc_jump, 1
    end

    def yyaccept
      throw :racc_jump, 2
    end

    def yyerrok
      @racc_error_status = 0
    end


    # for debugging output

    def racc_read_token( t, tok, val )
      @racc_debug_out.print 'read    '
      @racc_debug_out.print tok.inspect, '(', racc_token2str(t), ') '
      @racc_debug_out.puts val.inspect
      @racc_debug_out.puts
    end

    def racc_shift( tok, tstack, vstack )
      @racc_debug_out.puts "shift   #{racc_token2str tok}"
      racc_print_stacks tstack, vstack
      @racc_debug_out.puts
    end

    def racc_reduce( toks, sim, tstack, vstack )
      out = @racc_debug_out
      out.print 'reduce '
      if toks.empty?
        out.print ' <none>'
      else
        toks.each {|t| out.print ' ', racc_token2str(t) }
      end
      out.puts " --> #{racc_token2str(sim)}"

      racc_print_stacks tstack, vstack
      @racc_debug_out.puts
    end

    def racc_accept
      @racc_debug_out.puts 'accept'
      @racc_debug_out.puts
    end

    def racc_e_pop( state, tstack, vstack )
      @racc_debug_out.puts 'error recovering mode: pop token'
      racc_print_states state
      racc_print_stacks tstack, vstack
      @racc_debug_out.puts
    end

    def racc_next_state( curstate, state )
      @racc_debug_out.puts  "goto    #{curstate}"
      racc_print_states state
      @racc_debug_out.puts
    end

    def racc_print_stacks( t, v )
      out = @racc_debug_out
      out.print '        ['
      t.each_index do |i|
        out.print ' (', racc_token2str(t[i]), ' ', v[i].inspect, ')'
      end
      out.puts ' ]'
    end

    def racc_print_states( s )
      out = @racc_debug_out
      out.print '        ['
      s.each {|st| out.print ' ', st }
      out.puts ' ]'
    end

    def racc_token2str( tok )
      self.class::Racc_token_to_s_table[tok] or
          raise RuntimeError, "[Racc Bug] can't convert token #{tok} to string"
    end

    def token_to_str( t )
      self.class::Racc_token_to_s_table[t]
    end

  end

end
..end /usr/local/lib/ruby/site_ruby/1.8/racc/parser.rb modeval..id8b301b2307
end   # end of racc/parser.rb



require 'rational'
require 'smf'
include  SMF


class MMLParser < Racc::Parser

module_eval <<'..end mml.ry modeval..id0933854176', 'mml.ry', 66

  class SemanticError < StandardError; end

  STEPTAB = { 'w'=>Rational(1, 1), 'h'=>Rational(1, 2),
	      'q'=>Rational(1, 4), 'i'=>Rational(1, 8),
	      's'=>Rational(1, 16),'z'=>Rational(1, 32),
	      'u'=>Rational(1, 1920) }

  NOTETAB = { 'a'=>9, 'b'=>11, 'c'=>0, 'd'=>2, 'e'=>4, 'f'=>5, 'g'=>7 }

  def lineno() @co end

  def parse(str)
    @co = 1
    @str = str
    do_parse
  end

  def next_token
    1.times do
      @str = @str.sub(/\A([\s\v]+)/, '')
      if $1
	@co += $1.count("\n")
      end
      @str = @str.sub(%r|\A(//.*)$|, '')
      if $1
	retry
      end
    end
    return [false, false] if @str.size == 0

    if /\A([whqiszu])\b(\.+)?/i =~ @str
      @str = $'
      n = STEPTAB[$1.downcase]
      i = if $2 then $2.size else 0 end
      p = 1
      i.times do |j|
	p += Rational(1, 2 ** (j + 1))
      end
      s = n * p
      return [:STEP, s]
    end

    if /\Ar\b/i =~ @str
      @str = $'
      return [:NOTE, nil]
    end

    if /\A([abcdefg])\b([$%#]+)?([,']+)?/i =~ @str
      @str = $'
      na = NOTETAB[$1.downcase]
      if $2
	s1 = 0
	s1 -= $2.count('$')
	s1 += $2.count('#')
      end
      if $3
	s12 = 0
	s12 -= $3.count(",") * 12
	s12 += $3.count("'") * 12
      end
      return [:NOTE, [na, s1, s12]]
    end

    if /\A"/ =~ @str
      @str = $'
      s = ''
      until /\A"/ =~ @str
	case @str
	when /\A(\\a)/; s << "\a"
	when /\A(\\b)/; s << "\b"
	when /\A(\\e)/; s << "\e"
	when /\A(\\f)/; s << "\f"
	when /\A(\\n)/; s << "\n"
	when /\A(\\r)/; s << "\r"
	when /\A(\\t)/; s << "\t"
	when /\A(\\v)/; s << "\v"
	when /\A(\\\\)/; s << "\\"
	when /\A(\\")/; s << '"'
	when /\A\\([0-7]{3})/; s << $1.oct.chr
	when /\A\\x([0-9a-z]{2})/i; s << $1.hex.chr
	when /\A(\\\n)/
	when /\A(.)/m; s << $1
	end
	@co += $1.count("\n")
	@str = $'
      end
      @str = $'
      return [:TEXT, s]
    end

    if /\A([a-z][a-z0-9]*)/i =~ @str
      @str = $'
      return [:VAR, $1]
    end

    if %r|\A([-+*/]?=)| =~ @str
      @str = $'
      return [:AOP, $1[0]]
    end

    if /\A(\d+)/ =~ @str
      @str = $'
      return [:NUM, Rational($1.to_i)]
    end

    if /\A(.)/ =~ @str
      @str = $'
      return [$1, $1]
    end
  end

..end mml.ry modeval..id0933854176

##### racc 1.4.3 generates ###

racc_reduce_table = [
 0, 0, :racc_error,
 1, 20, :_reduce_1,
 0, 21, :_reduce_2,
 2, 21, :_reduce_3,
 1, 22, :_reduce_4,
 2, 22, :_reduce_5,
 1, 23, :_reduce_6,
 1, 23, :_reduce_none,
 1, 23, :_reduce_none,
 1, 23, :_reduce_none,
 3, 23, :_reduce_10,
 1, 25, :_reduce_11,
 1, 26, :_reduce_12,
 3, 27, :_reduce_13,
 5, 27, :_reduce_14,
 3, 24, :_reduce_15,
 3, 24, :_reduce_16,
 3, 24, :_reduce_17,
 3, 24, :_reduce_18,
 3, 24, :_reduce_19,
 1, 24, :_reduce_20,
 3, 28, :_reduce_21,
 3, 28, :_reduce_22,
 3, 28, :_reduce_23,
 3, 28, :_reduce_24,
 2, 28, :_reduce_25,
 3, 28, :_reduce_26,
 1, 28, :_reduce_27 ]

racc_reduce_n = 28

racc_shift_n = 48

racc_action_table = [
    19,    20,    21,    22,    37,    39,    40,    41,    18,    26,
    26,    26,    10,    33,    13,    26,    26,    42,    25,    25,
    25,    28,    28,    28,    25,    25,    26,    28,    28,    17,
    26,    26,    26,    37,    39,    25,    26,    16,    28,    25,
    25,    25,    28,    28,    28,    25,    19,    20,    28,    37,
    39,    40,    41,     3,    14,    34,    15,     4,     6,   nil,
    38,    10,    14,    13,    15,     4,     6,   nil,    10,    10,
    13,    13,    37,    39,    40,    41,    19,    20,    21,    22,
    10,   nil,    13,    19,    20,    37,    39 ]

racc_action_check = [
    23,    23,    23,    23,    35,    35,    35,    35,     7,    26,
    38,    41,    10,    23,    10,    37,    40,    35,    26,    38,
    41,    26,    38,    41,    37,    40,    17,    37,    40,     6,
    19,    20,    25,    46,    46,    17,    39,     3,    17,    19,
    20,    25,    19,    20,    25,    39,    32,    32,    39,    27,
    27,    27,    27,     1,    24,    24,    24,    24,    24,   nil,
    27,    24,     2,    24,     2,     2,     2,   nil,    21,     2,
    21,     2,    44,    44,    44,    44,     8,     8,     8,     8,
    22,   nil,    22,    31,    31,    47,    47 ]

racc_action_pointer = [
   nil,    53,    54,    37,   nil,   nil,    16,     1,    73,   nil,
    -3,   nil,   nil,   nil,   nil,   nil,   nil,    20,   nil,    24,
    25,    53,    65,    -3,    46,    26,     3,    46,   nil,   nil,
   nil,    80,    43,   nil,   nil,     1,   nil,     9,     4,    30,
    10,     5,   nil,   nil,    69,   nil,    30,    82 ]

racc_action_default = [
    -2,   -28,    -1,   -28,   -12,    -3,   -28,    -4,    -6,    -7,
   -28,    -8,    -9,   -20,    -2,   -11,    48,   -28,    -5,   -28,
   -28,   -28,   -28,   -28,   -28,   -28,   -28,   -13,   -27,   -17,
   -18,   -15,   -16,   -19,   -10,   -28,   -25,   -28,   -28,   -28,
   -28,   -28,   -26,   -23,   -14,   -24,   -21,   -22 ]

racc_goto_table = [
    27,     2,    29,    30,     1,    23,   nil,   nil,    35,    36,
   nil,   nil,   nil,   nil,   nil,    24,    31,    32,   nil,   nil,
    43,    44,    45,    46,    47 ]

racc_goto_check = [
     9,     2,     9,     9,     1,     5,   nil,   nil,     9,     9,
   nil,   nil,   nil,   nil,   nil,     2,     5,     5,   nil,   nil,
     9,     9,     9,     9,     9 ]

racc_goto_pointer = [
   nil,     4,     1,   nil,   nil,    -5,   nil,   nil,   nil,   -17 ]

racc_goto_default = [
   nil,   nil,   nil,     5,     7,     8,     9,    11,    12,   nil ]

racc_token_table = {
 false => 0,
 Object.new => 1,
 :UMINUS => 2,
 "*" => 3,
 "/" => 4,
 "+" => 5,
 "-" => 6,
 "&" => 7,
 "{" => 8,
 "}" => 9,
 :NOTE => 10,
 :TEXT => 11,
 :VAR => 12,
 :AOP => 13,
 "," => 14,
 "(" => 15,
 ")" => 16,
 :STEP => 17,
 :NUM => 18 }

racc_use_result_var = true

racc_nt_base = 19

Racc_arg = [
 racc_action_table,
 racc_action_check,
 racc_action_default,
 racc_action_pointer,
 racc_goto_table,
 racc_goto_check,
 racc_goto_default,
 racc_goto_pointer,
 racc_nt_base,
 racc_reduce_table,
 racc_token_table,
 racc_shift_n,
 racc_reduce_n,
 racc_use_result_var ]

Racc_token_to_s_table = [
'$end',
'error',
'UMINUS',
'"*"',
'"/"',
'"+"',
'"-"',
'"&"',
'"{"',
'"}"',
'NOTE',
'TEXT',
'VAR',
'AOP',
'","',
'"("',
'")"',
'STEP',
'NUM',
'$start',
'prog',
'list',
'stmt',
'expr',
'step',
'note',
'text',
'asgn',
'num']

Racc_debug_parser = false

##### racc system variables end #####

 # reduce 0 omitted

module_eval <<'.,.,', 'mml.ry', 15
  def _reduce_1( val, _values, result )
 result = val[0]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 17
  def _reduce_2( val, _values, result )
 result = [:list, []]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 18
  def _reduce_3( val, _values, result )
 val[0][1] << val[1]; result = val[0]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 21
  def _reduce_4( val, _values, result )
 result = [:stmt, val[0]]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 22
  def _reduce_5( val, _values, result )
 result = [:stmt, val[0], val[1]]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 25
  def _reduce_6( val, _values, result )
 result = [:step, val[0]]
   result
  end
.,.,

 # reduce 7 omitted

 # reduce 8 omitted

 # reduce 9 omitted

module_eval <<'.,.,', 'mml.ry', 27
  def _reduce_10( val, _values, result )
 result = val[1]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 30
  def _reduce_11( val, _values, result )
 result = [:note, val[0]]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 31
  def _reduce_12( val, _values, result )
 result = [:text, val[0]]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 34
  def _reduce_13( val, _values, result )
 result = [:asgn, val[0], val[1], val[2]]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 36
  def _reduce_14( val, _values, result )
 result = [:asgn, val[0], val[1], val[2], val[4]]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 39
  def _reduce_15( val, _values, result )
 result = [:add, val[0], val[2]]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 40
  def _reduce_16( val, _values, result )
 result = [:sub, val[0], val[2]]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 41
  def _reduce_17( val, _values, result )
 result = [:mul, val[0], val[2]]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 42
  def _reduce_18( val, _values, result )
 result = [:div, val[0], val[2]]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 43
  def _reduce_19( val, _values, result )
 result = val[1]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 44
  def _reduce_20( val, _values, result )
 result = [:imm, val[0]]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 47
  def _reduce_21( val, _values, result )
 result = [:add, val[0], val[2]]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 48
  def _reduce_22( val, _values, result )
 result = [:sub, val[0], val[2]]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 49
  def _reduce_23( val, _values, result )
 result = [:mul, val[0], val[2]]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 50
  def _reduce_24( val, _values, result )
 result = [:div, val[0], val[2]]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 51
  def _reduce_25( val, _values, result )
 result = [:negate, val[1]]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 52
  def _reduce_26( val, _values, result )
 result = val[1]
   result
  end
.,.,

module_eval <<'.,.,', 'mml.ry', 53
  def _reduce_27( val, _values, result )
 result = [:imm, val[0]]
   result
  end
.,.,

 def _reduce_none( val, _values, result )
  result
 end

end   # class MMLParser


class MMLEvaluator

  def initialize(de)
    @de = []
    @de << de
  end

  def top() @de[-1] end
  def push() @de.push(top.cp) end
  def pop() @de.pop end

  private :top, :push, :pop

  def evaluate(st)
    case st[0]
    when :list
      push
      st[1].each do |st2|
	evaluate(st2)
      end
      of = top[:of]
      pop
      top[:of] = of
      top.ci
    when :stmt
      of = top[:of]
      evaluate(st[1])
      if st[2]
	top[:of] = of
      end
    when :step
      top[:le] = evaluate(st[1])
    when :add
      return evaluate(st[1]) + evaluate(st[2])
    when :sub
      return evaluate(st[1]) - evaluate(st[2])
    when :mul
      return evaluate(st[1]) * evaluate(st[2])
    when :div
      return evaluate(st[1]) / evaluate(st[2])
    when :negate
      return - evaluate(st[1])
    when :imm
      return st[1]
    when :note
      top[:no] = st[1]
      top.ci
      top[:no] = nil
      top[:of] += top[:le]
    when :text
      top[:tx] = st[1]
      top.ci
      top[:tx] = nil
    when :asgn
      va = st[1]
      op = st[2]
      ob = evaluate(st[3])
      if st[4]
	ob2 = evaluate(st[4])
	ob = [ob, ob2]
      end
      va = va.intern
      v = top[va]
      case op
      when ?+; v += ob
      when ?-; v -= ob
      when ?*; v *= ob
      when ?/; v /= ob
      when ?=; v  = ob
      end
      top[va] = v
      top.ci
     end
  end

end

class Sheet

  def initialize(sq)
    @sq = sq
    @co = []
    @ke = {}
  end

  def ci(desc) @co << desc.cp end

  def gt(n) @sq[n] ||= Track.new end

  private :gt

  def re(v, l, h=nil)
    if v and l and v < l then v = l end
    if v and h and v > h then v = h end
    v
  end

  private :re

  def gen
    i = -1
    @co.collect!{|x| [x, i += 1]}
    @co.sort!
    @co.collect!{|x| x[0]}

    lev = Descripter.new(nil)

    wh = @sq.division * 4

    @co.each do |ev|

      tr = ev[:tr].to_i; tr = re(tr, 0, 65535) # 0/2**16-1
      ch = ev[:ch].to_i; ch = re(ch, 0, 15)    # 0/2**4-1
      of = ev[:of];      of = re(of, 0)
      oc = ev[:oc]
      le = ev[:le];      le = re(le, Rational(0))
      du = ev[:du];      du = re(du, Rational(0))
      ve = ev[:ve];      ve = re(ve, Rational(0), Rational(1))

      sf, = ev[:ke]

      keys = ev.keys

      [:tr, :ch, :of, :oc, :le, :du, :ve].each do |key|
	keys.delete(key)
      end

      keys.each do |key|

	if ev[key] == nil or ev[key] == lev[key]
	  next
	end

	v = ev[key]

	case key.to_s

	when 'no'
	  t = gt(tr)
	  o = (of * wh).round
	  p = ((of + le * du) * wh).round
	  na, s1, s12 = v
	  unless s1
	    if @ke[sf]
	      s1 = @ke[sf][na]
	    end
	  end
          s1  ||=0
          s12 ||=0
	  n = (na + s1 + s12 + oc * 12 + 12).to_i
	  if n < 0   then n =        n        % 12 end
	  if n > 127 then n = 116 + (n - 116) % 12 end
	  w = (ve * 127).round
	  if w != 0
	    t << NoteOn.new(o, ch, n, w)
	    t << NoteOff.new(p, ch, n, 64)
	  end
	  next

	when 'tx'
	  n = if /\A(co|sq):/ =~ v then 0 else tr end
	  t = gt(n)
	  o = (of * wh).round
	  case v
	  when /\Ate:/; t << GeneralPurposeText.new(o, $')
	  when /\Aco:/; t << CopyrightNotice.new(o, $')
	  when /\Asq:/; t << TrackName.new(o, $')
	  when /\Atr:/; t << TrackName.new(o, $')
	  when /\Ain:/; t << InstrumentName.new(o, $')
	  when /\Aly:/; t << Lyric.new(o, $')
	  when /\Ama:/; t << Marker.new(o, $')
	  when /\Acu:/; t << CuePoint.new(o, $')
	  when /\Apr:/; t << ProgramName.new(o, $')
	  when /\Ade:/; t << DeviceName.new(o, $')
	  else;         t << GeneralPurposeText.new(o, v)
	  end
	  next

	when 'te'
	  v = re(v, 1, 16777215) # 1/2**24-1
	  t = gt(0)
	  o = (of * wh).round
	  t <<  SetTempo.new(o, (60000000 / v).round)

	when 'ti'
	  v = [re(v[0], 1, 255), # 1/2**8-1
	       re(v[1], 0, 255)  # 0/2**8-1
	      ] if v
	  t = gt(0)
	  o = (of * wh).round
	  n, d = v
	  n, d = n.to_i, d.to_i
	  dd = -1
	  while d != 0
	    d >>= 1
	    dd += 1
	  end
	  c = 96 >> dd
	  t << TimeSignature.new(o, n, dd, c, 8)

	when 'ke'
	  v = [re(v[0], -128, 127), # -2**7/2**7-1
	       re(v[1], 0, 1)       # 0/1
	      ] if v
	  t = gt(tr)
	  o = (of * wh).round
	  s, m = v
	  t << KeySignature.new(o, s.to_i, m.to_i)

	  unless @ke[s]
	    @ke[s] = [0]*12
	    d = if s < 0 then -1 else +1 end
	    b = if d == 1 then 5 else 11 end
	    s.to_i.abs.times do |i|
	      n = (b + 7 * i * d) % 12
	      @ke[s][n] ||= 0
	      @ke[s][n] += d
	    end
	  end

	when /\App(\d+)\/\d+\Z/
	  n = $1
	  v = re(v, 0, 127) # 0/2**7-1
	  t = gt(tr)
	  o = (of * wh).round
	  t << PolyphonicKeyPressure.new(o, ch, n.to_i, v.to_i)

	when /\Aco(\d+)\/\d+\Z/
	  n = $1
	  v = re(v, 0, 127) # 0/2**7-1
	  t = gt(tr)
	  o = (of * wh).round
	  t << ControlChange.new(o, ch, n.to_i, v.to_i)

	when /\Amo(\d+)\/\d+\Z/
	  n = $1
	  v = re(v, 0, 127) # 0/2**7-1
	  t = gt(tr)
	  o = (of * wh).round
	  t << ChannelModeMessage.new(o, ch, n.to_i, v.to_i)

	when /\Apr\/\d+\Z/
	  v = re(v, 0, 127) # 0/2**7-1
	  t = gt(tr)
	  o = (of * wh).round
	  t << ProgramChange.new(o, ch, v.to_i)

	when /\Acp\/\d+\Z/
	  v = re(v, 0, 127) # 0/2**7-1
	  t = gt(tr)
	  o = (of * wh).round
	  t << ChannelPressure.new(o, ch, v.to_i)

	when /\Api\/\d+\Z/
	  v = re(v, -8192, 8191) # -2**13/2**13-1
	  t = gt(tr)
	  o = (of * wh).round
	  t << p = PitchBendChange.new(o, ch, v.to_i)

	when 'gm'
	  v = re(v, 0, 1) # 0/1
	  t = gt(0)
	  o = (of * wh).round
	  if v != 0
	    t << p = ExclusiveF0.new(o, "\xfe\x7f\x09\x01\xf7")
	  else
	    t << p = ExclusiveF0.new(o, "\xfe\x7f\x09\x02\xf7")
	  end

	end

	lev[key] = v

      end

    end

    ev = @co[-1]
    max_of = (if ev then ev[:of] else 0 end)
    o = (max_of * wh).round
    @sq.each do |tr| tr << EndOfTrack.new(o) end

  end

end

class Descripter

  include Comparable

  STEPTAB = { 'w'=>Rational(1, 1), 'h'=>Rational(1, 2),
	      'q'=>Rational(1, 4), 'i'=>Rational(1, 8),
	      's'=>Rational(1, 16),'z'=>Rational(1, 32),
	      'u'=>Rational(1, 1920) }

  NOTETAB = { 'a'=>9, 'b'=>11, 'c'=>0, 'd'=>2, 'e'=>4, 'f'=>5, 'g'=>7 }

  def initialize(sh)
    @sh = sh
    @ha = {}
    @ha[:tr] = 1
    @ha[:ch] = 0
    @ha[:of] = 0
    @ha[:oc] = Rational(4, 1)
    @ha[:le] = Rational(1, 4)
    @ha[:du] = Rational(9, 10)
    @ha[:ve] = Rational(1, 2)
  end

  def rv(k, ch)
    k = k.to_s
    k.gsub!(/0+(\d)/, '\1')
    case k
    when /\A(pp|co|mo)(\d+)\Z/; k += format('/%d', ch)
    when /\A(pr|cp|pi)\Z/     ; k += format('/%d', ch)
    end
    k = k.intern
  end

  private :rv

  def [] (k)    k = rv(k, @ha[:ch].to_i); @ha[k]     end
  def []=(k, v) k = rv(k, @ha[:ch].to_i); @ha[k] = v end

  def keys() @ha.keys end

  def ci() @sh.ci(self) end

  def cp()
    se, ha, st = self.dup, @ha.dup, []
    se.instance_eval do @ha, @st = ha, st end
    se
  end

  def <=>(other) self[:of] <=> other[:of] end

end

def usage
  warn 'usage: mml ifile [ofile]'
  exit 1
end

usage unless $*.size >= 1 and $*.size <= 2
ifile = $*.shift
ofile = $*.shift
ofile ||= File.basename(ifile, '.mml') + '.mid'

mi = open(ifile){|input| input.read}
sq = Sequence.new(1, 480)
sh = Sheet.new(sq)
de = Descripter.new(sh)
pa = MMLParser.new
ev = MMLEvaluator.new(de)
begin
  st = pa.parse(mi)
  ev.evaluate(st)
rescue
  warn format("%s: %d: syntax or semantic error\n", ifile, pa.lineno)
  exit 1
end
sh.gen
sq.encodefile(ofile)
