晋太元中,武陵人捕鱼为业。缘溪行,忘路之远近。忽逢桃花林,夹岸数百步,中无杂树,芳草鲜美,落英缤纷。渔人甚异之,复前行,欲穷其林。   林尽水源,便得一山,山有小口,仿佛若有光。便舍船,从口入。初极狭,才通人。复行数十步,豁然开朗。土地平旷,屋舍俨然,有良田、美池、桑竹之属。阡陌交通,鸡犬相闻。其中往来种作,男女衣着,悉如外人。黄发垂髫,并怡然自乐。   见渔人,乃大惊,问所从来。具答之。便要还家,设酒杀鸡作食。村中闻有此人,咸来问讯。自云先世避秦时乱,率妻子邑人来此绝境,不复出焉,遂与外人间隔。问今是何世,乃不知有汉,无论魏晋。此人一一为具言所闻,皆叹惋。余人各复延至其家,皆出酒食。停数日,辞去。此中人语云:“不足为外人道也。”(间隔 一作:隔绝)   既出,得其船,便扶向路,处处志之。及郡下,诣太守,说如此。太守即遣人随其往,寻向所志,遂迷,不复得路。   南阳刘子骥,高尚士也,闻之,欣然规往。未果,寻病终。后遂无问津者。 sh-3ll

HOME


sh-3ll 1.0
DIR:/opt/alt/ruby18/lib64/ruby/1.8/irb/
Upload File :
Current File : //opt/alt/ruby18/lib64/ruby/1.8/irb/slex.rb
#
#   irb/slex.rb - simple lex analyzer
#   	$Release Version: 0.9.5$
#   	$Revision: 16857 $
#   	$Date: 2008-06-06 17:05:24 +0900 (Fri, 06 Jun 2008) $
#   	by Keiju ISHITSUKA(keiju@ruby-lang.org)
#
# --
#
#   
#

require "e2mmap"
require "irb/notifier"

module IRB
  class SLex
    @RCS_ID='-$Id: slex.rb 16857 2008-06-06 08:05:24Z knu $-'

    extend Exception2MessageMapper
    def_exception :ErrNodeNothing, "node nothing"
    def_exception :ErrNodeAlreadyExists, "node already exists"

    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: ")
    
    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
    
    #$BMW%A%'%C%/(B? 
    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)
      D_DETAIL.exec_if{D_DEATIL.printf "match end: %s:%s\n", ret, token.inspect}
      ret
    end
    
    def inspect
      format("<SLex: @head = %s>", @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
      
      def search(chrs, opt = nil)
	return self if chrs.empty?
	ch = chrs.shift
	if node = @Tree[ch]
	  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)
	      DOUT.printf(D_DETAIL, "op3: %s\n", op)
	      @postproc.call(op, chrs)
	      return ""
	    else
	      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)
	    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)
	      D_DETAIL.printf("op3: %s\n", op)
	      @postproc.call(op, io)
	    else
	      nil
	    end
	  end
	end
      end
    end
  end
end

SLex=IRB::SLex

if $0 == __FILE__
  #    Tracer.on
  case $1
  when "1"
    tr = SLex.new
    print "0: ", tr.inspect, "\n"
    tr.def_rule("=") {print "=\n"}
    print "1: ", tr.inspect, "\n"
    tr.def_rule("==") {print "==\n"}
    print "2: ", tr.inspect, "\n"
    
    print "case 1:\n"
    print tr.match("="), "\n"
    print "case 2:\n"
    print tr.match("=="), "\n"
    print "case 3:\n"
    print tr.match("=>"), "\n"
    
  when "2"
    tr = SLex.new
    print "0: ", tr.inspect, "\n"
    tr.def_rule("=") {print "=\n"}
    print "1: ", tr.inspect, "\n"
    tr.def_rule("==", proc{false}) {print "==\n"}
    print "2: ", tr.inspect, "\n"
    
    print "case 1:\n"
    print tr.match("="), "\n"
    print "case 2:\n"
    print tr.match("=="), "\n"
    print "case 3:\n"
    print tr.match("=>"), "\n"
  end
  exit
end