DEFINITIONS
This source file includes following functions.
1 #
2 # irb/slex.rb - symple lex analizer
3 # $Release Version: 0.9$
4 # $Revision: 1.4 $
5 # $Date: 2002/07/09 11:17:16 $
6 # by Keiju ISHITSUKA(keiju@ishituska.com)
7 #
8 # --
9 #
10 #
11 #
12
13 require "e2mmap"
14
15 class SLex
16 @RCS_ID='-$Id: slex.rb,v 1.4 2002/07/09 11:17:16 keiju Exp $-'
17
18 extend Exception2MessageMapper
19 def_exception :ErrNodeNothing, "node nothing"
20 def_exception :ErrNodeAlreadyExists, "node already exists"
21
22 class << self
23 attr_accessor :debug_level
24 def debug?
25 debug_level > 0
26 end
27 end
28 @debug_level = 0
29
30 def initialize
31 @head = Node.new("")
32 end
33
34 def def_rule(token, preproc = nil, postproc = nil)
35 # print node.inspect, "\n" if SLex.debug?
36 postproc = proc if iterator?
37 node = create(token, preproc, postproc)
38 end
39
40 def def_rules(*tokens)
41 if iterator?
42 p = proc
43 end
44 for token in tokens
45 def_rule(token, nil, p)
46 end
47 end
48
49 def preporc(token, proc)
50 node = search(token)
51 node.preproc=proc
52 end
53
54 def postproc(token)
55 node = search(token, proc)
56 node.postproc=proc
57 end
58
59 def search(token)
60 @head.search(token.split(
61 end
62
63 def create(token, preproc = nil, postproc = nil)
64 @head.create_subnode(token.split(
65 end
66
67 def match(token)
68 case token
69 when Array
70 when String
71 return match(token.split(
72 else
73 return @head.match_io(token)
74 end
75 ret = @head.match(token)
76 printf "match end: %s:%s", ret, token.inspect if SLex.debug?
77 ret
78 end
79
80 def inspect
81 format("<SLex: @head = %s>", @head.inspect)
82 end
83
84 #----------------------------------------------------------------------
85 #
86 # class Node -
87 #
88 #----------------------------------------------------------------------
89 class Node
90 # if postproc is nil, this node is an abstract node.
91 # if postproc is non-nil, this node is a real node.
92 def initialize(preproc = nil, postproc = nil)
93 @Tree = {}
94 @preproc = preproc
95 @postproc = postproc
96 end
97
98 attr_accessor :preproc
99 attr_accessor :postproc
100
101 def search(chrs, opt = nil)
102 return self if chrs.empty?
103 ch = chrs.shift
104 if node = @Tree[ch]
105 node.search(chrs, opt)
106 else
107 if opt
108 chrs.unshift ch
109 self.create_subnode(chrs)
110 else
111 SLex.fail ErrNodeNothing
112 end
113 end
114 end
115
116 def create_subnode(chrs, preproc = nil, postproc = nil)
117 if chrs.empty?
118 if @postproc
119 p node
120 SLex.fail ErrNodeAlreadyExists
121 else
122 print "Warn: change abstruct node to real node\n" if SLex.debug?
123 @preproc = preproc
124 @postproc = postproc
125 end
126 return self
127 end
128
129 ch = chrs.shift
130 if node = @Tree[ch]
131 if chrs.empty?
132 if node.postproc
133 p node
134 p self
135 p ch
136 p chrs
137 SLex.fail ErrNodeAlreadyExists
138 else
139 print "Warn: change abstruct node to real node\n" if SLex.debug?
140 node.preproc = preproc
141 node.postproc = postproc
142 end
143 else
144 node.create_subnode(chrs, preproc, postproc)
145 end
146 else
147 if chrs.empty?
148 node = Node.new(preproc, postproc)
149 else
150 node = Node.new
151 node.create_subnode(chrs, preproc, postproc)
152 end
153 @Tree[ch] = node
154 end
155 node
156 end
157
158 #
159 # chrs: String
160 # character array
161 # io must have getc()/ungetc(); and ungetc() must be
162 # able to be called arbitrary number of times.
163 #
164 def match(chrs, op = "")
165 print "match>: ", chrs, "op:", op, "\n" if SLex.debug?
166 if chrs.empty?
167 if @preproc.nil? || @preproc.call(op, chrs)
168 printf "op1: %s\n", op if SLex.debug?
169 @postproc.call(op, chrs)
170 else
171 nil
172 end
173 else
174 ch = chrs.shift
175 if node = @Tree[ch]
176 if ret = node.match(chrs, op+ch)
177 return ret
178 else
179 chrs.unshift ch
180 if @postproc and @preproc.nil? || @preproc.call(op, chrs)
181 printf "op2: %s\n", op.inspect if SLex.debug?
182 ret = @postproc.call(op, chrs)
183 return ret
184 else
185 return nil
186 end
187 end
188 else
189 chrs.unshift ch
190 if @postproc and @preproc.nil? || @preproc.call(op, chrs)
191 printf "op3: %s\n", op if SLex.debug?
192 @postproc.call(op, chrs)
193 return ""
194 else
195 return nil
196 end
197 end
198 end
199 end
200
201 def match_io(io, op = "")
202 if op == ""
203 ch = io.getc
204 if ch == nil
205 return nil
206 end
207 else
208 ch = io.getc_of_rests
209 end
210 if ch.nil?
211 if @preproc.nil? || @preproc.call(op, io)
212 printf "op1: %s\n", op if SLex.debug?
213 @postproc.call(op, io)
214 else
215 nil
216 end
217 else
218 if node = @Tree[ch]
219 if ret = node.match_io(io, op+ch)
220 ret
221 else
222 io.ungetc ch
223 if @postproc and @preproc.nil? || @preproc.call(op, io)
224 printf "op2: %s\n", op.inspect if SLex.debug?
225 @postproc.call(op, io)
226 else
227 nil
228 end
229 end
230 else
231 io.ungetc ch
232 if @postproc and @preproc.nil? || @preproc.call(op, io)
233 printf "op3: %s\n", op if SLex.debug?
234 @postproc.call(op, io)
235 else
236 nil
237 end
238 end
239 end
240 end
241 end
242 end
243
244 if $0 == __FILE__
245 # Tracer.on
246 case $1
247 when "1"
248 tr = SLex.new
249 print "0: ", tr.inspect, "\n"
250 tr.def_rule("=") {print "=\n"}
251 print "1: ", tr.inspect, "\n"
252 tr.def_rule("==") {print "==\n"}
253 print "2: ", tr.inspect, "\n"
254
255 print "case 1:\n"
256 print tr.match("="), "\n"
257 print "case 2:\n"
258 print tr.match("=="), "\n"
259 print "case 3:\n"
260 print tr.match("=>"), "\n"
261
262 when "2"
263 tr = SLex.new
264 print "0: ", tr.inspect, "\n"
265 tr.def_rule("=") {print "=\n"}
266 print "1: ", tr.inspect, "\n"
267 tr.def_rule("==", proc{false}) {print "==\n"}
268 print "2: ", tr.inspect, "\n"
269
270 print "case 1:\n"
271 print tr.match("="), "\n"
272 print "case 2:\n"
273 print tr.match("=="), "\n"
274 print "case 3:\n"
275 print tr.match("=>"), "\n"
276 end
277 exit
278 end