#
# xpath.rb: generated by racc (runtime embedded)
#

###### racc/parser.rb

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

type.module_eval <<'..end /home/katsu/local/lib/site_ruby/racc/parser.rb modeval..id92db944ac5', '/home/katsu/local/lib/site_ruby/racc/parser.rb', 1
#
# parser.rb
#
#   Copyright (c) 1999,2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
#
#   This program is free software.
#   You can distribute/modify this program under the terms of
#   the GNU Lesser General Public License version 2 or later.
#
#   As a special exception, when this code is copied by Racc
#   into a Racc output file, you may use that output file
#   without restriction.
#

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


module Racc

  class Parser

    private


    begin
      if defined? Racc_Debug_Ruby_Parser then
        raise LoadError, 'debug ruby routine'
      end
      require 'racc/cparse'
      unless new.respond_to? :_racc_do_parse_c, true then
        raise LoadError, 'old cparse.so'
      end
      Racc_Main_Parsing_Routine = :_racc_do_parse_c
      Racc_YY_Parse_Method      = :_racc_yyparse_c
    rescue LoadError
      Racc_Main_Parsing_Routine = :_racc_do_parse_rb
      Racc_YY_Parse_Method      = :_racc_yyparse_rb
    end

    Racc_ruby_parser_version = '1.3.3'
    Racc_parser_version = Racc_ruby_parser_version

    def self.racc_runtime_type
      if Racc_Main_Parsing_Routine == :_racc_do_parse_c then
        'c'
      else
        'ruby'
      end
    end


    def _racc_setup
      t = self.type

      unless t::Racc_debug_parser then
        @yydebug = false
      end
      @yydebug = false unless defined? @yydebug

      if @yydebug then
        @racc_debug_out = $stderr unless defined? @racc_debug_out
        @racc_debug_out ||= $stderr
      end

      arg = t::Racc_arg
      if arg.size < 14 then
        arg[13] = true
      end
      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 NotImplementError, "#{self.type}\#next_token must be 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
      act = i = nil
      nerr = 0


      catch( :racc_end_parse ) {
      while true do

        if i = action_pointer[ @racc_state[-1] ] then
          if @racc_read_next then
            if @racc_t != 0 then   # $
              tok, @racc_val = next_token()
              @racc_t = (token_table[tok] or 1)   # error token
              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] then
             ;
          else
            act = action_default[ @racc_state[-1] ]
          end
        else
          act = action_default[ @racc_state[-1] ]
        end

        while act = _racc_evalact( act, arg ) do 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] ] do
          while act = _racc_evalact(
                  action_default[ @racc_state[-1] ], arg ) do end
        end

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

          i += @racc_t
          if i >= 0 and act = action_table[i] and
             action_check[i] == @racc_state[-1] then
# $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 ) do end

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

            while act = _racc_evalact( act, arg ) do 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 then
        #
        # shift
        #

        if @racc_error_status > 0 then
          @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 then
          @racc_tstack.push @racc_t
          racc_shift( @racc_t, @racc_tstack, @racc_vstack )
        end

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

        code = catch( :racc_jump ) {
          @racc_state.push _racc_do_reduce( arg, act )
          false
        }
        if code then
          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 then
        #
        # accept
        #

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

      elsif act == -reduce_n then
        #
        # error
        #

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

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

          throw :racc_end_parse, nil if @racc_state.size < 2
          @racc_state.pop
          @racc_vstack.pop
          if @yydebug then
            @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 then
        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 ] then
        i += state[-1]
        if i >= 0 and (curstate = goto_table[i]) and goto_check[i] == k1 then
          return curstate
        end
      end
      goto_default[ k1 ]
    end

    def on_error( t, val, vstack )
      raise ParseError, "\nparse error on value #{val.inspect}"
    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, '(internaly ', 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? then
        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 )
      type::Racc_token_to_s_table[tok] or
        raise RuntimeError, "[Racc Bug] can't convert token #{tok} to string"
    end

  end

end
..end /home/katsu/local/lib/site_ruby/racc/parser.rb modeval..id92db944ac5
end   # end of racc/parser.rb


#
# xpath.rb : generated by racc
#

module XPath

  class Error < StandardError ; end
  class CompileError < Error ; end
  class TypeError < Error ; end
  class NameError < Error ; end
  class ArgumentError < Error ; end
  class InvalidOperation < Error ; end


  class XPathProc

    def initialize(proc, source)
      @proc = proc
      @source = source
    end

    attr_reader :source

    def call(context)
      @proc.call context
    end

  end


  def self.compile(src, pattern = false)
    @compiler = Compiler.new unless defined? @compiler
    @compiler.compile src, pattern
  end



  module XPathObject

    def _type
      type.name.sub(/\A.*::(?:XPath)?(?=[^:]+\z)/, '')
    end
    private :_type

    def type_error(into)
      raise XPath::TypeError, "failed to convert #{_type} into #{into}"
    end
    private :type_error


    def to_str         # => to Ruby String
      type_error 'String'
    end

    def to_f           # => to Ruby Float
      type_error 'Float'
    end

    def true?          # => to Ruby Boolean
      type_error 'Boolean'
    end

    def to_ruby        # => to Ruby Object
      self
    end

    def to_predicate   # => to Ruby Float, true or false. shouldn't override.
      true?
    end


    def to_string(context)   # => to XPath String. shouldn't override.
      context.make_string to_str
    end

    def to_number(context)   # => to XPath Number. shouldn't override.
      context.make_number to_f
    end

    def to_boolean(context)  # => to XPath Boolean. shouldn't override.
      context.make_boolean true?
    end


    public

    # called from compiled XPath expression

    def ==(other)
      if other.is_a? XPathNodeSet or
          other.is_a? XPathBoolean or other.is_a? XPathNumber then
        other == self
      else
        to_str == other.to_str
      end
    end

    def <(other)
      if other.is_a? XPathNodeSet then
        other > self
      else
        to_f < other.to_f
      end
    end

    def >(other)
      if other.is_a? XPathNodeSet then
        other < self
      else
        to_f > other.to_f
      end
    end

    def <=(other)
      if other.is_a? XPathNodeSet then
        other >= self
      else
        to_f <= other.to_f
      end
    end

    def >=(other)
      if other.is_a? XPathNodeSet then
        other <= self
      else
        to_f >= other.to_f
      end
    end

    def **(other)
      type_error 'NodeSet'
    end

    def predicate(&block)
      type_error 'NodeSet'
    end

    def at(pos)
      type_error 'NodeSet'
    end

    def funcall(name)   # for XPointer
      raise XPath::NameError, "undefined function `#{name}' for #{_type}"
    end

  end




  class XPathBoolean

    include XPathObject

    class << self
      attr_reader :instance
      private :new
    end

    def to_str
      true?.to_s
    end

    # def to_f
    # def true?

    def to_ruby
      true?
    end

    def to_boolean(context)
      self
    end

    def ==(other)
      true? == other.true?
    end

  end


  class XPathTrueClass < XPathBoolean

    @instance = new

    def to_f
      1.0
    end

    def true?
      true
    end

  end


  class XPathFalseClass < XPathBoolean

    @instance = new

    def to_f
      0.0
    end

    def true?
      false
    end

  end


  XPathTrue = XPathTrueClass.instance
  XPathFalse = XPathFalseClass.instance




  class XPathNumber

    include XPathObject

    def initialize(num)
      raise ::TypeError, "must be a Float" unless num.is_a? Float
      @value = num
    end

    def to_str
      if @value.nan? then
        'NaN'
      elsif @value.infinite? then
        if @value < 0 then
          '-Infinity'
        else
          'Infinity'
        end
      else
        sprintf("%.100f", @value).gsub(/\.?0+\z/, '')    # enough?
      end
    end

    def to_f
      @value
    end

    def true?
      @value != 0.0 and not @value.nan?
    end

    def to_ruby
      to_f
    end

    def to_predicate
      to_f
    end

    def to_number(context)
      self
    end


    def ==(other)
      if other.is_a? XPathNodeSet or other.is_a? XPathBoolean then
        other == self
      else
        @value == other.to_f
      end
    end

    def +(other)
      @value += other.to_f
      self
    end

    def -(other)
      @value -= other.to_f
      self
    end

    def *(other)
      @value *= other.to_f
      self
    end

    def /(other)
      @value /= other.to_f
      self
    end

    def %(other)
      n = other.to_f
      f = @value % n
      f = -f if @value < 0
      f = -f if n < 0
      @value = f
      self
    end

    def -@
      @value = -@value
      self
    end

    def floor
      @value = @value.floor.to_f
      self
    end

    def ceil
      @value = @value.ceil.to_f
      self
    end

    def round
      f = @value
      unless f.nan? or f.infinite? then
        if f >= 0.0 then
          @value = f.round.to_f
        elsif f - f.truncate >= -0.5 then
          @value = f.ceil.to_f
        else
          @value = f.floor.to_f
        end
      end
      self
    end

  end




  class XPathString

    include XPathObject

    def initialize(str)
      raise ::TypeError, "must be a String" unless str.is_a? String
      @value = str
    end

    def to_str
      @value
    end

    def to_f
      if /\A\s*(-?\d+\.?\d*)(?:\s|\z)/ =~ @value then
        $1.to_f
      else
        0.0 / 0.0  # NaN
      end
    end

    def true?
      not @value.empty?
    end

    def to_ruby
      to_str
    end

    def to_string(context)
      self
    end


    def concat(s)
      @value = @value + s
      self
    end

    def start_with?(s)
      /\A#{Regexp.quote(s)}/ =~ @value
    end

    def contain?(s)
      /#{Regexp.quote(s)}/ =~ @value
    end

    def substring_before(s)
      if /#{Regexp.quote(s)}/ =~ @value then
        @value = $`
      else
        @value = ''
      end
      self
    end

    def substring_after(s)
      if /#{Regexp.quote(s)}/ =~ @value then
        @value = $'
      else
        @value = ''
      end
      self
    end

    def substring(start, len)
      start = start.round.to_f
      if start.infinite? or start.nan? then
        @value = ''
      elsif len then
        len = len.round.to_f
        maxlen = start + len
        len = maxlen - 1.0 if len >= maxlen
        if start <= 1.0 then
          start = 0
        else
          start = start.to_i - 1
        end
        if len.nan? or len < 1.0 then
          @value = ''
        elsif len.infinite? then
          # @value = @value[start..-1]
          /\A[\W\w]{0,#{start}}/ =~ @value
          @value = $'
        else
          # @value = @value[start, len.to_i]
          /\A[\W\w]{0,#{start}}([\W\w]{0,#{len.to_i}})/ =~ @value
          @value = $1
        end
      elsif start > 1.0 then
        # @value = @value[(start-1)..-1]
        /\A[\W\w]{0,#{start.to_i-1}}/ =~ @value
        @value = $'
      end
      raise "BUG" unless @value
      self
    end

    def size
      @value.gsub(/[^\Wa-zA-Z_\d]/, ' ').size
    end

    def normalize_space
      @value = @value.strip
      @value.gsub!(/\s+/, ' ')
      self
    end

    def translate(from, to)
      to = to.split(//)
      h = {}
      from.split(//).each_with_index { |i,n|
        h[i] = to[n] unless h.key? i
      }
      @value = @value.gsub(/[#{Regexp.quote(h.keys.join)}]/) { |s| h[s] }
      self
    end

    def replace(str)
      @value = str
      self
    end

  end





class Compiler < Racc::Parser

module_eval <<'..end xpath.ry modeval..idcc62899492', 'xpath.ry', 268

  module CompilePhaseObject

    def invoke_conv(expr, conv_method)
      return unless conv_method
      if conv_method == '.to_number' or
          conv_method == '.to_string' or
          conv_method == '.to_boolean' then
        expr.push conv_method, '(', nil, ')'
      else
        expr.push conv_method
      end
    end
    private :invoke_conv

  end


  module ConstantObject

    include CompilePhaseObject

    def to_string
      StringConstant.new to_str
    end

    def to_number
      NumberConstant.new self
    end

    def to_boolean
      if true? then
        ConstantTrue
      else
        ConstantFalse
      end
    end

  end


  module BooleanConstant

    include ConstantObject

    def value_type
      :boolean
    end

    def expr(conv_method = nil)
      if conv_method == '.to_ruby' or conv_method == '.true?' then
        [ true?.to_s ]
      else
        ret = [ nil, '.make_boolean(', true?.to_s, ')' ]
        invoke_conv ret, conv_method unless conv_method == '.to_boolean'
        ret
      end
    end

  end

  class ConstantTrueClass < XPathTrueClass
    include BooleanConstant
    @instance = new
  end

  class ConstantFalseClass < XPathFalseClass
    include BooleanConstant
    @instance = new
  end

  ConstantTrue = ConstantTrueClass.instance
  ConstantFalse = ConstantFalseClass.instance



  class NumberConstant < XPathNumber

    include ConstantObject

    def value_type
      :number
    end

    def initialize(src)
      f = src.to_f
      if src.is_a? ConstantObject and s = dump_float(f) then
        src = s
      end
      @src = [ src ]
      @precedence = 1
      super f
    end

    attr_reader :precedence
    protected :precedence

    def to_number
      self
    end


    def expr(conv_method = nil)
      @src.collect! { |i|
        if i.is_a? ConstantObject then
          i.expr '.to_f'
        else
          i
        end
      }
      expr = @src
      expr.flatten!
      @src = :draff  # for debug
      unless conv_method == '.to_ruby' or conv_method == '.to_f' then
        expr[0, 0] = [ nil, '.make_number(' ]
        expr.push(')')
        invoke_conv expr, conv_method unless conv_method == '.to_number'
      end
      expr
    end


    private

    def dump_float(f)
      if f.finite? and f == eval(s = f.to_s) then
        s
      elsif f.infinite? then
        if f > 0 then
          '(1.0 / 0.0)'
        else
          '(-1.0 / 0.0)'
        end
      elsif f.nan? then
        '(0.0 / 0.0)'
      else
        nil
      end
    end


    def concat(op, other, prec)
      @src.unshift('(').push(')') if @precedence < prec
      if other.precedence < prec then
        @src.push(op).push('(').concat(other.expr('.to_f')).push(')')
      else
        @src.push(op).concat(other.expr('.to_f'))
      end
      @precedence = prec
    end


    public

    def self.def_arithmetic_operator(op, precedence)
      module_eval <<_, __FILE__, __LINE__ + 1
      def #{op}(other)
        super other
        if s = dump_float(@value) then
          @src.clear
          @src.push s
        else
          concat ' #{op} ', other, #{precedence}
        end
        self
      end
_
    end

    def_arithmetic_operator '+', 0
    def_arithmetic_operator '-', 0
    def_arithmetic_operator '*', 1
    def_arithmetic_operator '/', 1

    class << self
      undef def_arithmetic_operator
    end

    def %(other)
      orig = @value
      super other
      if s = dump_float(@value) then
        @src.clear
        @src.push s
      else
        f = other.to_f
        other = -other if orig % f == -@value
        concat ' % ', other, 1
      end
      self
    end

    def -@
      super
      if s = dump_float(@value) then
        @src.clear
        @src.push s
      else
        if @src.size == 1 then
          @src.unshift '-'
        else
          @src.unshift('-(').push(')')
        end
        @precedence = 1
      end
      self
    end

  end



  class StringConstant < XPathString

    include ConstantObject

    def value_type
      :string
    end

    def to_string
      self
    end

    def expr(conv_method = nil)
      if conv_method == '.to_ruby' or conv_method == '.to_str' then
        [ @value.dump ]
      else
        ret = [ nil, '.make_string(', @value.dump, ')' ]
        invoke_conv ret, conv_method unless conv_method == '.to_string'
        ret
      end
    end

  end



  class Expression

    include CompilePhaseObject

    def initialize(expr)
      if expr.is_a? ConstantObject then
        @value = expr
      else
        raise "BUG" unless expr.is_a? Array
        @value = nil
        @valuetype = nil
        @expr = expr
      end
      @unary = true
    end

    attr_reader :value


    def value_type
      if @value then
        @value.value_type
      else
        @valuetype
      end
    end


    def unarize
      unless @unary then
        @expr.unshift('(').push(')')
        @unary = true
      end
      self
    end


    def self.def_comparison_operator(name, op)
      module_eval <<_, __FILE__, __LINE__ + 1
      def #{name}(other)
        if @value and other.value then
          if @value #{op} other.value then
            @value = ConstantTrue
          else
            @value = ConstantFalse
          end
          @unary = true
        else
          @expr = expr.push(' #{op} ').concat(other.expr)
          @valuetype = :ruby_boolean
          @unary = false
        end
        self
      end
_
    end

    def self.def_arithmetic_operator(*ops)
      ops.each { |op|
        module_eval <<_, __FILE__, __LINE__ + 1
        def #{op}(other)
          if @value and other.value then
            @value = @value.to_number #{op} other.value.to_number
          else
            @expr = expr('.to_number').push(' #{op} ')
            # not 'to_number', for a little speed up :-)
            @expr.concat other.expr('.to_f')
            @valuetype = :number
            @unary = false
          end
          self
        end
_
      }
    end

    def_comparison_operator 'eq',  '=='
    def_comparison_operator 'neq', '!='
    def_comparison_operator 'lt',  '<'
    def_comparison_operator 'gt',  '>'
    def_comparison_operator 'le',  '<='
    def_comparison_operator 'ge',  '>='
    def_arithmetic_operator '+', '-', '*', '/', '%'

    class << self
      undef def_comparison_operator
      undef def_arithmetic_operator
    end

    def -@
      if @value then
        @value = -@value.to_number
      else
        unarize
        @expr = expr('.to_number').unshift('-')
      end
      self
    end

    def logical_or(other)
      if @value and @value.true? then
        @value = ConstantTrue
        @unary = true
        @expr = @valuetype = nil
      else
        @expr = expr('.true?').push(' || ').concat(other.expr('.true?'))
        @valuetype = :ruby_boolean
        @unary = false
      end
      self
    end

    def logical_and(other)
      if @value and not @value.true? then
        @value = ConstantFalse
        @unary = true
        @expr = @valuetype = nil
      else
        @expr = expr('.true?').push(' && ').concat(other.expr('.true?'))
        @valuetype = :ruby_boolean
        @unary = false
      end
      self
    end

    def **(other)
      @expr = expr.push(' ** ').concat(other.expr)
      @valuetype = nil
      @unary = false
      self
    end


    def add_predicate(pred)
      unarize
      @expr = expr.concat(pred)
      @valuetype = nil
      self
    end

    def <<(other)
      path = other.expr
      path.shift  # nil
      path.shift  # .to_nodeset
      add_predicate path
    end

    def add_step(axis)
      add_predicate [ ".step(:#{axis.tr('-','_')})" ]
    end


    def expr(conv_method = nil)
      if @value then
        ret = @value.expr(conv_method)
        @value = nil
      elsif @valuetype == :ruby_boolean then
        ret = @expr
        unless conv_method == '.to_ruby' or conv_method == '.true?' then
          ret[0, 0] = [ nil, '.make_boolean(' ]
          ret.push ')'
          invoke_conv ret, conv_method unless conv_method == '.to_boolean'
        end
      elsif @valuetype == :number and conv_method == '.to_number' then
        ret = @expr
      elsif @valuetype == :string and conv_method == '.to_string' then
        ret = @expr
      elsif @valuetype == :boolean and conv_method == '.to_boolean' then
        ret = @expr
      else
        if conv_method then
          unarize
          invoke_conv @expr, conv_method
        end
        ret = @expr
      end
      @expr = :draff   # for debug
      ret
    end

  end



  class LocationPath

    include CompilePhaseObject

    def initialize
      @root = false
      @steps = []    # [ axis, [ tests ], predicates ]
    end

    attr_reader :root, :steps
    protected :root, :steps

    def absolute!
      @root = true
      self
    end


    def add_step(axis, nodetype = false, localpart = false,
                 namespace = false, predicate = nil)
      if nodetype == false and localpart == false and namespace == false then
        append_step axis, [], predicate
      else
        append_step axis, [ [ nodetype, localpart, namespace ] ], predicate
      end
      self
    end


    def <<(other)
      raise "BUG" if other.root
      other = other.steps
      other.each { |step|
        if step[0] then
          append_step(*step)
        else
          add_predicate(step[2])
        end
      }
      self
    end


    def add_predicate(pred)
      @steps.push [ nil, nil, pred ]
      self
    end


    def **(other)
      unless other.is_a? LocationPath then
        ret = nil
      else
        othersteps = other.steps
        size = @steps.size
        unless size == othersteps.size then
          othersize = othersteps.size
          if size >= othersize then
            ret = (@steps[0, othersize] == othersize and self)
          else
            ret = (othersteps[0, size] == @steps and other)
          end
        else
          last = @steps.pop
          otherlast = othersteps.pop
          if @steps == othersteps and mix_step(last, otherlast) then
            ret = self
          else
            ret = nil
          end
          @steps.push last
          othersteps.push otherlast
        end
      end
      ret or Expression.new(expr) ** other
    end


    private

    UnifiableAxes = {
      'descendant' => {
        'descendant-or-self' => 'descendant',
      },
      'descendant-or-self' => {
        'child'              => 'descendant',
        'descendant'         => 'descendant',
        'descendant-or-self' => 'descendant-or-self',
      },
      'ancestor' => {
        'ancestor-or-self'   => 'ancestor',
      },
      'ancestor-or-self' => {
        'parent'             => 'ancestor',
        'ancestor'           => 'ancestor',
        'ancestor-or-self'   => 'ancestor-or-self',
      },
      'following-sibling' => {
        'following-sibling'  => 'following-sibling',
      },
      'preceding-sibling' => {
        'preceding-sibling'  => 'preceding-sibling',
      },
      'following' => {
        'following'          => 'following',
        'following-sibling'  => 'following',
      },
      'preceding' => {
        'preceding'          => 'preceding',
        'preceding-sibling'  => 'preceding',
      },
      'child' => {
        'following-sibling'  => 'child',
        'preceding-sibling'  => 'child',
      },
    }
    UnifiableAxes.default = {}


    def append_step(axis, test, predicate)
      lastaxis, lasttest, lastpred = laststep = @steps.last
      if axis == 'self' and test.empty? then
        @steps.push [ nil, nil, predicate ] if predicate
      elsif lastaxis and lasttest.empty? and
          not lastpred and not predicate and
          w = UnifiableAxes[lastaxis][axis] then
        laststep[0] = w
        laststep[1] = test
      else
        @steps.push [ axis, test, predicate ]
      end
    end


    def mix_step(step, other)
      if step[0] and step[0] == other[0] and step[2] == other[2] then
        step[1].concat other[1]
        step
      else
        nil
      end
    end


    public

    def expr(conv_method = nil)
      if @root then
        expr = [ nil, '.root_nodeset' ]
      else
        expr = [ nil, '.to_nodeset' ]
      end
      @steps.each { |axis,test,predicate|
        if axis.nil? then   # predicate only
          expr.concat predicate
        elsif test.empty? and not predicate then
          expr.push ".select_all(:#{axis.tr('-','_')})"
        else
          expr.push ".step(:#{axis.tr('-','_')})"
          if test.empty? then
            expr.push ' { |n| n.select_all'
          else
            expr.push ' { |n| n.select { |i| '
            test.each { |nodetype,localpart,namespace|
              if nodetype then
                expr.push "i.node_type == :#{nodetype.tr('-','_')}", ' && '
              end
              if localpart then
                expr.push "i.name_localpart == #{localpart.dump}", ' && '
              end
              if namespace.nil? then
                expr.push 'i.namespace_uri.nil?', ' && '
              elsif namespace then
                namespace = namespace.dump
                expr.push('i.namespace_uri == ', nil,
                          ".get_namespace(#{namespace})", ' && ')
              end
              expr[-1] = ' or '
            }
            expr[-1] = ' }'
          end
          expr.concat predicate if predicate
          expr.push ' }'
        end
      }
      @steps = :draff   # for debug
      invoke_conv expr, conv_method
      expr
    end


    def value_type
      nil
    end

    def value
      nil
    end

    def unarize
      self
    end

    def self.redirect_to_expr(*ops)
      ops.each { |op|
        name = op
        name = op[1..-1] if op[0] == ?.
        module_eval <<_, __FILE__, __LINE__ + 1
        def #{name}(arg) ; Expression.new(expr) #{op} arg ; end
_
      }
    end

    redirect_to_expr('.eq', '.neq', '.lt', '.gt', '.le', '.ge',
                     '+', '-', '*', '/', '%', '.logical_or', '.logical_and')

    class << self
      undef redirect_to_expr
    end

    def -@
      -Expression.new(expr)
    end

  end




  Delim = '\\s\\(\\)\\[\\]\\.@,\\/\\|\\*\\+"\'=!<>:'
  Name = "[^-#{Delim}][^#{Delim}]*"

  Operator = {
    '@' => true, '::' => true, '(' => true, '[' => true,
    :MUL => true, 'and' => true, 'or' => true, 'mod' => true, 'div' => true,
    '/'  => true, '//' => true, '|'  => true, '+' => true,
    '-'  => true, '='  => true, '!=' => true, '<' => true,
    '<=' => true, '>'  => true, '>=' => true,
    ':' => false
    # ':' '*'    => '*' must not be a MultiplyOperator
    # ':' 'and'  => 'and' must be a OperatorName
  }

  NodeType = {
    'comment' => true,
    'text' => true,
    'processing-instruction' => true,
    'node' => true,
  }


  private

  def axis?(s)
    /\A[-a-zA-Z]+\z/ =~ s
  end

  def nodetype?(s)
    NodeType.key? s
  end

  def tokenize(src)
    token = []
    src.scan(/(\.\.?|\/\/?|::?|!=|[<>]=?|[-()\[\].@,|+=*])|
              ("[^"]*"|'[^']*')|(\d+\.?\d*)|
              (\$?#{Name}(?::#{Name})?)|
              \s+|./ox) { |delim,literal,number,name|  #/
      if delim then
        if delim == '*' then
          delim = :MUL if (prev = token[-1]) and not Operator.key? prev[0]
        elsif delim == '::' then
          prev = token[-1]
          if prev and prev[0] == :Name and axis? prev[1] then
            prev[0] = :AxisName
          end
        elsif delim == '(' then
          if (prev = token[-1]) and prev[0] == :Name then
            if nodetype? prev[1] then
              prev[0] = :NodeType
            else
              prev[0] = :FuncName
            end
          end
        end
        token.push [ delim, delim ]
      elsif name then
        prev = token[-1]
        if name[0] == ?$ then
          name[0,1] = ''
          token.push [ :Variable, name ]
        elsif Operator.key? name and
            (prev = token[-1]) and not Operator[prev[0]] then
          token.push [ name, name ]
        else
          token.push [ :Name, name ]
        end
      elsif number then
        number << '.0' unless number.include? ?.
        token.push [ :Number, number ]
      elsif literal then
        literal.chop!
        literal[0,1] = ''
        token.push [ :Literal, literal ]
      else
        s = $&.strip
        token.push [ s, s ] unless s.empty?
      end
    }
    token
  end


  public

  def compile(src, pattern = false)
    @token = tokenize(src)
    @token.push [ false, :end ]
    @token.each { |i| p i } if @yydebug
    @token.reverse!
    @token.push [ :PATTERN, nil ] if pattern
    @context = 'context0'
    ret = do_parse
    ret = ret.unshift("proc { |context0| ").push(" }").join
    print ">>>>\n", ret, "\n<<<<\n" if @yydebug
    XPathProc.new eval(ret), src
  end


  def initialize(debug = false)
    super()
    @yydebug = debug
  end


  private

  def next_token
    @token.pop
  end


  def is_xpointer?
    false
  end


  def on_error(*args) # tok, val, values
    raise CompileError, 'parse error'
  end


..end xpath.ry modeval..idcc62899492

##### racc 1.3.3 generates ###

racc_reduce_table = [
 0, 0, :racc_error,
 0, 39, :_reduce_1,
 1, 39, :_reduce_2,
 2, 39, :_reduce_3,
 1, 41, :_reduce_none,
 3, 41, :_reduce_5,
 3, 40, :_reduce_6,
 3, 40, :_reduce_7,
 3, 40, :_reduce_8,
 3, 40, :_reduce_9,
 3, 40, :_reduce_10,
 3, 40, :_reduce_11,
 3, 40, :_reduce_12,
 3, 40, :_reduce_13,
 3, 40, :_reduce_14,
 3, 40, :_reduce_15,
 2, 40, :_reduce_16,
 3, 40, :_reduce_17,
 3, 40, :_reduce_18,
 3, 40, :_reduce_19,
 3, 40, :_reduce_20,
 1, 40, :_reduce_none,
 1, 40, :_reduce_none,
 3, 40, :_reduce_23,
 3, 40, :_reduce_24,
 1, 43, :_reduce_25,
 3, 43, :_reduce_26,
 1, 43, :_reduce_27,
 1, 43, :_reduce_28,
 1, 43, :_reduce_29,
 2, 43, :_reduce_30,
 4, 45, :_reduce_31,
 0, 47, :_reduce_32,
 1, 47, :_reduce_33,
 3, 47, :_reduce_34,
 0, 48, :_reduce_35,
 0, 49, :_reduce_36,
 5, 46, :_reduce_37,
 1, 42, :_reduce_38,
 2, 42, :_reduce_39,
 2, 42, :_reduce_40,
 1, 42, :_reduce_none,
 1, 44, :_reduce_42,
 3, 44, :_reduce_43,
 3, 44, :_reduce_44,
 0, 51, :_reduce_45,
 0, 52, :_reduce_46,
 8, 44, :_reduce_47,
 1, 50, :_reduce_48,
 1, 50, :_reduce_49,
 3, 50, :_reduce_50,
 0, 55, :_reduce_none,
 2, 55, :_reduce_52,
 1, 54, :_reduce_53,
 1, 54, :_reduce_54,
 3, 54, :_reduce_55,
 4, 54, :_reduce_56,
 0, 56, :_reduce_none,
 1, 56, :_reduce_none,
 0, 53, :_reduce_59,
 1, 53, :_reduce_60,
 2, 53, :_reduce_none ]

racc_reduce_n = 62

racc_shift_n = 100

racc_action_table = [
    -1,    75,    87,    16,    19,    16,    19,    82,     2,     9,
    12,     9,    12,    42,    44,    47,    48,     5,     7,    10,
    14,    18,    43,    20,     1,     4,    71,     2,    84,    16,
    19,    26,    83,    47,    48,     9,    12,     7,    10,    14,
    18,    26,    20,     1,     4,    46,     2,    26,    16,    19,
    52,    49,    54,    50,     9,    12,     7,    10,    14,    18,
   -32,    20,     1,     4,   -32,     2,    88,    16,    19,    47,
    48,    47,    48,     9,    12,     7,    10,    14,    18,   -32,
    20,     1,     4,   -32,     2,    90,    16,    19,    47,    48,
    43,    79,     9,    12,     7,    10,    14,    18,    78,    20,
     1,     4,    95,     2,    26,    16,    19,    96,    37,    83,
    99,     9,    12,     7,    10,    14,    18,   nil,    20,     1,
     4,   nil,     2,   nil,    16,    19,   nil,   nil,   nil,   nil,
     9,    12,     7,    10,    14,    18,   nil,    20,     1,     4,
   nil,     2,   nil,    16,    19,   nil,   nil,   nil,   nil,     9,
    12,     7,    10,    14,    18,   nil,    20,     1,     4,   nil,
     2,   nil,    16,    19,   nil,   nil,   nil,   nil,     9,    12,
     7,    10,    14,    18,   nil,    20,     1,     4,   nil,     2,
   nil,    16,    19,   nil,   nil,   nil,   nil,     9,    12,     7,
    10,    14,    18,   nil,    20,     1,     4,   nil,     2,   nil,
    16,    19,   nil,   nil,   nil,   nil,     9,    12,     7,    10,
    14,    18,   nil,    20,     1,     4,   nil,     2,   nil,    16,
    19,   nil,   nil,   nil,   nil,     9,    12,     7,    10,    14,
    18,   nil,    20,     1,     4,   nil,     2,   nil,    16,    19,
   nil,   nil,   nil,   nil,     9,    12,     7,    10,    14,    18,
   nil,    20,     1,     4,   nil,     2,   nil,    16,    19,   nil,
   nil,   nil,   nil,     9,    12,     7,    10,    14,    18,   nil,
    20,     1,     4,   nil,     2,   nil,    16,    19,   nil,   nil,
   nil,   nil,     9,    12,     7,    10,    14,    18,   nil,    20,
     1,     4,   nil,     2,   nil,    16,    19,   nil,   nil,   nil,
   nil,     9,    12,     7,    10,    14,    18,   nil,    20,     1,
     4,   nil,     2,   nil,    16,    19,   nil,   nil,   nil,   nil,
     9,    12,     7,    10,    14,    18,   nil,    20,     1,     4,
   nil,     2,   nil,    16,    19,   nil,   nil,   nil,   nil,     9,
    12,     7,    10,    14,    18,   nil,    20,     1,     4,   nil,
     2,   nil,    16,    19,   nil,   nil,   nil,   nil,     9,    12,
     7,    10,    14,    18,   nil,    20,     1,     4,   nil,     2,
   nil,    16,    19,   nil,   nil,   nil,   nil,     9,    12,     7,
    10,    14,    18,   nil,    20,     1,     4,   nil,     2,   nil,
    16,    19,   nil,   nil,   nil,   nil,     9,    12,     7,    10,
    14,    18,   nil,    20,     1,     4,    16,    19,   nil,    16,
    19,   nil,     9,    12,   nil,     9,    12,    26,   nil,    29,
    31,    33,    35,    23,    25,    27,    28,    30,    32,    34,
    36,    24,     7,    10,     7,    10,    26,    81,    29,    31,
    33,    16,    19,    16,    19,    16,    19,     9,    12,     9,
    12,     9,    12,    26,   nil,    29,    31,    33,    35,    23,
    25,    27,    28,    30,    32,    34,    36,    24,    26,   nil,
    29,    31,    33,    35,    23,    25,    27,    28,    30,    32,
    34,    36,    24,    26,   nil,    29,    31,    33,    35,    23,
    25,    27,    28,    30,    32,    34,    36,    24,    26,   nil,
    29,    31,    33,    35,    23,    25,    27,    28,    30,    32,
    34,    36,    24,    26,   nil,    29,    31,    33,    35,    23,
    25,    27,    28,    30,    32,    34,    36,    26,   nil,    29,
    31,    33,    35,    23,    25,    27,    28,    30,    32,    34,
    26,   nil,    29,    31,    33,    35,    23,    25,    27,    28,
    30,    26,   nil,    29,    31,    33,    35,    23,    25,    27,
    28,    30,    16,    19,   -59,   -59,   nil,   -59,     9,    12,
    16,    19,   nil,   nil,   nil,   nil,     9,    12,    26,   nil,
    29,    31,    33,    35,    23,    26,   nil,    29,    31,    33,
    35,    23,    26,   nil,    29,    31,    33,    35,    23,    26,
   nil,    29,    31,    33,    35,    23,    26,   nil,    29,    31,
    33 ]

racc_action_check = [
     0,    47,    75,    48,    48,    47,    47,    54,     0,    48,
    48,    47,    47,    11,    11,    40,    40,     0,     0,     0,
     0,     0,    11,     0,     0,     0,    38,    23,    70,     0,
     0,    61,    70,    13,    13,     0,     0,    23,    23,    23,
    23,    22,    23,    23,    23,    12,    37,    63,    23,    23,
    15,    15,    21,    15,    23,    23,    37,    37,    37,    37,
    37,    37,    37,    37,    37,    94,    78,    37,    37,    41,
    41,    74,    74,    37,    37,    94,    94,    94,    94,    94,
    94,    94,    94,    94,    36,    79,    94,    94,    72,    72,
    80,    50,    94,    94,    36,    36,    36,    36,    49,    36,
    36,    36,    89,    35,    65,    36,    36,    93,     4,    97,
    98,    36,    36,    35,    35,    35,    35,   nil,    35,    35,
    35,   nil,    34,   nil,    35,    35,   nil,   nil,   nil,   nil,
    35,    35,    34,    34,    34,    34,   nil,    34,    34,    34,
   nil,    83,   nil,    34,    34,   nil,   nil,   nil,   nil,    34,
    34,    83,    83,    83,    83,   nil,    83,    83,    83,   nil,
    73,   nil,    83,    83,   nil,   nil,   nil,   nil,    83,    83,
    73,    73,    73,    73,   nil,    73,    73,    73,   nil,    33,
   nil,    73,    73,   nil,   nil,   nil,   nil,    73,    73,    33,
    33,    33,    33,   nil,    33,    33,    33,   nil,    32,   nil,
    33,    33,   nil,   nil,   nil,   nil,    33,    33,    32,    32,
    32,    32,   nil,    32,    32,    32,   nil,    18,   nil,    32,
    32,   nil,   nil,   nil,   nil,    32,    32,    18,    18,    18,
    18,   nil,    18,    18,    18,   nil,    31,   nil,    18,    18,
   nil,   nil,   nil,   nil,    18,    18,    31,    31,    31,    31,
   nil,    31,    31,    31,   nil,    30,   nil,    31,    31,   nil,
   nil,   nil,   nil,    31,    31,    30,    30,    30,    30,   nil,
    30,    30,    30,   nil,     2,   nil,    30,    30,   nil,   nil,
   nil,   nil,    30,    30,     2,     2,     2,     2,   nil,     2,
     2,     2,   nil,    29,   nil,     2,     2,   nil,   nil,   nil,
   nil,     2,     2,    29,    29,    29,    29,   nil,    29,    29,
    29,   nil,    25,   nil,    29,    29,   nil,   nil,   nil,   nil,
    29,    29,    25,    25,    25,    25,   nil,    25,    25,    25,
   nil,    26,   nil,    25,    25,   nil,   nil,   nil,   nil,    25,
    25,    26,    26,    26,    26,   nil,    26,    26,    26,   nil,
    27,   nil,    26,    26,   nil,   nil,   nil,   nil,    26,    26,
    27,    27,    27,    27,   nil,    27,    27,    27,   nil,    28,
   nil,    27,    27,   nil,   nil,   nil,   nil,    27,    27,    28,
    28,    28,    28,   nil,    28,    28,    28,   nil,    24,   nil,
    28,    28,   nil,   nil,   nil,   nil,    28,    28,    24,    24,
    24,    24,   nil,    24,    24,    24,    44,    44,   nil,    24,
    24,   nil,    44,    44,   nil,    24,    24,    53,   nil,    53,
    53,    53,    53,    53,    53,    53,    53,    53,    53,    53,
    53,    53,    71,    71,     5,     5,    67,    53,    67,    67,
    67,    42,    42,    71,    71,     5,     5,    42,    42,    71,
    71,     5,     5,     3,   nil,     3,     3,     3,     3,     3,
     3,     3,     3,     3,     3,     3,     3,     3,    69,   nil,
    69,    69,    69,    69,    69,    69,    69,    69,    69,    69,
    69,    69,    69,    92,   nil,    92,    92,    92,    92,    92,
    92,    92,    92,    92,    92,    92,    92,    92,    86,   nil,
    86,    86,    86,    86,    86,    86,    86,    86,    86,    86,
    86,    86,    86,    56,   nil,    56,    56,    56,    56,    56,
    56,    56,    56,    56,    56,    56,    56,    68,   nil,    68,
    68,    68,    68,    68,    68,    68,    68,    68,    68,    68,
    66,   nil,    66,    66,    66,    66,    66,    66,    66,    66,
    66,    64,   nil,    64,    64,    64,    64,    64,    64,    64,
    64,    64,     7,     7,     7,     7,   nil,     7,     7,     7,
    10,    10,   nil,   nil,   nil,   nil,    10,    10,    57,   nil,
    57,    57,    57,    57,    57,    60,   nil,    60,    60,    60,
    60,    60,    59,   nil,    59,    59,    59,    59,    59,    62,
   nil,    62,    62,    62,    62,    62,    55,   nil,    55,    55,
    55 ]

racc_action_pointer = [
     0,   nil,   266,   451,    87,   416,   nil,   533,   nil,   nil,
   541,    -5,     8,    15,   nil,    19,   nil,   nil,   209,   nil,
   nil,    52,    39,    19,   380,   304,   323,   342,   361,   285,
   247,   228,   190,   171,   114,    95,    76,    38,    24,   nil,
    -3,    51,   412,   nil,   377,   nil,   nil,   -24,   -26,    65,
    70,   nil,   nil,   415,     7,   604,   511,   576,   nil,   590,
   583,    29,   597,    45,   549,   102,   538,   434,   525,   466,
     6,   414,    70,   152,    53,   -19,   nil,   nil,    35,    62,
    63,   nil,   nil,   133,   nil,   nil,   496,   nil,   nil,    80,
   nil,   nil,   481,    79,    57,   nil,   nil,    83,    88,   nil ]

racc_action_default = [
   -59,   -28,   -59,    -2,   -62,   -59,   -42,   -38,   -21,   -60,
   -59,   -22,   -62,   -41,   -25,   -62,   -48,   -29,   -59,   -49,
   -27,   -62,   -16,   -59,   -59,   -59,   -59,   -59,   -59,   -59,
   -59,   -59,   -59,   -59,   -59,   -59,   -59,   -59,    -3,    -4,
   -39,   -40,   -59,   -35,   -59,   -30,   -61,   -59,   -59,   -54,
   -62,   -51,   -53,   -62,   -62,   -15,    -6,   -10,   -20,   -11,
   -12,   -17,   -13,   -18,    -8,   -19,    -9,   -14,    -7,   -33,
   -62,   -59,   -23,   -59,   -24,   -62,   -43,   -44,   -62,   -57,
   -50,   -26,   100,   -59,   -31,    -5,   -36,   -45,   -55,   -62,
   -58,   -52,   -34,   -62,   -59,   -56,   -37,   -46,   -62,   -47 ]

racc_goto_table = [
     3,    45,    22,    39,    70,    40,    76,    77,    41,    73,
    38,    93,    21,    94,    98,    51,    80,    89,    53,   nil,
   nil,   nil,   nil,    55,    56,    57,    58,    59,    60,    61,
    62,    63,    64,    65,    66,    67,    68,   nil,   nil,   nil,
    72,   nil,    74,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
   nil,    97,   nil,   nil,   nil,   nil,   nil,   nil,   nil,    85,
    91,   nil,   nil,    86,   nil,   nil,   nil,   nil,   nil,   nil,
   nil,   nil,   nil,    92 ]

racc_goto_check = [
     2,     8,     2,     4,     9,     6,    12,    12,     6,    10,
     3,    11,     1,    13,    14,    16,    17,    18,     2,   nil,
   nil,   nil,   nil,     2,     2,     2,     2,     2,     2,     2,
     2,     2,     2,     2,     2,     2,     2,   nil,   nil,   nil,
     6,   nil,     6,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,
   nil,     9,   nil,   nil,   nil,   nil,   nil,   nil,   nil,     4,
     8,   nil,   nil,     2,   nil,   nil,   nil,   nil,   nil,   nil,
   nil,   nil,   nil,     2 ]

racc_goto_pointer = [
   nil,    12,     0,     5,    -2,   nil,    -2,   nil,   -10,   -33,
   -34,   -75,   -41,   -74,   -83,   nil,     0,   -35,   -62 ]

racc_goto_default = [
   nil,   nil,    69,   nil,     8,    11,    13,    17,   nil,   nil,
   nil,   nil,     6,   nil,   nil,    15,   nil,   nil,   nil ]

racc_token_table = {
 false => 0,
 Object.new => 1,
 "|" => 2,
 :NEG => 3,
 :MUL => 4,
 "div" => 5,
 "mod" => 6,
 "+" => 7,
 "-" => 8,
 "<" => 9,
 ">" => 10,
 "<=" => 11,
 ">=" => 12,
 "=" => 13,
 "!=" => 14,
 "and" => 15,
 "or" => 16,
 :PATTERN => 17,
 "/" => 18,
 "//" => 19,
 :Variable => 20,
 "(" => 21,
 ")" => 22,
 :Literal => 23,
 :Number => 24,
 :FuncName => 25,
 "," => 26,
 "[" => 27,
 "]" => 28,
 "." => 29,
 ".." => 30,
 "*" => 31,
 :Name => 32,
 ":" => 33,
 :NodeType => 34,
 "@" => 35,
 :AxisName => 36,
 "::" => 37 }

racc_use_result_var = false

racc_nt_base = 38

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_debug_parser = false

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

 # reduce 0 omitted

module_eval <<'.,.,', 'xpath.ry', 27
  def _reduce_1( val, _values)
 []
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 30
  def _reduce_2( val, _values)
                        expr = val[0].expr('.to_ruby')
                        expr.collect! { |i| i or @context }
                        expr
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 36
  def _reduce_3( val, _values)
                        expr = val[0].expr('.to_ruby')
                        expr.collect! { |i| i or @context }
                        expr
  end
.,.,

 # reduce 4 omitted

module_eval <<'.,.,', 'xpath.ry', 43
  def _reduce_5( val, _values)
 val[0] ** val[2]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 46
  def _reduce_6( val, _values)
 val[0].logical_or val[2]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 48
  def _reduce_7( val, _values)
 val[0].logical_and val[2]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 50
  def _reduce_8( val, _values)
 val[0].eq val[2]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 52
  def _reduce_9( val, _values)
 val[0].neq val[2]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 54
  def _reduce_10( val, _values)
 val[0].lt val[2]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 56
  def _reduce_11( val, _values)
 val[0].gt val[2]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 58
  def _reduce_12( val, _values)
 val[0].le val[2]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 60
  def _reduce_13( val, _values)
 val[0].ge val[2]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 62
  def _reduce_14( val, _values)
 val[0] + val[2]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 64
  def _reduce_15( val, _values)
 val[0] - val[2]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 66
  def _reduce_16( val, _values)
 -val[1]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 68
  def _reduce_17( val, _values)
 val[0] * val[2]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 70
  def _reduce_18( val, _values)
 val[0] / val[2]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 72
  def _reduce_19( val, _values)
 val[0] % val[2]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 75
  def _reduce_20( val, _values)
                        # Why `**' is used for unionizing node-sets is that its
                        # precedence is higher than any other binary operators
                        # in Ruby.
                        val[0] ** val[2]
  end
.,.,

 # reduce 21 omitted

 # reduce 22 omitted

module_eval <<'.,.,', 'xpath.ry', 83
  def _reduce_23( val, _values)
 val[0] << val[2]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 85
  def _reduce_24( val, _values)
 val[0].add_step('descendant-or-self') << val[2]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 89
  def _reduce_25( val, _values)
                        Expression.new [ nil,'.get_variable(',val[0].dump,')' ]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 92
  def _reduce_26( val, _values)
 val[1].unarize
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 94
  def _reduce_27( val, _values)
 Expression.new StringConstant.new(val[0])
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 96
  def _reduce_28( val, _values)
 Expression.new NumberConstant.new(val[0])
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 98
  def _reduce_29( val, _values)
 Expression.new val[0]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 100
  def _reduce_30( val, _values)
 val[0].add_predicate val[1]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 104
  def _reduce_31( val, _values)
                        val[2][0,0] = [ nil, ".funcall(#{val[0].dump}" ]
                        val[2].push(')')
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 109
  def _reduce_32( val, _values)
 []
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 111
  def _reduce_33( val, _values)
 val[0].expr.unshift ', '
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 113
  def _reduce_34( val, _values)
 val[0].push(', ').concat(val[2].expr)
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 117
  def _reduce_35( val, _values)
                        c = @context
                        @context = c.succ
                        c
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 123
  def _reduce_36( val, _values)
                        c = @context
                        @context = _values[-2]
                        c
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 129
  def _reduce_37( val, _values)
                        expr = val[2]
                        valuetype = expr.value_type
                        value = expr.value
                        if valuetype == :number then
                          if value then
                            f = value.to_f
                            if f > 0 and f.truncate == f then
                              [ ".at(#{f.to_i})" ]
                            else
                              [ '.at(0)' ]   # clear
                            end
                          else
                            expr.expr('.to_f').
                              unshift('.at(').push(')')
                          end
                        elsif value then
                          if value.true? then
                            []
                          else
                            [ '.at(0)' ]   # clear
                          end
                        else
                          c = val[3]
                          if valuetype == :ruby_boolean then
                            conv = '.true?'
                          else
                            conv = '.to_predicate'
                          end
                          a = expr.expr(conv)
                          a.collect! { |i| i or c }
                          a.unshift(".predicate { |#{c}| ").push(' }')
                        end
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 164
  def _reduce_38( val, _values)
 LocationPath.new.absolute!
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 166
  def _reduce_39( val, _values)
 val[1].absolute!
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 169
  def _reduce_40( val, _values)
                        path = LocationPath.new
                        path.absolute!
                        path.add_step('descendant-or-self') << val[1]
  end
.,.,

 # reduce 41 omitted

module_eval <<'.,.,', 'xpath.ry', 176
  def _reduce_42( val, _values)
 LocationPath.new.add_step(*val[0])
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 178
  def _reduce_43( val, _values)
 val[0].add_step(*val[2])
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 181
  def _reduce_44( val, _values)
                        val[0].add_step('descendant-or-self').add_step(*val[2])
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 186
  def _reduce_45( val, _values)
                        c = @context
                        @context = c.succ
                        c
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 192
  def _reduce_46( val, _values)
                        c = @context
                        @context = _values[-2]
                        c
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 198
  def _reduce_47( val, _values)
                        on_error unless is_xpointer?
                        args = val[5]
                        c = val[6]
                        args.collect! { |i| i or c }
                        args[0] = ".funcall(#{val[2].dump}) { |#{c}| ["
                        args.push '] }'
                        val[0].add_predicate args
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 208
  def _reduce_48( val, _values)
 [ 'self', false, false, false, nil ]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 210
  def _reduce_49( val, _values)
 [ 'parent', false, false, false, nil ]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 213
  def _reduce_50( val, _values)
                        nodetest = val[1]
                        unless nodetest[0] then
                          axis = val[0]
                          if axis != 'attribute' and axis != 'namespace' then
                            nodetest[0] = 'element'
                          end
                        end
                        nodetest[0] = false if nodetest[0] == 'node'
                        nodetest.unshift(val[0]).push(val[2])
  end
.,.,

 # reduce 51 omitted

module_eval <<'.,.,', 'xpath.ry', 226
  def _reduce_52( val, _values)
 (val[0] || []).concat val[1]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 229
  def _reduce_53( val, _values)
 [ false, false, false ]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 232
  def _reduce_54( val, _values)
                        if /:/ =~ val[0] then
                          [ false, $', $` ]   #' <= for racc
                        else
                          [ false, val[0], nil ]
                        end
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 240
  def _reduce_55( val, _values)
                        on_error if /:/ =~ val[0]
                        [ false, false, val[0] ]
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 245
  def _reduce_56( val, _values)
                        nodetype = val[0]
                        arg = val[2]
                        if arg and nodetype != 'processing-instruction' then
                          raise CompileError,
                            "nodetest #{nodetype}() requires no argument"
                        end
                        [ nodetype, arg || false, false ]
  end
.,.,

 # reduce 57 omitted

 # reduce 58 omitted

module_eval <<'.,.,', 'xpath.ry', 258
  def _reduce_59( val, _values)
 'child'
  end
.,.,

module_eval <<'.,.,', 'xpath.ry', 260
  def _reduce_60( val, _values)
 'attribute'
  end
.,.,

 # reduce 61 omitted

 def _reduce_none( val, _values)
  val[0]
 end

end   # class Compiler


  #
  #   Client            NodeVisitor        a NodeAdapter        a Node
  #     |                    |                   |                 |
  #    |=|                   |                   |                 |
  #    | |--{visit(node)}-->|=|                  |                 |
  #    | |                  | |---{accept(self)}----------------->|=|
  #    | |                  |=|                  |                | |
  #    | |                   |                   |                | |
  #    | |                  |=|<------------------{on_**(self)}---|=|
  #    | |                  | |                  |                 |
  #    | |                  | |--{wrap(node)}-->|=|                |
  #    | |                  | |                 | |                |
  #    | |                  | |                 |=|                |
  #    | |<--[NodeAdapter]--|=|                  |                 |
  #    | |                   |                   |                 |
  #    | |-----{request}----------------------->|=|                |
  #    | |                   |                  | |--{request}--->|=|
  #    | |                   |                  | |               | |
  #    | |                   |                  | |<-----[Data]---|=|
  #    | |<--------------------------[Data]-----|=|                |
  #    | |                   |                   |                 |
  #    |=|                   |                   |                 |
  #     |                    |                   |                 |
  #


  class TransparentNodeVisitor

    def visit(node)
      node
    end

  end


  class NullNodeAdapter

    def node
      self
    end

    def root
      nil
    end

    def parent
      nil
    end

    def children
      []
    end

    def each_following_siblings
    end

    def each_preceding_siblings
    end

    def attributes
      []
    end

    def namespaces
      []
    end

    def index
      0
    end

    def node_type
      nil
    end

    def name_localpart
      nil
    end

    def qualified_name
      name_localpart
    end

    def namespace_uri
      nil
    end

    def string_value
      ''
    end

    def lang
      nil
    end

    def select_id(*ids)
      raise XPath::Error, "selection by ID is not supported"
    end

  end




  class AxisIterator

    def reverse_order?
      false
    end

  end


  class ReverseAxisIterator < AxisIterator

    def reverse_order?
      true
    end

  end


  class SelfIterator < AxisIterator

    def each(node, visitor)
      yield visitor.visit(node)
    end

  end


  class ChildIterator < AxisIterator

    def each(node, visitor, &block)
      visitor.visit(node).children.each { |i| yield visitor.visit(i) }
    end

  end


  class ParentIterator < AxisIterator

    def each(node, visitor)
      parent = visitor.visit(node).parent
      yield visitor.visit(parent) if parent
    end

  end


  class AncestorIterator < ReverseAxisIterator

    def each(node, visitor)
      node = visitor.visit(node).parent
      while node
        i = visitor.visit(node)
        parent = i.parent
        yield i
        node = parent
      end
    end

  end


  class AncestorOrSelfIterator < AncestorIterator

    def each(node, visitor)
      yield visitor.visit(node)
      super
    end

  end


  class DescendantIterator < AxisIterator

    def each(node, visitor)
      stack = visitor.visit(node).children.reverse
      while node = stack.pop
        i = visitor.visit(node)
        stack.concat i.children.reverse
        yield i
      end
    end

  end


  class DescendantOrSelfIterator < DescendantIterator

    def each(node, visitor)
      yield visitor.visit(node)
      super
    end

  end


  class FollowingSiblingIterator < AxisIterator

    def each(node, visitor)
      visitor.visit(node).each_following_siblings { |i|
        yield visitor.visit(i)
      }
    end

  end


  class PrecedingSiblingIterator < ReverseAxisIterator

    def each(node, visitor)
      visitor.visit(node).each_preceding_siblings { |i|
        yield visitor.visit(i)
      }
    end

  end


  class FollowingIterator < DescendantOrSelfIterator

    def each(node, visitor)
      while parent = (a = visitor.visit(node)).parent
        a.each_following_siblings { |i| super i, visitor }
        node = parent
      end
    end

  end


  class PrecedingIterator < ReverseAxisIterator

    def each(node, visitor)
      while parent = (adaptor = visitor.visit(node)).parent
        adaptor.each_preceding_siblings { |i|
          stack = visitor.visit(i).children.dup
          while node = stack.pop
            a = visitor.visit(node)
            stack.concat a.children
            yield a
          end
          yield visitor.visit(i)
        }
        node = parent
      end
    end

  end


  class AttributeIterator < AxisIterator

    def each(node, visitor)
      visitor.visit(node).attributes.each { |i| yield visitor.visit(i) }
    end

  end


  class NamespaceIterator < AxisIterator

    def each(node, visitor)
      visitor.visit(node).namespaces.each { |i| yield visitor.visit(i) }
    end

  end




  class XPathNodeSet

    class LocationStep < XPathNodeSet

      def initialize(context)
        @context = context
        @visitor = context.visitor
        @nodes = []
      end

      def set_iterator(iterator)
        @iterator = iterator
      end

      def reuse(node)
        @node = node
        @nodes.clear
      end

      def select
        @iterator.each(@node, @visitor) { |i|
          node = i.node
          @nodes.push node if yield(i)
        }
        self
      end

      def select_all
        @iterator.each(@node, @visitor) { |i| @nodes.push i.node }
        self
      end

    end


    include XPathObject

    def initialize(context, *nodes)
      @context = context.dup
      @visitor = context.visitor
      nodes.sort! { |a,b| compare_position a, b }
      @nodes = nodes
    end

    attr_reader :nodes
    protected :nodes


    def to_str
      if @nodes.empty? then
        ''
      else
        @visitor.visit(@nodes[0]).string_value
      end
    end

    def to_f
      to_string(@context).to_f
    end

    def true?
      not @nodes.empty?
    end

    def to_ruby
      @nodes
    end


    def self.def_comparison_operator(*ops)
      ops.each { |op|
        module_eval <<_, __FILE__, __LINE__ + 1
        def #{op}(other)
          if other.is_a? XPathBoolean then
            other #{op} self.to_boolean
          else
            visitor = @visitor
            str = @context.make_string('')
            ret = false
            @nodes.each { |node|
              str.replace visitor.visit(node).string_value
              break if ret = (other #{op} str)
            }
            ret
          end
        end
_
      }
    end

    def_comparison_operator '==', '<', '>', '<=', '>='

    class << self
      undef def_comparison_operator
    end

    def **(other)
      super unless other.is_a? XPathNodeSet
      merge other.nodes
      self
    end


    def count
      @nodes.size
    end

    def first
      @nodes[0]
    end

    def each(&block)
      @nodes.each(&block)
    end


    def funcall(name)   # for XPointer
      raise "BUG" unless block_given?
      func = ('f_' + name.tr('-', '_')).intern
      super unless respond_to? func, true
      size = @nodes.size
      pos = 1
      c = @context.dup
      begin
        @nodes.collect! { |node|
          c.reuse node, pos, size
          pos += 1
          args = yield(c)
          send(func, node, *args)
        }
      rescue Object::ArgumentError
        if $@[1] == "#{__FILE__}:#{__LINE__-3}:in `send'" then
          raise XPath::ArgumentError, "#{$!} for `#{name}'"
        end
        raise
      end
      self
    end


    private

    def compare_position(node1, node2)
      visitor = @visitor
      ancestors1 = []
      ancestors2 = []
      p1 = visitor.visit(node1).parent
      while p1
        ancestors1.push node1
        p1 = visitor.visit(node1 = p1).parent
      end
      p2 = visitor.visit(node2).parent
      while p2
        ancestors2.push node2
        p2 = visitor.visit(node2 = p2).parent
      end
      unless node1 == node2 then
        raise XPath::Error, "can't compare the positions of given two nodes"
      end
      n = -1
      ancestors1.reverse_each { |node1|
        node2 = ancestors2[n]
        unless node1 == node2 then
          break unless node2
          return visitor.visit(node1).index - visitor.visit(node2).index
        end
        n -= 1
      }
      ancestors1.size - ancestors2.size
    end


    def merge(other)
      if @nodes.empty? or other.empty? then
        @nodes.concat other
      elsif (n = compare_position(@nodes.last, other.first)) <= 0 then
        @nodes.pop if n == 0
        @nodes.concat other
      elsif (n = compare_position(other.last, @nodes.first)) <= 0 then
        other.pop if n == 0
        @nodes = other.concat(@nodes)
      else
        newnodes = []
        nodes = @nodes
        until nodes.empty? or other.empty?
          n = compare_position(nodes.last, other.last)
          if n > 0 then
            newnodes.push nodes.pop
          elsif n < 0 then
            newnodes.push other.pop
          else
            newnodes.push nodes.pop
            other.pop
          end
        end
        newnodes.reverse!
        @nodes.concat(other).concat(newnodes)
      end
    end


    IteratorForAxis = {
      :self               => SelfIterator.new,
      :child              => ChildIterator.new,
      :parent             => ParentIterator.new,
      :ancestor           => AncestorIterator.new,
      :ancestor_or_self   => AncestorOrSelfIterator.new,
      :descendant         => DescendantIterator.new,
      :descendant_or_self => DescendantOrSelfIterator.new,
      :following          => FollowingIterator.new,
      :preceding          => PrecedingIterator.new,
      :following_sibling  => FollowingSiblingIterator.new,
      :preceding_sibling  => PrecedingSiblingIterator.new,
      :attribute          => AttributeIterator.new,
      :namespace          => NamespaceIterator.new,
    }

    def get_iterator(axis)
      ret = IteratorForAxis[axis]
      unless ret then
        raise XPath::NameError, "invalid axis `#{axis.id2name.tr('_','-')}'"
      end
      ret
    end

    def make_location_step
      if defined? @__lstep__ then
        @__lstep__
      else
        @__lstep__ = LocationStep.new(@context)
      end
    end


    public

    def step(axis)
      iterator = get_iterator(axis)
      lstep = make_location_step
      lstep.set_iterator iterator
      oldnodes = @nodes
      @nodes = []
      oldnodes.each { |node|
        lstep.reuse node
        nodes = yield(lstep).nodes
        nodes.reverse! if iterator.reverse_order?
        merge nodes
      }
      self
    end


    def select_all(axis)
      iterator = get_iterator(axis)
      visitor = @visitor
      oldnodes = @nodes
      @nodes = []
      oldnodes.each { |start|
        nodes = []
        iterator.each(start, visitor) { |i| nodes.push i.node }
        nodes.reverse! if iterator.reverse_order?
        merge nodes
      }
      self
    end


    def predicate
      context = @context
      size = @nodes.size
      pos = 1
      result = nil
      newnodes = @nodes.reject { |node|
        context.reuse node, pos, size
        pos += 1
        result = yield(context)
        break if result.is_a? Numeric
        not result
      }
      if result.is_a? Numeric then
        at result
      else
        @nodes = newnodes
      end
      self
    end


    def at(pos)
      n = pos.to_i
      if n != pos or n <= 0 then
        node = nil
      else
        node = @nodes[n - 1]
      end
      @nodes.clear
      @nodes.push node if node
      self
    end

  end



  class Context

    def initialize(node, namespace = nil, variable = nil, visitor = nil)
      visitor = TransparentNodeVisitor.new unless visitor
      @visitor = visitor
      @node = node
      @context_position = 1
      @context_size = 1
      @variables = variable
      @namespaces = namespace || {}
    end

    attr_reader :visitor, :node, :context_position, :context_size

    def reuse(node, pos = 1, size = 1)
      @variables = nil
      @node, @context_position, @context_size = node, pos, size
    end


    def get_variable(name)
      value = @variables && @variables[name]  # value should be a XPathObjcect.
      raise XPath::NameError, "undefined variable `#{name}'" unless value
      value
    end


    PredefinedNamespace = {
      'xml' => 'http://www.w3.org/XML/1998/namespace',
    }

    def get_namespace(prefix)
      ret = @namespaces[prefix] || PredefinedNamespace[prefix]
      raise XPath::Error, "undeclared namespace `#{prefix}'" unless ret
      ret
    end


    def make_string(str)
      XPathString.new str
    end

    def make_number(num)
      XPathNumber.new num
    end

    def make_boolean(f)
      if f then
        XPathTrue
      else
        XPathFalse
      end
    end

    def make_nodeset(*nodes)
      XPathNodeSet.new(self, *nodes)
    end


    def to_nodeset
      make_nodeset @node
    end

    def root_nodeset
      make_nodeset @visitor.visit(@node).root
    end


    def funcall(name, *args)
      begin
        send('f_' + name.tr('-', '_'), *args)
      rescue Object::NameError
        if $@[0] == "#{__FILE__}:#{__LINE__-2}:in `send'" then
          raise XPath::NameError, "undefined function `#{name}'"
        end
        raise
      rescue Object::ArgumentError
        if $@[1] == "#{__FILE__}:#{__LINE__-7}:in `send'" then
          raise XPath::ArgumentError, "#{$!} for `#{name}'"
        end
        raise
      end
    end


    private

    def must(type, *args)
      args.each { |i|
        unless i.is_a? type then
          s = type.name.sub(/\A.*::(?:XPath)?(?=[^:]+\z)/, '')
          raise XPath::TypeError, "argument must be #{s}"
        end
      }
    end

    def must_be_nodeset(*args)
      must XPathNodeSet, *args
    end


    def f_last
      make_number @context_size.to_f
    end

    def f_position
      make_number @context_position.to_f
    end

    def f_count(nodeset)
      must_be_nodeset nodeset
      make_number nodeset.count.to_f
    end

    def f_id(obj)
      unless obj.is_a? XPathNodeSet then
        ids = obj.to_str.strip.split(/\s+/)
      else
        ids = []
        obj.each { |node| ids.push @visitor.visit(node).string_value }
      end
      root = @visitor.visit(@node).root
      make_nodeset(*@visitor.visit(root).select_id(*ids))
    end

    def f_local_name(nodeset = nil)
      unless nodeset then
        n = @node
      else
        must_be_nodeset nodeset
        n = nodeset.first
      end
      n = @visitor.visit(n) if n
      n = n.name_localpart if n
      n = '' unless n
      make_string n
    end

    def f_namespace_uri(nodeset = nil)
      unless nodeset then
        n = @node
      else
        must_be_nodeset nodeset
        n = nodeset.first
      end
      n = @visitor.visit(n) if n
      n = n.namespace_uri if n
      n = '' unless n
      make_string n
    end

    def f_name(nodeset = nil)
      unless nodeset then
        n = @node
      else
        must_be_nodeset nodeset
        n = nodeset.first
      end
      n = @visitor.visit(n) if n
      n = n.qualified_name if n
      n = '' unless n
      make_string n
    end


    def f_string(obj = nil)
      obj = to_nodeset unless obj
      obj.to_string self
    end

    def f_concat(str, str2, *strs)
      s = str2.to_str.dup
      strs.each { |i| s << i.to_str }
      str.to_string(self).concat(s)
    end

    def f_starts_with(str, sub)
      make_boolean str.to_string(self).start_with?(sub.to_str)
    end

    def f_contains(str, sub)
      make_boolean str.to_string(self).contain?(sub.to_str)
    end

    def f_substring_before(str, sub)
      str.to_string(self).substring_before sub.to_str
    end

    def f_substring_after(str, sub)
      str.to_string(self).substring_after sub.to_str
    end

    def f_substring(str, start, len = nil)
      len = len.to_number(self) if len
      str.to_string(self).substring start.to_number(self), len
    end

    def f_string_length(str = nil)
      if str then
        str = str.to_string(self)
      else
        str = make_string(@node.string_value)
      end
      make_number str.size.to_f
    end

    def f_normalize_space(str = nil)
      if str then
        str = str.to_string(self)
      else
        str = make_string(@node.string_value)
      end
      str.normalize_space
    end

    def f_translate(str, from, to)
      str.to_string(self).translate from.to_str, to.to_str
    end


    def f_boolean(obj)
      obj.to_boolean self
    end

    def f_not(bool)
      make_boolean(!bool.true?)
    end

    def f_true
      make_boolean true
    end

    def f_false
      make_boolean false
    end

    def f_lang(str)
      lang = @visitor.visit(@node).lang
      make_boolean(lang && /\A#{Regexp.quote(str.to_str)}(?:-|\z)/i =~ lang)
    end


    def f_number(obj = nil)
      obj = to_nodeset unless obj
      obj.to_number self
    end

    def f_sum(nodeset)
      must_be_nodeset nodeset
      sum = 0.0
      nodeset.each { |node|
        sum += make_string(@visitor.visit(node).string_value).to_f
      }
      make_number sum
    end

    def f_floor(num)
      num.to_number(self).floor
    end

    def f_ceiling(num)
      num.to_number(self).ceil
    end

    def f_round(num)
      num.to_number(self).round
    end

  end


end
