2 # irb/slex.rb - symple lex analizer
3 # $Release Version: 0.9.5$
5 # $Date: 2007-02-12 15:01:19 -0800 (Mon, 12 Feb 2007) $
6 # by Keiju ISHITSUKA(keiju@ruby-lang.org)
14 require "irb/notifier"
18 @RCS_ID='-$Id: slex.rb 11708 2007-02-12 23:01:19Z shyouhei $-'
20 extend Exception2MessageMapper
21 def_exception :ErrNodeNothing, "node nothing"
22 def_exception :ErrNodeAlreadyExists, "node already exists"
24 DOUT = Notifier::def_notifier("SLex::")
25 D_WARN = DOUT::def_notifier(1, "Warn: ")
26 D_DEBUG = DOUT::def_notifier(2, "Debug: ")
27 D_DETAIL = DOUT::def_notifier(4, "Detail: ")
29 DOUT.level = Notifier::D_NOMSG
35 def def_rule(token, preproc = nil, postproc = nil, &block)
38 postproc = block if block_given?
39 node = create(token, preproc, postproc)
42 def def_rules(*tokens, &block)
47 def_rule(token, nil, p)
51 def preproc(token, proc)
58 node = search(token, proc)
63 @head.search(token.split(//))
66 def create(token, preproc = nil, postproc = nil)
67 @head.create_subnode(token.split(//), preproc, postproc)
74 return match(token.split(//))
76 return @head.match_io(token)
78 ret = @head.match(token)
79 D_DETAIL.exec_if{D_DEATIL.printf "match end: %s:%s\n", ret, token.inspect}
84 format("<SLex: @head = %s>", @head.inspect)
87 #----------------------------------------------------------------------
91 #----------------------------------------------------------------------
93 # if postproc is nil, this node is an abstract node.
94 # if postproc is non-nil, this node is a real node.
95 def initialize(preproc = nil, postproc = nil)
101 attr_accessor :preproc
102 attr_accessor :postproc
104 def search(chrs, opt = nil)
105 return self if chrs.empty?
108 node.search(chrs, opt)
112 self.create_subnode(chrs)
114 SLex.fail ErrNodeNothing
119 def create_subnode(chrs, preproc = nil, postproc = nil)
123 SLex.fail ErrNodeAlreadyExists
125 D_DEBUG.puts "change abstract node to real node."
140 SLex.fail ErrNodeAlreadyExists
142 D_WARN.puts "change abstract node to real node"
143 node.preproc = preproc
144 node.postproc = postproc
147 node.create_subnode(chrs, preproc, postproc)
151 node = Node.new(preproc, postproc)
154 node.create_subnode(chrs, preproc, postproc)
164 # io must have getc()/ungetc(); and ungetc() must be
165 # able to be called arbitrary number of times.
167 def match(chrs, op = "")
168 D_DETAIL.print "match>: ", chrs, "op:", op, "\n"
170 if @preproc.nil? || @preproc.call(op, chrs)
171 DOUT.printf(D_DETAIL, "op1: %s\n", op)
172 @postproc.call(op, chrs)
179 if ret = node.match(chrs, op+ch)
183 if @postproc and @preproc.nil? || @preproc.call(op, chrs)
184 DOUT.printf(D_DETAIL, "op2: %s\n", op.inspect)
185 ret = @postproc.call(op, chrs)
193 if @postproc and @preproc.nil? || @preproc.call(op, chrs)
194 DOUT.printf(D_DETAIL, "op3: %s\n", op)
195 @postproc.call(op, chrs)
204 def match_io(io, op = "")
211 ch = io.getc_of_rests
214 if @preproc.nil? || @preproc.call(op, io)
215 D_DETAIL.printf("op1: %s\n", op)
216 @postproc.call(op, io)
222 if ret = node.match_io(io, op+ch)
226 if @postproc and @preproc.nil? || @preproc.call(op, io)
227 DOUT.exec_if{D_DETAIL.printf "op2: %s\n", op.inspect}
228 @postproc.call(op, io)
235 if @postproc and @preproc.nil? || @preproc.call(op, io)
236 D_DETAIL.printf("op3: %s\n", op)
237 @postproc.call(op, io)
255 print "0: ", tr.inspect, "\n"
256 tr.def_rule("=") {print "=\n"}
257 print "1: ", tr.inspect, "\n"
258 tr.def_rule("==") {print "==\n"}
259 print "2: ", tr.inspect, "\n"
262 print tr.match("="), "\n"
264 print tr.match("=="), "\n"
266 print tr.match("=>"), "\n"
270 print "0: ", tr.inspect, "\n"
271 tr.def_rule("=") {print "=\n"}
272 print "1: ", tr.inspect, "\n"
273 tr.def_rule("==", proc{false}) {print "==\n"}
274 print "2: ", tr.inspect, "\n"
277 print tr.match("="), "\n"
279 print tr.match("=="), "\n"
281 print tr.match("=>"), "\n"