process (SexpProcessor)

    # File lib/sexp_processor.rb, line 163
      def process(exp)
        return nil if exp.nil?
        exp = self.rewrite(exp) if self.context.empty?

        unless @unsupported_checked then
          m = public_methods.grep(/^process_/) { |o| o.to_s.sub(/^process_/, '').intern }
          supported = m - (m - @unsupported)

          raise UnsupportedNodeError, "#{supported.inspect} shouldn't be in @unsupported" unless supported.empty?

          @unsupported_checked = true
        end

        result = self.expected.new

        type = exp.first
        raise "type should be a Symbol, not: #{exp.first.inspect}" unless
          Symbol === type

        self.context.unshift type

        if @debug.has_key? type then
          str = exp.inspect
          puts "// DEBUG: #{str}" if str =~ @debug[type]
        end

        exp_orig = nil
        exp_orig = exp.deep_clone if $DEBUG or
          @debug.has_key? type or @exceptions.has_key?(type)

        raise UnsupportedNodeError, "'#{type}' is not a supported node type" if
          @unsupported.include? type

        if @debug.has_key? type then
          str = exp.inspect
          puts "// DEBUG (rewritten): #{str}" if str =~ @debug[type]
        end

        # now do a pass with the real processor (or generic)
        meth = @processors[type] || @default_method
        if meth then

          if @warn_on_default and meth == @default_method then
            warn "WARNING: Using default method #{meth} for #{type}"
          end

          exp.shift if @auto_shift_type and meth != @default_method

          result = error_handler(type, exp_orig) do
            self.send(meth, exp)
          end

          raise SexpTypeError, "Result must be a #{@expected}, was #{result.class}:#{result.inspect}" unless @expected === result

          self.assert_empty(meth, exp, exp_orig) if @require_empty
        else
          unless @strict then
            until exp.empty? do
              sub_exp = exp.shift
              sub_result = nil
              if Array === sub_exp then
                sub_result = error_handler(type, exp_orig) do
                  process(sub_exp)
                end
                raise "Result is a bad type" unless Array === sub_exp
                raise "Result does not have a type in front: #{sub_exp.inspect}" unless Symbol === sub_exp.first unless sub_exp.empty?
              else
                sub_result = sub_exp
              end
              result << sub_result
            end

            # NOTE: this is costly, but we are in the generic processor
            # so we shouldn't hit it too much with RubyToC stuff at least.
            #if Sexp === exp and not exp.sexp_type.nil? then
            begin
              result.sexp_type = exp.sexp_type
            rescue Exception
              # nothing to do, on purpose
            end
          else
            msg = "Bug! Unknown node-type #{type.inspect} to #{self.class}"
            msg += " in #{exp_orig.inspect} from #{caller.inspect}" if $DEBUG
            raise UnknownNodeError, msg
          end
        end

        self.context.shift
        result
      end