diff --git a/ChangeLog b/ChangeLog index 87a7b4d6d0..2f0d794df1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +Thu Apr 14 00:20:31 2005 Keiju Ishitsuka + * bin/irb lib/irb.rb lib/irb/...: IRB 0.9.5. + Wed Apr 13 23:40:21 2005 Kouhei Sutou * lib/rss/rss.rb (RSS::VERSION): 0.1.3 -> 0.1.4. diff --git a/bin/irb b/bin/irb index 309da52161..f277bc4b69 100644 --- a/bin/irb +++ b/bin/irb @@ -1,10 +1,10 @@ #!/usr/bin/env ruby # # irb.rb - intaractive ruby -# $Release Version: 0.7.3 $ +# $Release Version: 0.9.5 $ # $Revision$ # $Date$ -# by Keiju ISHITSUKA(keiju@ishitsuka.com) +# by Keiju ISHITSUKA(keiju@ruby-lang.org) # require "irb" diff --git a/lib/irb.rb b/lib/irb.rb index 1e59d6f669..5cacbf859e 100644 --- a/lib/irb.rb +++ b/lib/irb.rb @@ -1,9 +1,9 @@ # # irb.rb - irb main module -# $Release Version: 0.9 $ +# $Release Version: 0.9.5 $ # $Revision$ # $Date$ -# by Keiju ISHITSUKA(keiju@ishitsuka.com) +# by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # @@ -88,8 +88,8 @@ module IRB # irb interpriter main routine # class Irb - def initialize(workspace = nil, input_method = nil) - @context = Context.new(self, workspace, input_method) + def initialize(workspace = nil, input_method = nil, output_method = nil) + @context = Context.new(self, workspace, input_method, output_method) @context.main.extend ExtendCommandBundle @signal_status = :IN_IRB @@ -106,6 +106,8 @@ module IRB f = @context.prompt_s elsif continue f = @context.prompt_c + elsif indent > 0 + f = @context.prompt_n else @context.prompt_i f = @context.prompt_i end diff --git a/lib/irb/cmd/chws.rb b/lib/irb/cmd/chws.rb index 84f06014ba..88585b778b 100644 --- a/lib/irb/cmd/chws.rb +++ b/lib/irb/cmd/chws.rb @@ -1,9 +1,9 @@ # # change-ws.rb - -# $Release Version: 0.9$ +# $Release Version: 0.9.5$ # $Revision$ # $Date$ -# by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd) +# by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # diff --git a/lib/irb/cmd/fork.rb b/lib/irb/cmd/fork.rb index 30024dc5e0..2866b1373b 100644 --- a/lib/irb/cmd/fork.rb +++ b/lib/irb/cmd/fork.rb @@ -1,9 +1,23 @@ +# +# fork.rb - +# $Release Version: 0.9.5 $ +# $Revision$ +# $Date$ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# + +@RCS_ID='-$Id$-' + module IRB module ExtendCommand class Fork + def new_alias_name(name, prefix = "__alias_of__", postfix = "__") + base_name = "#{prefix}#{name}#{postfix}" + all_methods = instance_methods(true) + private_instance_methods(true) + same_methods = all_methods.grep(/^#{Regexp.quote(base_name)}[0-9]*$/) + return base_name if same_methods.empty? + no = same_methods.size + while !same_methods.include?(alias_name = base_name + no) + no += 1 + end + alias_name + end + end end diff --git a/lib/irb/help.rb b/lib/irb/help.rb index eb876a6dbe..f091999bd1 100644 --- a/lib/irb/help.rb +++ b/lib/irb/help.rb @@ -1,6 +1,6 @@ # # irb/help.rb - print usase module -# $Release Version: 0.9$ +# $Release Version: 0.9.5$ # $Revision$ # $Date$ # by Keiju ISHITSUKA(keiju@ishitsuka.com) diff --git a/lib/irb/init.rb b/lib/irb/init.rb index ad53a303f8..ad46a0afdc 100644 --- a/lib/irb/init.rb +++ b/lib/irb/init.rb @@ -1,9 +1,9 @@ # # irb/init.rb - irb initialize module -# $Release Version: 0.9$ +# $Release Version: 0.9.5$ # $Revision$ # $Date$ -# by Keiju ISHITSUKA(keiju@ishitsuka.com) +# by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # @@ -54,36 +54,43 @@ module IRB @CONF[:VERBOSE] = nil @CONF[:EVAL_HISTORY] = nil + @CONF[:SAVE_HISTORY] = nil @CONF[:BACK_TRACE_LIMIT] = 16 @CONF[:PROMPT] = { :NULL => { :PROMPT_I => nil, + :PROMPT_N => nil, :PROMPT_S => nil, :PROMPT_C => nil, :RETURN => "%s\n" }, :DEFAULT => { :PROMPT_I => "%N(%m):%03n:%i> ", + :PROMPT_N => "%N(%m):%03n:%i> ", :PROMPT_S => "%N(%m):%03n:%i%l ", :PROMPT_C => "%N(%m):%03n:%i* ", :RETURN => "=> %s\n" }, :CLASSIC => { :PROMPT_I => "%N(%m):%03n:%i> ", + :PROMPT_N => "%N(%m):%03n:%i> ", :PROMPT_S => "%N(%m):%03n:%i%l ", :PROMPT_C => "%N(%m):%03n:%i* ", :RETURN => "%s\n" }, :SIMPLE => { :PROMPT_I => ">> ", + :PROMPT_N => ">> ", :PROMPT_S => nil, :PROMPT_C => "?> ", :RETURN => "=> %s\n" }, :INF_RUBY => { :PROMPT_I => "%N(%m):%03n:%i> ", +# :PROMPT_N => "%N(%m):%03n:%i> ", + :PROMPT_N => nil, :PROMPT_S => nil, :PROMPT_C => nil, :RETURN => "%s\n", @@ -91,6 +98,7 @@ module IRB }, :XMP => { :PROMPT_I => nil, + :PROMPT_N => nil, :PROMPT_S => nil, :PROMPT_C => nil, :RETURN => " ==>%s\n" @@ -183,37 +191,48 @@ module IRB end end - # enumerate possible rc files - def IRB.rc_files(rc) - yield File.expand_path("~/.irb#{rc}") if ENV.key?("HOME") - yield ".irb#{rc}" - yield "irb#{rc.sub(/\A_?/, '.')}" - yield "_irb#{rc}" - yield "$irb#{rc}" - end - # running config def IRB.run_config if @CONF[:RC] - catch(:EXIT) do - rc_files("rc") do |rc| - begin - load rc - throw :EXIT - rescue LoadError, Errno::ENOENT - rescue - print "load error: #{rc}\n" - print $!.class, ": ", $!, "\n" - for err in $@[0, $@.size - 2] - print "\t", err, "\n" - end - throw :EXIT - end + begin + load rc_file + rescue LoadError, Errno::ENOENT + rescue + print "load error: #{rc_file}\n" + print $!.class, ": ", $!, "\n" + for err in $@[0, $@.size - 2] + print "\t", err, "\n" end end end end + IRBRC_EXT = "rc" + def IRB.rc_file(ext = IRBRC_EXT) + if !@CONF[:RC_NAME_GENERATOR] + rc_file_generators do |rcgen| + @CONF[:RC_NAME_GENERATOR] ||= rcgen + if File.exist?(rcgen.call(IRBRC_EXT)) + @CONF[:RC_NAME_GENERATOR] = rcgen + break + end + end + end + @CONF[:RC_NAME_GENERATOR].call ext + end + + # enumerate possible rc-file base name generators + def IRB.rc_file_generators + if home = ENV["HOME"] + yield proc{|rc| home+"/.irb#{rc}"} + end + home = Dir.pwd + yield proc{|rc| home+"/.irb#{rc}"} + yield proc{|rc| home+"/irb#{rc.sub(/\A_?/, '.')}"} + yield proc{|rc| home+"/_irb#{rc}"} + yield proc{|rc| home+"/$irb#{rc}"} + end + # loading modules def IRB.load_modules for m in @CONF[:LOAD_MODULES] diff --git a/lib/irb/input-method.rb b/lib/irb/input-method.rb index d1fc83a975..750add767e 100644 --- a/lib/irb/input-method.rb +++ b/lib/irb/input-method.rb @@ -1,9 +1,9 @@ # -# irb/input-method.rb - input methods using irb -# $Release Version: 0.9$ +# irb/input-method.rb - input methods used irb +# $Release Version: 0.9.5$ # $Revision$ # $Date$ -# by Keiju ISHITSUKA(keiju@ishitsuka.com) +# by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # @@ -85,49 +85,12 @@ module IRB require "readline" class ReadlineInputMethod < InputMethod include Readline - - def ReadlineInputMethod.create_finalizer(hist, file) - proc do - if num = IRB.conf[:SAVE_HISTORY] and (num = num.to_i) > 0 - if hf = IRB.conf[:HISTORY_FILE] - file = File.expand_path(hf) - end - if file - open(file, 'w' ) do |f| - hist = hist.to_a - f.puts(hist[-num..-1] || hist) - end - end - end - end - end - def initialize super @line_no = 0 @line = [] @eof = false - - loader = proc {|f| f.each {|l| HISTORY << l.chomp}} - if hist = IRB.conf[:HISTORY_FILE] - hist = File.expand_path(hist) - begin - open(hist, &loader) - rescue - end - else - IRB.rc_files("_history") do |hist| - begin - open(hist, &loader) - rescue - hist = nil - else - break - end - end - end - ObjectSpace.define_finalizer(self, ReadlineInputMethod.create_finalizer(HISTORY, hist)) end def gets diff --git a/lib/irb/lc/error.rb b/lib/irb/lc/error.rb index 68a488a48a..247596b7fe 100644 --- a/lib/irb/lc/error.rb +++ b/lib/irb/lc/error.rb @@ -1,9 +1,9 @@ # # irb/lc/error.rb - -# $Release Version: 0.9$ +# $Release Version: 0.9.5$ # $Revision$ # $Date$ -# by Keiju ISHITSUKA(keiju@ishitsuka.com) +# by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # diff --git a/lib/irb/lc/help-message b/lib/irb/lc/help-message index efc00bf148..32087d113c 100644 --- a/lib/irb/lc/help-message +++ b/lib/irb/lc/help-message @@ -1,9 +1,9 @@ # # irb/lc/help-message.rb - -# $Release Version: 0.9$ +# $Release Version: 0.9.5$ # $Revision$ # $Date$ -# by Keiju ISHITSUKA(keiju@ishitsuka.com) +# by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # diff --git a/lib/irb/lc/ja/error.rb b/lib/irb/lc/ja/error.rb index e1afaf5d71..4c2fb3b839 100644 --- a/lib/irb/lc/ja/error.rb +++ b/lib/irb/lc/ja/error.rb @@ -1,9 +1,9 @@ # # irb/lc/ja/error.rb - -# $Release Version: 0.9$ +# $Release Version: 0.9.5$ # $Revision$ # $Date$ -# by Keiju ISHITSUKA(keiju@ishitsuka.com) +# by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # @@ -25,5 +25,3 @@ module IRB def_exception :CantChangeBinding, 'バインディング(%s)に変更できません.' def_exception :UndefinedPromptMode, 'プロンプトモード(%s)は定義されていません.' end - - diff --git a/lib/irb/lc/ja/help-message b/lib/irb/lc/ja/help-message index 4b710c7788..debbfe9355 100644 --- a/lib/irb/lc/ja/help-message +++ b/lib/irb/lc/ja/help-message @@ -1,9 +1,9 @@ # # irb/lc/ja/help-message.rb - -# $Release Version: 0.9$ +# $Release Version: 0.9.5$ # $Revision$ # $Date$ -# by Keiju ISHITSUKA(keiju@ishitsuka.com) +# by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # diff --git a/lib/irb/locale.rb b/lib/irb/locale.rb index 351406c2da..ddd2187680 100644 --- a/lib/irb/locale.rb +++ b/lib/irb/locale.rb @@ -1,9 +1,9 @@ # # irb/locale.rb - internationalization module -# $Release Version: 0.9$ +# $Release Version: 0.9.5$ # $Revision$ # $Date$ -# by Keiju ISHITSUKA(keiju@ishitsuka.com) +# by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # diff --git a/lib/irb/ruby-lex.rb b/lib/irb/ruby-lex.rb index e25af30546..9e055ee94a 100644 --- a/lib/irb/ruby-lex.rb +++ b/lib/irb/ruby-lex.rb @@ -1,9 +1,9 @@ # # irb/ruby-lex.rb - ruby lexcal analizer -# $Release Version: 0.9$ +# $Release Version: 0.9.5$ # $Revision$ # $Date$ -# by Keiju ISHITSUKA(keiju@ishitsuka.com) +# by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # @@ -51,13 +51,18 @@ class RubyLex @indent = 0 @indent_stack = [] + @lex_state = EXPR_BEG + @space_seen = false + @here_header = false + + @continue = false + @line = "" @skip_space = false @readed_auto_clean_up = false @exception_on_syntax_error = true + @prompt = nil - @here_header = nil - @lex_state = nil end attr_accessor :skip_space @@ -119,6 +124,7 @@ class RubyLex l.concat c break if c == "\n" end + return nil if l == "" and c.nil? l end @@ -186,7 +192,7 @@ class RubyLex end private :buf_input - def set_prompt(p=nil, &block) + def set_prompt(p = nil, &block) p = block if block_given? if p.respond_to?(:call) @prompt = p @@ -280,7 +286,7 @@ class RubyLex tk = @OP.match(self) @space_seen = tk.kind_of?(TkSPACE) rescue SyntaxError - abort if @exception_on_syntax_error + raise if @exception_on_syntax_error tk = TkError.new(@seek, @line_no, @char_no) end end while @skip_space and tk.kind_of?(TkSPACE) @@ -330,7 +336,7 @@ class RubyLex } def lex_init() - @OP = SLex.new + @OP = IRB::SLex.new @OP.def_rules("\0", "\004", "\032") do Token(TkEND_OF_SCRIPT) end @@ -429,6 +435,7 @@ class RubyLex @OP.def_rules("`") do |op, io| if @lex_state == EXPR_FNAME + @lex_state = EXPR_END Token(op) else identify_string(op) @@ -472,11 +479,13 @@ class RubyLex @OP.def_rule("+@", proc{@lex_state == EXPR_FNAME}) do |op, io| + @lex_state = EXPR_ARG Token(op) end @OP.def_rule("-@", proc{@lex_state == EXPR_FNAME}) do |op, io| + @lex_state = EXPR_ARG Token(op) end @@ -616,10 +625,12 @@ class RubyLex end @OP.def_rule("[]", proc{@lex_state == EXPR_FNAME}) do + @lex_state = EXPR_ARG Token("[]") end @OP.def_rule("[]=", proc{@lex_state == EXPR_FNAME}) do + @lex_state = EXPR_ARG Token("[]=") end @@ -790,14 +801,13 @@ class RubyLex else if @lex_state != EXPR_FNAME if ENINDENT_CLAUSE.include?(token) - # check for ``class = val''. + # check for ``class = val'' etc. valid = true case token when "class" valid = false unless peek_match?(/^\s*(<<|\w|::)/) when "def" valid = false if peek_match?(/^\s*(([+-\/*&\|^]|<<|>>|\|\||\&\&)=|\&\&|\|\|)/) -# valid = false if peek_match?(/^\s*(([+-\/*&\|^]|<<|>>|\|\||\&\&)?=|\&\&|\|\|)/) when "do" valid = false if peek_match?(/^\s*([+-\/*]?=|\*|<|>|\&)/) when *ENINDENT_CLAUSE @@ -885,7 +895,11 @@ class RubyLex end @here_header = false - while (l = gets.chomp) && (indent ? l.strip : l) != quoted + while l = gets + l = l.sub(/(:?\r)?\n\z/, '') + if (indent ? l.strip : l) == quoted + break + end end @here_header = true @@ -920,19 +934,43 @@ class RubyLex def identify_number @lex_state = EXPR_END - if ch = getc + if peek(0) == "0" && peek(1) !~ /[.eE]/ + getc if /[xX]/ =~ peek(0) ch = getc match = /[0-9a-fA-F_]/ elsif /[bB]/ =~ peek(0) ch = getc match = /[01_]/ + elsif /[oO]/ =~ peek(0) + ch = getc + match = /[0-7_]/ else match = /[0-7_]/ end + + len0 = true + non_digit = false while ch = getc - if ch !~ match + if match =~ ch + if ch == "_" + if non_digit + RubyLex.fail SyntaxError, "trailing `#{ch}' in number" + else + non_digit = ch + end + else + non_digit = false + len0 = false + end + else ungetc + if len0 + RubyLex.fail SyntaxError, "numeric literal without digits" + end + if non_digit + RubyLex.fail SyntaxError, "trailing `#{non_digit}' in number" + end break end end @@ -942,24 +980,39 @@ class RubyLex type = TkINTEGER allow_point = true allow_e = true + non_digit = false while ch = getc case ch - when /[0-9_]/ + when /[0-9]/ + non_digit = false + when "_" + non_digit = ch when allow_point && "." + if non_digit + RubyLex.fail SyntaxError, "trailing `#{non_digit}' in number" + end type = TkFLOAT if peek(0) !~ /[0-9]/ + type = TkINTEGER ungetc break end allow_point = false when allow_e && "e", allow_e && "E" + if non_digit + RubyLex.fail SyntaxError, "trailing `#{non_digit}' in number" + end type = TkFLOAT if peek(0) =~ /[+-]/ getc end allow_e = false allow_point = false + non_digit = ch else + if non_digit + RubyLex.fail SyntaxError, "trailing `#{non_digit}' in number" + end ungetc break end diff --git a/lib/irb/ruby-token.rb b/lib/irb/ruby-token.rb index 49b97e9c54..525d4df14c 100644 --- a/lib/irb/ruby-token.rb +++ b/lib/irb/ruby-token.rb @@ -1,9 +1,9 @@ # # irb/ruby-token.rb - ruby tokens -# $Release Version: 0.9$ +# $Release Version: 0.9.5$ # $Revision$ # $Date$ -# by Keiju ISHITSUKA(keiju@ishitsuka.com) +# by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # @@ -64,7 +64,7 @@ module RubyToken class TkOPASGN < TkOp def initialize(seek, line_no, char_no, op) super(seek, line_no, char_no) - op = TkReading2Token[op] unless op.kind_of?(Symbol) + op = TkReading2Token[op][0] unless op.kind_of?(Symbol) @op = op end attr :op diff --git a/lib/irb/slex.rb b/lib/irb/slex.rb index f729721a58..fd984bb947 100644 --- a/lib/irb/slex.rb +++ b/lib/irb/slex.rb @@ -1,9 +1,9 @@ # # irb/slex.rb - symple lex analizer -# $Release Version: 0.9$ +# $Release Version: 0.9.5$ # $Revision$ # $Date$ -# by Keiju ISHITSUKA(keiju@ishituska.com) +# by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # @@ -11,229 +11,234 @@ # require "e2mmap" +require "irb/notifier" -class SLex - @RCS_ID='-$Id$-' +module IRB + class SLex + @RCS_ID='-$Id$-' - extend Exception2MessageMapper - def_exception :ErrNodeNothing, "node nothing" - def_exception :ErrNodeAlreadyExists, "node already exists" + extend Exception2MessageMapper + def_exception :ErrNodeNothing, "node nothing" + def_exception :ErrNodeAlreadyExists, "node already exists" - class << self - attr_accessor :debug_level - def debug? - debug_level > 0 - end - end - @debug_level = 0 - - def initialize - @head = Node.new("") - end - - def def_rule(token, preproc = nil, postproc = nil, &block) - # print node.inspect, "\n" if SLex.debug? - postproc = block if block_given? - node = create(token, preproc, postproc) - end - - def def_rules(*tokens, &block) - if block_given? - p = block - end - for token in tokens - def_rule(token, nil, p) - end - end - - def preproc(token, proc) - node = search(token) - node.preproc=proc - end - - def postproc(token) - node = search(token, proc) - node.postproc=proc - end - - def search(token) - @head.search(token.split(//)) - end - - def create(token, preproc = nil, postproc = nil) - @head.create_subnode(token.split(//), preproc, postproc) - end - - def match(token) - case token - when Array - when String - return match(token.split(//)) - else - return @head.match_io(token) - end - ret = @head.match(token) - printf "match end: %s:%s", ret, token.inspect if SLex.debug? - ret - end - - def inspect - format("", @head.inspect) - end - - #---------------------------------------------------------------------- - # - # class Node - - # - #---------------------------------------------------------------------- - class Node - # if postproc is nil, this node is an abstract node. - # if postproc is non-nil, this node is a real node. - def initialize(preproc = nil, postproc = nil) - @Tree = {} - @preproc = preproc - @postproc = postproc - end - - attr_accessor :preproc - attr_accessor :postproc + DOUT = Notifier::def_notifier("SLex::") + D_WARN = DOUT::def_notifier(1, "Warn: ") + D_DEBUG = DOUT::def_notifier(2, "Debug: ") + D_DETAIL = DOUT::def_notifier(4, "Detail: ") - def search(chrs, opt = nil) - return self if chrs.empty? - ch = chrs.shift - if node = @Tree[ch] - node.search(chrs, opt) + DOUT.level = Notifier::D_NOMSG + + def initialize + @head = Node.new("") + end + + def def_rule(token, preproc = nil, postproc = nil, &block) + D_DETAIL.pp token + + postproc = block if block_given? + node = create(token, preproc, postproc) + end + + def def_rules(*tokens, &block) + if block_given? + p = block + end + for token in tokens + def_rule(token, nil, p) + end + end + + def preproc(token, proc) + node = search(token) + node.preproc=proc + end + + #要チェック? + def postproc(token) + node = search(token, proc) + node.postproc=proc + end + + def search(token) + @head.search(token.split(//)) + end + + def create(token, preproc = nil, postproc = nil) + @head.create_subnode(token.split(//), preproc, postproc) + end + + def match(token) + case token + when Array + when String + return match(token.split(//)) else - if opt - chrs.unshift ch - self.create_subnode(chrs) - else - SLex.fail ErrNodeNothing - end + return @head.match_io(token) end + ret = @head.match(token) + D_DETAIL.exec_if{D_DEATIL.printf "match end: %s:%s\n", ret, token.inspect} + ret end - def create_subnode(chrs, preproc = nil, postproc = nil) - if chrs.empty? - if @postproc - SLex.fail ErrNodeAlreadyExists - else - print "Warn: change abstract node to real node\n" if SLex.debug? - @preproc = preproc - @postproc = postproc - end - return self + def inspect + format("", @head.inspect) + end + + #---------------------------------------------------------------------- + # + # class Node - + # + #---------------------------------------------------------------------- + class Node + # if postproc is nil, this node is an abstract node. + # if postproc is non-nil, this node is a real node. + def initialize(preproc = nil, postproc = nil) + @Tree = {} + @preproc = preproc + @postproc = postproc end + + attr_accessor :preproc + attr_accessor :postproc - ch = chrs.shift - if node = @Tree[ch] - if chrs.empty? - if node.postproc - p node - p self - p ch - p chrs - SLex.fail ErrNodeAlreadyExists - else - print "Warn: change abstract node to real node\n" if SLex.debug? - node.preproc = preproc - node.postproc = postproc - end - else - node.create_subnode(chrs, preproc, postproc) - end - else - if chrs.empty? - node = Node.new(preproc, postproc) - else - node = Node.new - node.create_subnode(chrs, preproc, postproc) - end - @Tree[ch] = node - end - node - end - - # - # chrs: String - # character array - # io must have getc()/ungetc(); and ungetc() must be - # able to be called arbitrary number of times. - # - def match(chrs, op = "") - print "match>: ", chrs, "op:", op, "\n" if SLex.debug? - if chrs.empty? - if @preproc.nil? || @preproc.call(op, chrs) - printf "op1: %s\n", op if SLex.debug? - @postproc.call(op, chrs) - else - nil - end - else + def search(chrs, opt = nil) + return self if chrs.empty? ch = chrs.shift if node = @Tree[ch] - if ret = node.match(chrs, op+ch) - return ret + node.search(chrs, opt) + else + if opt + chrs.unshift ch + self.create_subnode(chrs) + else + SLex.fail ErrNodeNothing + end + end + end + + def create_subnode(chrs, preproc = nil, postproc = nil) + if chrs.empty? + if @postproc + D_DETAIL.pp node + SLex.fail ErrNodeAlreadyExists + else + D_DEBUG.puts "change abstract node to real node." + @preproc = preproc + @postproc = postproc + end + return self + end + + ch = chrs.shift + if node = @Tree[ch] + if chrs.empty? + if node.postproc + DebugLogger.pp node + DebugLogger.pp self + DebugLogger.pp ch + DebugLogger.pp chrs + SLex.fail ErrNodeAlreadyExists + else + D_WARN.puts "change abstract node to real node" + node.preproc = preproc + node.postproc = postproc + end + else + node.create_subnode(chrs, preproc, postproc) + end + else + if chrs.empty? + node = Node.new(preproc, postproc) + else + node = Node.new + node.create_subnode(chrs, preproc, postproc) + end + @Tree[ch] = node + end + node + end + + # + # chrs: String + # character array + # io must have getc()/ungetc(); and ungetc() must be + # able to be called arbitrary number of times. + # + def match(chrs, op = "") + D_DETAIL.print "match>: ", chrs, "op:", op, "\n" + if chrs.empty? + if @preproc.nil? || @preproc.call(op, chrs) + DOUT.printf(D_DETAIL, "op1: %s\n", op) + @postproc.call(op, chrs) + else + nil + end + else + ch = chrs.shift + if node = @Tree[ch] + if ret = node.match(chrs, op+ch) + return ret + else + chrs.unshift ch + if @postproc and @preproc.nil? || @preproc.call(op, chrs) + DOUT.printf(D_DETAIL, "op2: %s\n", op.inspect) + ret = @postproc.call(op, chrs) + return ret + else + return nil + end + end else chrs.unshift ch if @postproc and @preproc.nil? || @preproc.call(op, chrs) - printf "op2: %s\n", op.inspect if SLex.debug? - ret = @postproc.call(op, chrs) - return ret + DOUT.printf(D_DETAIL, "op3: %s\n", op) + @postproc.call(op, chrs) + return "" else return nil end end - else - chrs.unshift ch - if @postproc and @preproc.nil? || @preproc.call(op, chrs) - printf "op3: %s\n", op if SLex.debug? - @postproc.call(op, chrs) - return "" - else + end + end + + def match_io(io, op = "") + if op == "" + ch = io.getc + if ch == nil return nil end - end - end - end - - def match_io(io, op = "") - if op == "" - ch = io.getc - if ch == nil - return nil - end - else - ch = io.getc_of_rests - end - if ch.nil? - if @preproc.nil? || @preproc.call(op, io) - printf "op1: %s\n", op if SLex.debug? - @postproc.call(op, io) else - nil + ch = io.getc_of_rests end - else - if node = @Tree[ch] - if ret = node.match_io(io, op+ch) - ret + if ch.nil? + if @preproc.nil? || @preproc.call(op, io) + D_DETAIL.printf("op1: %s\n", op) + @postproc.call(op, io) + else + nil + end + else + if node = @Tree[ch] + if ret = node.match_io(io, op+ch) + ret + else + io.ungetc ch + if @postproc and @preproc.nil? || @preproc.call(op, io) + DOUT.exec_if(D_DETAIL) {printf "op2: %s\n", op.inspect} + @postproc.call(op, io) + else + nil + end + end else io.ungetc ch if @postproc and @preproc.nil? || @preproc.call(op, io) - printf "op2: %s\n", op.inspect if SLex.debug? + D_DETAIL.printf("op3: %s\n", op) @postproc.call(op, io) else nil end end - else - io.ungetc ch - if @postproc and @preproc.nil? || @preproc.call(op, io) - printf "op3: %s\n", op if SLex.debug? - @postproc.call(op, io) - else - nil - end end end end @@ -275,3 +280,4 @@ if $0 == __FILE__ end exit end + diff --git a/lib/irb/version.rb b/lib/irb/version.rb index a9e37f7e7b..28b079740a 100644 --- a/lib/irb/version.rb +++ b/lib/irb/version.rb @@ -1,6 +1,6 @@ # # irb/version.rb - irb version definition file -# $Release Version: 0.9$ +# $Release Version: 0.9.5$ # $Revision$ # $Date$ # by Keiju ISHITSUKA(keiju@ishitsuka.com) @@ -11,6 +11,6 @@ # module IRB - @RELEASE_VERSION = "0.9" - @LAST_UPDATE_DATE = "02/07/03" + @RELEASE_VERSION = "0.9.5" + @LAST_UPDATE_DATE = "05/04/13" end diff --git a/lib/irb/workspace.rb b/lib/irb/workspace.rb index 3b099b1baa..7d1794cd7b 100644 --- a/lib/irb/workspace.rb +++ b/lib/irb/workspace.rb @@ -1,9 +1,9 @@ # # irb/workspace-binding.rb - -# $Release Version: 0.9$ +# $Release Version: 0.9.5$ # $Revision$ # $Date$ -# by Keiju ISHITSUKA(keiju@ishitsuka.com) +# by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- # diff --git a/lib/irb/ws-for-case-2.rb b/lib/irb/ws-for-case-2.rb index 1c58fb7dda..afd49d23e1 100644 --- a/lib/irb/ws-for-case-2.rb +++ b/lib/irb/ws-for-case-2.rb @@ -1,9 +1,9 @@ # # irb/ws-for-case-2.rb - -# $Release Version: 0.9$ +# $Release Version: 0.9.5$ # $Revision$ # $Date$ -# by Keiju ISHITSUKA(keiju@ishitsuka.com) +# by Keiju ISHITSUKA(keiju@ruby-lang.org) # # -- #