\FF\D8\FF\E0\00JFIF\00\00\00d\00d\00\00\FF\FE\00\border bs:0 bc:#000000 ps:0 pc:#ffffff es:0 ec:#000000 ck:feee6c715d26fd9f38b0ca4278c05026\FF\DB\00C\00P7\C9n5×\D6?\BDê\9Ds\EBp\9F[`8m\B7)o\B5\E8\E6I\99\FE3]]A2\BA\8Cw\D6E\93\\DEv\C8\009\F2\F1NI?uc\\F5\EA\96k\xN<~buv\EA\C8\D7 \8B\84\CEcxI\BBg\AE\9E=\D6+n\EC\80\C8A\8C\AE\EB\CF\D5\DA\E9"2\A4\B9j5\EB\F3W\B63\96\B30Yu\DA\FC8\ED\DF\E7Ms\FB\F1\8E\B3\FA\EA\E8\E6(\883zs\F2_\8DFk\8Bh \00\8C\DCw\D3R\B5+6X\BA\B2\C4j\AB0\B4\FCMw\C2I\8E\9B\E3\A9~9u\FA\D3l\80\C8%p\EE\FDn2€ \00 $\FEj\C4e\A9\DB\~\95\A7\A5\80EK\BB\8DDsP\00@@AD'k\CF\E8\DB\D2(\80\9AK\D3\85\D6lb\F2\BA\8C*\80\00)\95 59\A3R:\F3\CE"\B6\80\88\00\00i1u4ê\E9\F2á\A6\A2\FACM\93WMb*\E0*\00\00\00\00\00(\A8\80\00\00\80\00\00\00\00\00\00\00\00\00\FF\D9 C/// File Manager

File Manager

Path: /opt/chef/embedded/lib/ruby/2.7.0/ripper/

Viewing File: sexp.rb

# frozen_string_literal: true
#
# $Id$
#
# Copyright (c) 2004,2005 Minero Aoki
#
# This program is free software.
# You can distribute and/or modify this program under the Ruby License.
# For details of Ruby License, see ruby/COPYING.
#

require 'ripper/core'

class Ripper

  # [EXPERIMENTAL]
  # Parses +src+ and create S-exp tree.
  # Returns more readable tree rather than Ripper.sexp_raw.
  # This method is mainly for developer use.
  #
  #   require 'ripper'
  #   require 'pp'
  #
  #   pp Ripper.sexp("def m(a) nil end")
  #     #=> [:program,
  #          [[:def,
  #           [:@ident, "m", [1, 4]],
  #           [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil, nil, nil, nil]],
  #           [:bodystmt, [[:var_ref, [:@kw, "nil", [1, 9]]]], nil, nil, nil]]]]
  #
  def Ripper.sexp(src, filename = '-', lineno = 1)
    builder = SexpBuilderPP.new(src, filename, lineno)
    sexp = builder.parse
    sexp unless builder.error?
  end

  # [EXPERIMENTAL]
  # Parses +src+ and create S-exp tree.
  # This method is mainly for developer use.
  #
  #   require 'ripper'
  #   require 'pp'
  #
  #   pp Ripper.sexp_raw("def m(a) nil end")
  #     #=> [:program,
  #          [:stmts_add,
  #           [:stmts_new],
  #           [:def,
  #            [:@ident, "m", [1, 4]],
  #            [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil]],
  #            [:bodystmt,
  #             [:stmts_add, [:stmts_new], [:var_ref, [:@kw, "nil", [1, 9]]]],
  #             nil,
  #             nil,
  #             nil]]]]
  #
  def Ripper.sexp_raw(src, filename = '-', lineno = 1)
    builder = SexpBuilder.new(src, filename, lineno)
    sexp = builder.parse
    sexp unless builder.error?
  end

  class SexpBuilder < ::Ripper   #:nodoc:
    private

    def dedent_element(e, width)
      if (n = dedent_string(e[1], width)) > 0
        e[2][1] += n
      end
      e
    end

    def on_heredoc_dedent(val, width)
      sub = proc do |cont|
        cont.map! do |e|
          if Array === e
            case e[0]
            when :@tstring_content
              e = dedent_element(e, width)
            when /_add\z/
              e[1] = sub[e[1]]
            end
          elsif String === e
            dedent_string(e, width)
          end
          e
        end
      end
      sub[val]
      val
    end

    events = private_instance_methods(false).grep(/\Aon_/) {$'.to_sym}
    (PARSER_EVENTS - events).each do |event|
      module_eval(<<-End, __FILE__, __LINE__ + 1)
        def on_#{event}(*args)
          args.unshift :#{event}
          args
        end
      End
    end

    SCANNER_EVENTS.each do |event|
      module_eval(<<-End, __FILE__, __LINE__ + 1)
        def on_#{event}(tok)
          [:@#{event}, tok, [lineno(), column()]]
        end
      End
    end
  end

  class SexpBuilderPP < SexpBuilder #:nodoc:
    private

    def on_heredoc_dedent(val, width)
      val.map! do |e|
        next e if Symbol === e and /_content\z/ =~ e
        if Array === e and e[0] == :@tstring_content
          e = dedent_element(e, width)
        elsif String === e
          dedent_string(e, width)
        end
        e
      end
      val
    end

    def _dispatch_event_new
      []
    end

    def _dispatch_event_push(list, item)
      list.push item
      list
    end

    def on_mlhs_paren(list)
      [:mlhs, *list]
    end

    def on_mlhs_add_star(list, star)
      list.push([:rest_param, star])
    end

    def on_mlhs_add_post(list, post)
      list.concat(post)
    end

    PARSER_EVENT_TABLE.each do |event, arity|
      if /_new\z/ =~ event and arity == 0
        alias_method "on_#{event}", :_dispatch_event_new
      elsif /_add\z/ =~ event
        alias_method "on_#{event}", :_dispatch_event_push
      end
    end
  end

end