lib/racc/parser.rb


DEFINITIONS

This source file includes following functions.


   1  #
   2  # parser.rb
   3  #
   4  #   Copyright (c) 1999-2002 Minero Aoki <aamine@loveruby.net>
   5  #
   6  #   This program is free software.
   7  #   You can distribute/modify this program under the same terms of ruby.
   8  #
   9  #   As a special exception, when this code is copied by Racc
  10  #   into a Racc output file, you may use that output file
  11  #   without restriction.
  12  #
  13  #   $Id: parser.rb,v 1.1 2002/03/22 07:20:31 aamine Exp $
  14  #
  15  
  16  unless defined? NotImplementedError then
  17    NotImplementedError = NotImplementError
  18  end
  19  
  20  
  21  module Racc
  22    class ParseError < StandardError; end
  23  end
  24  unless defined? ::ParseError then
  25    ParseError = Racc::ParseError
  26  end
  27  
  28  
  29  module Racc
  30  
  31    unless defined? Racc_No_Extentions then
  32      Racc_No_Extentions = false
  33    end
  34  
  35    class Parser
  36  
  37      Racc_Runtime_Version = '1.4.2'
  38      Racc_Runtime_Revision = '$Revision: 1.1 $'.split(/\s+/)[1]
  39  
  40      Racc_Runtime_Core_Version_R = '1.4.2'
  41      Racc_Runtime_Core_Revision_R = '$Revision: 1.1 $'.split(/\s+/)[1]
  42      begin
  43        require 'racc/cparse'
  44      # Racc_Runtime_Core_Version_C  = (defined in extention)
  45        Racc_Runtime_Core_Revision_C = Racc_Runtime_Core_Id_C.split(/\s+/)[2]
  46        unless new.respond_to? :_racc_do_parse_c, true then
  47          raise LoadError, 'old cparse.so'
  48        end
  49        if Racc_No_Extentions then
  50          raise LoadError, 'selecting ruby version of racc runtime core'
  51        end
  52  
  53        Racc_Main_Parsing_Routine    = :_racc_do_parse_c
  54        Racc_YY_Parse_Method         = :_racc_yyparse_c
  55        Racc_Runtime_Core_Version    = Racc_Runtime_Core_Version_C
  56        Racc_Runtime_Core_Revision   = Racc_Runtime_Core_Revision_C
  57        Racc_Runtime_Type            = 'c'
  58      rescue LoadError
  59        Racc_Main_Parsing_Routine    = :_racc_do_parse_rb
  60        Racc_YY_Parse_Method         = :_racc_yyparse_rb
  61        Racc_Runtime_Core_Version    = Racc_Runtime_Core_Version_R
  62        Racc_Runtime_Core_Revision   = Racc_Runtime_Core_Revision_R
  63        Racc_Runtime_Type            = 'ruby'
  64      end
  65  
  66      def self.racc_runtime_type
  67        Racc_Runtime_Type
  68      end
  69  
  70  
  71      private
  72  
  73  
  74      def _racc_setup
  75        t = self.type
  76  
  77        unless t::Racc_debug_parser then
  78          @yydebug = false
  79        end
  80        @yydebug = false unless defined? @yydebug
  81  
  82        if @yydebug then
  83          @racc_debug_out = $stderr unless defined? @racc_debug_out
  84          @racc_debug_out ||= $stderr
  85        end
  86  
  87        arg = t::Racc_arg
  88        if arg.size < 14 then
  89          arg[13] = true
  90        end
  91        arg
  92      end
  93  
  94      def _racc_init_sysvars
  95        @racc_state = [ 0 ]
  96        @racc_tstack = []
  97        @racc_vstack = []
  98  
  99        @racc_t = nil
 100        @racc_val = nil
 101  
 102        @racc_read_next = true
 103  
 104        @racc_user_yyerror = false
 105        @racc_error_status = 0
 106      end
 107  
 108  
 109      ###
 110      ### do_parse
 111      ###
 112  
 113      def do_parse
 114        __send__ Racc_Main_Parsing_Routine, _racc_setup(), false
 115      end
 116  
 117      def next_token
 118        raise NotImplementedError, "#{self.type}\#next_token is not defined"
 119      end
 120  
 121      def _racc_do_parse_rb( arg, in_debug )
 122        action_table, action_check, action_default, action_pointer,
 123        goto_table,   goto_check,   goto_default,   goto_pointer,
 124        nt_base,      reduce_table, token_table,    shift_n,
 125        reduce_n,     use_result,   * = arg
 126  
 127        _racc_init_sysvars
 128        tok = act = i = nil
 129        nerr = 0
 130  
 131  
 132        catch( :racc_end_parse ) {
 133        while true do
 134  
 135          if i = action_pointer[ @racc_state[-1] ] then
 136            if @racc_read_next then
 137              if @racc_t != 0 then   # not EOF
 138                tok, @racc_val = next_token()
 139                unless tok then   # EOF
 140                  @racc_t = 0
 141                else
 142                  @racc_t = (token_table[tok] or 1)   # error token
 143                end
 144                racc_read_token( @racc_t, tok, @racc_val ) if @yydebug
 145  
 146                @racc_read_next = false
 147              end
 148            end
 149            i += @racc_t
 150            if i >= 0 and act = action_table[i] and
 151               action_check[i] == @racc_state[-1] then
 152              ;
 153            else
 154              act = action_default[ @racc_state[-1] ]
 155            end
 156          else
 157            act = action_default[ @racc_state[-1] ]
 158          end
 159  
 160          while act = _racc_evalact( act, arg ) do end
 161  
 162        end
 163        }
 164      end
 165  
 166  
 167      ###
 168      ### yyparse
 169      ###
 170  
 171      def yyparse( recv, mid )
 172        __send__ Racc_YY_Parse_Method, recv, mid, _racc_setup(), true
 173      end
 174  
 175      def _racc_yyparse_rb( recv, mid, arg, c_debug )
 176        action_table, action_check, action_default, action_pointer,
 177        goto_table,   goto_check,   goto_default,   goto_pointer,
 178        nt_base,      reduce_table, token_table,    shift_n,
 179        reduce_n,     use_result,   * = arg
 180  
 181        _racc_init_sysvars
 182        tok = nil
 183        act = nil
 184        i = nil
 185        nerr = 0
 186  
 187  
 188        catch( :racc_end_parse ) {
 189          until i = action_pointer[ @racc_state[-1] ] do
 190            while act = _racc_evalact(
 191                    action_default[ @racc_state[-1] ], arg ) do end
 192          end
 193  
 194          recv.__send__( mid ) do |tok, val|
 195  # $stderr.puts "rd: tok=#{tok}, val=#{val}"
 196            unless tok then
 197              @racc_t = 0
 198            else
 199              @racc_t = (token_table[tok] or 1)   # error token
 200            end
 201            @racc_val = val
 202            @racc_read_next = false
 203  
 204            i += @racc_t
 205            if i >= 0 and act = action_table[i] and
 206               action_check[i] == @racc_state[-1] then
 207  # $stderr.puts "01: act=#{act}"
 208            else
 209              act = action_default[ @racc_state[-1] ]
 210  # $stderr.puts "02: act=#{act}"
 211  # $stderr.puts "curstate=#{@racc_state[-1]}"
 212            end
 213  
 214            while act = _racc_evalact( act, arg ) do end
 215  
 216            while not (i = action_pointer[ @racc_state[-1] ]) or
 217                  not @racc_read_next or
 218                  @racc_t == 0 do   # $
 219              if i and i += @racc_t and
 220                 i >= 0 and
 221                 act = action_table[i] and
 222                 action_check[i] == @racc_state[-1] then
 223  # $stderr.puts "03: act=#{act}"
 224                ;
 225              else
 226  # $stderr.puts "04: act=#{act}"
 227                act = action_default[ @racc_state[-1] ]
 228              end
 229  
 230              while act = _racc_evalact( act, arg ) do end
 231            end
 232          end
 233        }
 234      end
 235  
 236  
 237      ###
 238      ### common
 239      ###
 240  
 241      def _racc_evalact( act, arg )
 242  # $stderr.puts "ea: act=#{act}"
 243        action_table, action_check, action_default, action_pointer,
 244        goto_table,   goto_check,   goto_default,   goto_pointer,
 245        nt_base,      reduce_table, token_table,    shift_n,
 246        reduce_n,     use_result,   * = arg
 247  nerr = 0   # tmp
 248  
 249        if act > 0 and act < shift_n then
 250          #
 251          # shift
 252          #
 253  
 254          if @racc_error_status > 0 then
 255            @racc_error_status -= 1 unless @racc_t == 1   # error token
 256          end
 257  
 258          @racc_vstack.push @racc_val
 259          @racc_state.push act
 260          @racc_read_next = true
 261  
 262          if @yydebug then
 263            @racc_tstack.push @racc_t
 264            racc_shift( @racc_t, @racc_tstack, @racc_vstack )
 265          end
 266  
 267        elsif act < 0 and act > -reduce_n then
 268          #
 269          # reduce
 270          #
 271  
 272          code = catch( :racc_jump ) {
 273            @racc_state.push _racc_do_reduce( arg, act )
 274            false
 275          }
 276          if code then
 277            case code
 278            when 1 # yyerror
 279              @racc_user_yyerror = true   # user_yyerror
 280              return -reduce_n
 281            when 2 # yyaccept
 282              return shift_n
 283            else
 284              raise RuntimeError, '[Racc Bug] unknown jump code'
 285            end
 286          end
 287  
 288        elsif act == shift_n then
 289          #
 290          # accept
 291          #
 292  
 293          racc_accept if @yydebug
 294          throw :racc_end_parse, @racc_vstack[0]
 295  
 296        elsif act == -reduce_n then
 297          #
 298          # error
 299          #
 300  
 301          case @racc_error_status
 302          when 0
 303            unless arg[21] then   # user_yyerror
 304              nerr += 1
 305              on_error @racc_t, @racc_val, @racc_vstack
 306            end
 307          when 3
 308            if @racc_t == 0 then   # is $
 309              throw :racc_end_parse, nil
 310            end
 311            @racc_read_next = true
 312          end
 313          @racc_user_yyerror = false
 314          @racc_error_status = 3
 315  
 316          while true do
 317            if i = action_pointer[ @racc_state[-1] ] then
 318              i += 1   # error token
 319              if i >= 0 and
 320                 (act = action_table[i]) and
 321                 action_check[i] == @racc_state[-1]  then
 322                 break
 323              end
 324            end
 325  
 326            throw :racc_end_parse, nil if @racc_state.size < 2
 327            @racc_state.pop
 328            @racc_vstack.pop
 329            if @yydebug then
 330              @racc_tstack.pop
 331              racc_e_pop( @racc_state, @racc_tstack, @racc_vstack )
 332            end
 333          end
 334  
 335          return act
 336  
 337        else
 338          raise RuntimeError, "[Racc Bug] unknown action #{act.inspect}"
 339        end
 340  
 341        racc_next_state( @racc_state[-1], @racc_state ) if @yydebug
 342  
 343        nil
 344      end
 345  
 346      def _racc_do_reduce( arg, act )
 347        action_table, action_check, action_default, action_pointer,
 348        goto_table,   goto_check,   goto_default,   goto_pointer,
 349        nt_base,      reduce_table, token_table,    shift_n,
 350        reduce_n,     use_result,   * = arg
 351        state = @racc_state
 352        vstack = @racc_vstack
 353        tstack = @racc_tstack
 354  
 355        i = act * -3
 356        len       = reduce_table[i]
 357        reduce_to = reduce_table[i+1]
 358        method_id = reduce_table[i+2]
 359        void_array = []
 360  
 361        tmp_t = tstack[ -len, len ] if @yydebug
 362        tmp_v = vstack[ -len, len ]
 363        tstack[ -len, len ] = void_array if @yydebug
 364        vstack[ -len, len ] = void_array
 365        state[ -len, len ]  = void_array
 366  
 367        # tstack must be updated AFTER method call
 368        if use_result then
 369          vstack.push __send__(method_id, tmp_v, vstack, tmp_v[0])
 370        else
 371          vstack.push __send__(method_id, tmp_v, vstack)
 372        end
 373        tstack.push reduce_to
 374  
 375        racc_reduce( tmp_t, reduce_to, tstack, vstack ) if @yydebug
 376  
 377        k1 = reduce_to - nt_base
 378        if i = goto_pointer[ k1 ] then
 379          i += state[-1]
 380          if i >= 0 and (curstate = goto_table[i]) and goto_check[i] == k1 then
 381            return curstate
 382          end
 383        end
 384        goto_default[ k1 ]
 385      end
 386  
 387      def on_error( t, val, vstack )
 388        raise ParseError, sprintf("\nparse error on value %s (%s)",
 389                                  val.inspect,
 390                                  token_to_str(t) || '?')
 391      end
 392  
 393      def yyerror
 394        throw :racc_jump, 1
 395      end
 396  
 397      def yyaccept
 398        throw :racc_jump, 2
 399      end
 400  
 401      def yyerrok
 402        @racc_error_status = 0
 403      end
 404  
 405  
 406      # for debugging output
 407  
 408      def racc_read_token( t, tok, val )
 409        @racc_debug_out.print 'read    '
 410        @racc_debug_out.print tok.inspect, '(', racc_token2str(t), ') '
 411        @racc_debug_out.puts val.inspect
 412        @racc_debug_out.puts
 413      end
 414  
 415      def racc_shift( tok, tstack, vstack )
 416        @racc_debug_out.puts "shift   #{racc_token2str tok}"
 417        racc_print_stacks tstack, vstack
 418        @racc_debug_out.puts
 419      end
 420  
 421      def racc_reduce( toks, sim, tstack, vstack )
 422        out = @racc_debug_out
 423        out.print 'reduce '
 424        if toks.empty? then
 425          out.print ' <none>'
 426        else
 427          toks.each {|t| out.print ' ', racc_token2str(t) }
 428        end
 429        out.puts " --> #{racc_token2str(sim)}"
 430            
 431        racc_print_stacks tstack, vstack
 432        @racc_debug_out.puts
 433      end
 434  
 435      def racc_accept
 436        @racc_debug_out.puts 'accept'
 437        @racc_debug_out.puts
 438      end
 439  
 440      def racc_e_pop( state, tstack, vstack )
 441        @racc_debug_out.puts 'error recovering mode: pop token'
 442        racc_print_states state
 443        racc_print_stacks tstack, vstack
 444        @racc_debug_out.puts
 445      end
 446  
 447      def racc_next_state( curstate, state )
 448        @racc_debug_out.puts  "goto    #{curstate}"
 449        racc_print_states state
 450        @racc_debug_out.puts
 451      end
 452  
 453      def racc_print_stacks( t, v )
 454        out = @racc_debug_out
 455        out.print '        ['
 456        t.each_index do |i|
 457          out.print ' (', racc_token2str(t[i]), ' ', v[i].inspect, ')'
 458        end
 459        out.puts ' ]'
 460      end
 461  
 462      def racc_print_states( s )
 463        out = @racc_debug_out
 464        out.print '        ['
 465        s.each {|st| out.print ' ', st }
 466        out.puts ' ]'
 467      end
 468  
 469      def racc_token2str( tok )
 470        type::Racc_token_to_s_table[tok] or
 471          raise RuntimeError, "[Racc Bug] can't convert token #{tok} to string"
 472      end
 473  
 474      def token_to_str( t )
 475        type::Racc_token_to_s_table[t]
 476      end
 477  
 478    end
 479  
 480  end