razyk 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,66 @@
1
+ require "razyk/node"
2
+
3
+ begin
4
+ require "graphviz"
5
+ rescue LoadError
6
+ end
7
+
8
+ if defined?(GraphViz)
9
+ module RazyK
10
+ module Graph
11
+ def create_node(gv, tree, ctx)
12
+ i = ctx[:index]
13
+ ctx[:index] = i + 1
14
+ if tree.to.empty?
15
+ gv.add_node("#{tree.label}#{i}", :label => tree.label.to_s)
16
+ else
17
+ gv.add_node("#{tree.label}#{i}", :shape => "point")
18
+ end
19
+ end
20
+ module_function :create_node
21
+
22
+ def graph_internal(gv, tree, node, ctx)
23
+ tree.to.each do |n|
24
+ cached = false
25
+ if ctx[:cache] and ctx[:cache][n.object_id]
26
+ gn = ctx[:cache][n.object_id]
27
+ cached = true
28
+ else
29
+ gn = create_node(gv, n, ctx)
30
+ ctx[:cache][n.object_id] = gn
31
+ end
32
+ if tree.car == n
33
+ gv.add_edge(node, gn, :color => ctx[:car_arrow_color])
34
+ else
35
+ gv.add_edge(node, gn, :color => ctx[:cdr_arrow_color])
36
+ end
37
+ unless cached
38
+ graph_internal(gv, n, gn, ctx)
39
+ end
40
+ end
41
+ end
42
+ module_function :graph_internal
43
+
44
+ #
45
+ # create GraphViz from combinator tree
46
+ #
47
+ def graph(tree, opt={})
48
+ gv = GraphViz.new("CombinatorGraph")
49
+ ctx = {
50
+ :index => 0,
51
+ :car_arrow_color => opt[:car_arrow_color] || :red,
52
+ :cdr_arrow_color => opt[:cdr_arrow_color] || :black,
53
+ :cache => (opt[:style] == :dag) ? {} : nil,
54
+ }
55
+ node = create_node(gv, tree, ctx)
56
+ graph_internal(gv, tree, node, ctx)
57
+ gv
58
+ end
59
+ module_function :graph
60
+
61
+ def tree2svg(tree, file=nil)
62
+ graph(tree).output(:svg => file)
63
+ end
64
+ end
65
+ end
66
+ end
data/lib/razyk/node.rb ADDED
@@ -0,0 +1,117 @@
1
+ module RazyK
2
+
3
+ #
4
+ # Combinator Expression is implemented as DAG (Directed Acyclic Graph)
5
+ # There is two type of node
6
+ # Combinator - leaf node which has no child node.
7
+ # express elemental combinator.
8
+ # Pair - non leaf node which always has 2 child node.
9
+ # express term of two combinators or terms
10
+ #
11
+ # ex) In pair expression like Lisp/Scheme
12
+ # "``ski" => ( ( S . K ) . I )
13
+ # "`s`ki" => ( S . ( K . I ) )
14
+ #
15
+ # S, K, I are Combinator
16
+ # (S . K) is Pair
17
+ #
18
+ class Node
19
+ def initialize(label, from=[], to=[])
20
+ @label = label
21
+ @from = []
22
+ @to = []
23
+ from.each do |f|
24
+ self.class.connect(f, self)
25
+ end
26
+ to.each do |t|
27
+ self.class.connect(self, t)
28
+ end
29
+ end
30
+ attr_reader :label, :from, :to
31
+
32
+ # create connectivity from a to b (a -> b)
33
+ # TODO: circularity check
34
+ def self.connect(a, b)
35
+ a.to.push(b)
36
+ b.from.push(a)
37
+ end
38
+
39
+ # destroy connectivity from a to b (a -x-> b)
40
+ def self.disconnect(a, b)
41
+ a.to.delete(b)
42
+ b.from.delete(a)
43
+ end
44
+
45
+ # replace parent nodes' reference of self to new_node
46
+ def replace(new_node)
47
+ @from.dup.each do |f|
48
+ f.replace_child(self, new_node)
49
+ end
50
+ end
51
+
52
+ # replace child node from a to b
53
+ def replace_child(a, b)
54
+ self.class.disconnect(self, a)
55
+ self.class.connect(self, b)
56
+ end
57
+ end
58
+
59
+ class Combinator < Node
60
+ def initialize(comb)
61
+ super(comb)
62
+ end
63
+
64
+ def to_s
65
+ @label.to_s
66
+ end
67
+ def inspect
68
+ to_s
69
+ end
70
+ end
71
+
72
+ #
73
+ # Pair has only two child node (car and cdr).
74
+ # It represent term of combinators or terms.
75
+ class Pair < Node
76
+ def initialize(car, cdr)
77
+ car = Combinator.new(car) unless car.is_a?(Node)
78
+ cdr = Combinator.new(cdr) unless cdr.is_a?(Node)
79
+ super(:Pair, [], [car, cdr])
80
+ @car = car
81
+ @cdr = cdr
82
+ end
83
+ attr_reader :car, :cdr
84
+
85
+ def car=(n)
86
+ replace_child(car, n)
87
+ end
88
+
89
+ def cdr=(n)
90
+ replace_child(cdr, n)
91
+ end
92
+
93
+ def cut_car
94
+ self.class.disconnect(self, car)
95
+ car
96
+ end
97
+
98
+ def cut_cdr
99
+ self.class.disconnect(self, cdr)
100
+ cdr
101
+ end
102
+
103
+ def replace_child(a, b)
104
+ super
105
+ @car = b if @car == a
106
+ @cdr = b if @cdr == a
107
+ @to = [@car, @cdr]
108
+ end
109
+
110
+ def to_s
111
+ "(#{@car} #{@cdr})"
112
+ end
113
+ def inspect
114
+ to_s
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,423 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by Racc 1.4.6
4
+ # from Racc grammer file "".
5
+ #
6
+
7
+ require 'racc/parser.rb'
8
+
9
+
10
+ require "razyk/node"
11
+
12
+ module RazyK
13
+ class Parser < Racc::Parser
14
+
15
+ module_eval(<<'...end parser.y/module_eval...', 'parser.y', 114)
16
+
17
+ def str2list(str)
18
+ # (K 256) means End-of-stream. RazyK String adopt it as null terminator
19
+ head = Pair.new(:K, 256)
20
+ str.unpack("C*").reverse_each do |ch|
21
+ head = Pair.new(Pair.new(:CONS, ch), head)
22
+ end
23
+ head
24
+ end
25
+
26
+ def scan
27
+ # state : EXPR/IN_COMMENT/IN_LIRETAL/IN_STRING/IN_STRING_ESC
28
+ state = :EXPR
29
+ literal = []
30
+ @lineno = 1
31
+ @buf.each_char do |ch|
32
+ @lineno += 1 if ch == "\n"
33
+ case state
34
+ when :IN_COMMENT
35
+ state = :EXPR if ch == "\n"
36
+ next
37
+ when :IN_LITERAL
38
+ if /[\w.-]/ =~ ch
39
+ literal.push(ch)
40
+ next
41
+ else
42
+ raise "empty literal at line.#{@lineno}" if literal.empty?
43
+ name = literal.join
44
+ literal.clear
45
+ yield [:LITERAL, name]
46
+ state = :EXPR
47
+ # through down
48
+ end
49
+ when :IN_STRING
50
+ if "\\" == ch
51
+ state = :IN_STRING_ESC
52
+ elsif '"' == ch
53
+ yield [:STRING, literal.join]
54
+ literal.clear
55
+ state = :EXPR
56
+ else
57
+ literal.push(ch)
58
+ end
59
+ next
60
+ when :IN_STRING_ESC
61
+ case ch
62
+ when "n"
63
+ literal.push("\n")
64
+ when "t"
65
+ literal.push("\t")
66
+ when "r"
67
+ literal.push("\r")
68
+ when "b"
69
+ literal.push("\b")
70
+ when "f"
71
+ literal.push("\f")
72
+ else
73
+ literal.push(ch)
74
+ end
75
+ state = :IN_STRING
76
+ next
77
+ end
78
+
79
+ tok = case ch
80
+ when "#"
81
+ state = :IN_COMMENT
82
+ nil
83
+ when "$"
84
+ state = :IN_LITERAL
85
+ nil
86
+ when "\""
87
+ state = :IN_STRING
88
+ nil
89
+ when "I"
90
+ [:I, ch]
91
+ when "i"
92
+ [:SMALL_I, ch]
93
+ when "K", "k"
94
+ [:K, ch]
95
+ when "S", "s"
96
+ [:S, ch]
97
+ when "`"
98
+ [:BACKSLASH, ch]
99
+ when "*"
100
+ [:ASTAR, ch]
101
+ when "("
102
+ [:LPAR, ch]
103
+ when ")"
104
+ [:RPAR, ch]
105
+ when "0"
106
+ [:ZERO, ch]
107
+ when "1"
108
+ [:ONE, ch]
109
+ end
110
+ yield tok if tok
111
+ end
112
+ if state == :IN_LITERAL and not literal.empty?
113
+ name = literal.join
114
+ literal.clear
115
+ yield [:LITERAL, name]
116
+ state = :EXPR
117
+ end
118
+ yield [false, nil]
119
+ end
120
+
121
+ def parse(str, opt={})
122
+ @buf = str
123
+ @jot = []
124
+ yyparse self, :scan
125
+ end
126
+
127
+ def self.parse(str, opt={})
128
+ self.new.parse(str)
129
+ end
130
+ ...end parser.y/module_eval...
131
+ ##### State transition tables begin ###
132
+
133
+ racc_action_table = [
134
+ 7, 8, 9, 5, 11, 12, 13, 29, 16, 17,
135
+ 14, 15, 7, 8, 9, 5, 11, 12, 13, 18,
136
+ 16, 17, 14, 15, 7, 8, 9, 20, 11, 12,
137
+ 13, 3, 16, 17, 14, 15, 7, 8, 9, 5,
138
+ 11, 12, 13, nil, 16, 17, 14, 15, 7, 8,
139
+ 9, 20, 11, 12, 13, nil, 16, 17, 14, 15,
140
+ 7, 8, 9, 5, 11, 12, 13, nil, 16, 17,
141
+ 14, 15, 16, 17, 16, 17 ]
142
+
143
+ racc_action_check = [
144
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
145
+ 23, 23, 2, 2, 2, 2, 2, 2, 2, 3,
146
+ 2, 2, 2, 2, 22, 22, 22, 22, 22, 22,
147
+ 22, 1, 22, 22, 22, 22, 19, 19, 19, 19,
148
+ 19, 19, 19, nil, 19, 19, 19, 19, 12, 12,
149
+ 12, 12, 12, 12, 12, nil, 12, 12, 12, 12,
150
+ 11, 11, 11, 11, 11, 11, 11, nil, 11, 11,
151
+ 11, 11, 17, 17, 16, 16 ]
152
+
153
+ racc_action_pointer = [
154
+ nil, 31, 10, 19, nil, nil, nil, nil, nil, nil,
155
+ nil, 58, 46, nil, nil, nil, 64, 62, nil, 34,
156
+ nil, nil, 22, -2, nil, nil, nil, nil, nil, nil ]
157
+
158
+ racc_action_default = [
159
+ -2, -21, -1, -21, -3, -4, -5, -8, -9, -10,
160
+ -11, -21, -21, -2, -15, -16, -20, -20, 30, -21,
161
+ -6, -7, -21, -21, -17, -19, -18, -12, -13, -14 ]
162
+
163
+ racc_goto_table = [
164
+ 2, 21, 22, 25, 25, 1, 19, 24, 26, nil,
165
+ nil, 21, 28, 23, 27 ]
166
+
167
+ racc_goto_check = [
168
+ 2, 4, 5, 6, 6, 1, 3, 7, 7, nil,
169
+ nil, 4, 5, 2, 3 ]
170
+
171
+ racc_goto_pointer = [
172
+ nil, 5, 0, -5, -11, -10, -13, -9 ]
173
+
174
+ racc_goto_default = [
175
+ nil, nil, nil, 4, 6, nil, 10, nil ]
176
+
177
+ racc_reduce_table = [
178
+ 0, 0, :racc_error,
179
+ 1, 15, :_reduce_1,
180
+ 0, 16, :_reduce_2,
181
+ 2, 16, :_reduce_3,
182
+ 1, 17, :_reduce_4,
183
+ 1, 17, :_reduce_none,
184
+ 1, 19, :_reduce_6,
185
+ 1, 19, :_reduce_none,
186
+ 1, 18, :_reduce_8,
187
+ 1, 18, :_reduce_9,
188
+ 1, 18, :_reduce_10,
189
+ 1, 18, :_reduce_11,
190
+ 3, 18, :_reduce_12,
191
+ 3, 18, :_reduce_13,
192
+ 3, 18, :_reduce_14,
193
+ 1, 18, :_reduce_15,
194
+ 1, 18, :_reduce_16,
195
+ 2, 20, :_reduce_17,
196
+ 2, 20, :_reduce_18,
197
+ 1, 21, :_reduce_none,
198
+ 0, 21, :_reduce_none ]
199
+
200
+ racc_reduce_n = 21
201
+
202
+ racc_shift_n = 30
203
+
204
+ racc_token_table = {
205
+ false => 0,
206
+ :error => 1,
207
+ :I => 2,
208
+ :K => 3,
209
+ :S => 4,
210
+ :SMALL_I => 5,
211
+ :BACKSLASH => 6,
212
+ :ASTAR => 7,
213
+ :LPAR => 8,
214
+ :RPAR => 9,
215
+ :ZERO => 10,
216
+ :ONE => 11,
217
+ :LITERAL => 12,
218
+ :STRING => 13 }
219
+
220
+ racc_nt_base = 14
221
+
222
+ racc_use_result_var = true
223
+
224
+ Racc_arg = [
225
+ racc_action_table,
226
+ racc_action_check,
227
+ racc_action_default,
228
+ racc_action_pointer,
229
+ racc_goto_table,
230
+ racc_goto_check,
231
+ racc_goto_default,
232
+ racc_goto_pointer,
233
+ racc_nt_base,
234
+ racc_reduce_table,
235
+ racc_token_table,
236
+ racc_shift_n,
237
+ racc_reduce_n,
238
+ racc_use_result_var ]
239
+
240
+ Racc_token_to_s_table = [
241
+ "$end",
242
+ "error",
243
+ "I",
244
+ "K",
245
+ "S",
246
+ "SMALL_I",
247
+ "BACKSLASH",
248
+ "ASTAR",
249
+ "LPAR",
250
+ "RPAR",
251
+ "ZERO",
252
+ "ONE",
253
+ "LITERAL",
254
+ "STRING",
255
+ "$start",
256
+ "program",
257
+ "ccexpr",
258
+ "expr",
259
+ "expr2",
260
+ "iotaexpr",
261
+ "no_empty_jot_expr",
262
+ "jot_expr" ]
263
+
264
+ Racc_debug_parser = false
265
+
266
+ ##### State transition tables end #####
267
+
268
+ # reduce 0 omitted
269
+
270
+ module_eval(<<'.,.,', 'parser.y', 16)
271
+ def _reduce_1(val, _values, result)
272
+ result = val[0] || Combinator.new(:I)
273
+
274
+ result
275
+ end
276
+ .,.,
277
+
278
+ module_eval(<<'.,.,', 'parser.y', 22)
279
+ def _reduce_2(val, _values, result)
280
+ result = nil
281
+
282
+ result
283
+ end
284
+ .,.,
285
+
286
+ module_eval(<<'.,.,', 'parser.y', 26)
287
+ def _reduce_3(val, _values, result)
288
+ if val[0].nil?
289
+ result = val[1]
290
+ else
291
+ result = Pair.new(val[0], val[1])
292
+ end
293
+
294
+ result
295
+ end
296
+ .,.,
297
+
298
+ module_eval(<<'.,.,', 'parser.y', 36)
299
+ def _reduce_4(val, _values, result)
300
+ result = Combinator.new(:I)
301
+
302
+ result
303
+ end
304
+ .,.,
305
+
306
+ # reduce 5 omitted
307
+
308
+ module_eval(<<'.,.,', 'parser.y', 43)
309
+ def _reduce_6(val, _values, result)
310
+ result = Combinator.new(:IOTA)
311
+
312
+ result
313
+ end
314
+ .,.,
315
+
316
+ # reduce 7 omitted
317
+
318
+ module_eval(<<'.,.,', 'parser.y', 50)
319
+ def _reduce_8(val, _values, result)
320
+ result = Combinator.new(:I)
321
+
322
+ result
323
+ end
324
+ .,.,
325
+
326
+ module_eval(<<'.,.,', 'parser.y', 54)
327
+ def _reduce_9(val, _values, result)
328
+ result = Combinator.new(:K)
329
+
330
+ result
331
+ end
332
+ .,.,
333
+
334
+ module_eval(<<'.,.,', 'parser.y', 58)
335
+ def _reduce_10(val, _values, result)
336
+ result = Combinator.new(:S)
337
+
338
+ result
339
+ end
340
+ .,.,
341
+
342
+ module_eval(<<'.,.,', 'parser.y', 62)
343
+ def _reduce_11(val, _values, result)
344
+ comb = Combinator.new(:I)
345
+ @jot.reverse_each do |i|
346
+ case i
347
+ when 0
348
+ comb = Pair.new(Pair.new(comb, :S), :K)
349
+ when 1
350
+ comb = Pair.new(:S, Pair.new(:K, comb))
351
+ end
352
+ end
353
+ @jot.clear
354
+ result = comb
355
+
356
+ result
357
+ end
358
+ .,.,
359
+
360
+ module_eval(<<'.,.,', 'parser.y', 76)
361
+ def _reduce_12(val, _values, result)
362
+ result = Pair.new(val[1], val[2])
363
+
364
+ result
365
+ end
366
+ .,.,
367
+
368
+ module_eval(<<'.,.,', 'parser.y', 80)
369
+ def _reduce_13(val, _values, result)
370
+ result = Pair.new(val[1], val[2])
371
+
372
+ result
373
+ end
374
+ .,.,
375
+
376
+ module_eval(<<'.,.,', 'parser.y', 84)
377
+ def _reduce_14(val, _values, result)
378
+ result = val[1]
379
+
380
+ result
381
+ end
382
+ .,.,
383
+
384
+ module_eval(<<'.,.,', 'parser.y', 88)
385
+ def _reduce_15(val, _values, result)
386
+ result = Combinator.new(val[0].to_sym)
387
+
388
+ result
389
+ end
390
+ .,.,
391
+
392
+ module_eval(<<'.,.,', 'parser.y', 92)
393
+ def _reduce_16(val, _values, result)
394
+ result = str2list(val[0])
395
+
396
+ result
397
+ end
398
+ .,.,
399
+
400
+ module_eval(<<'.,.,', 'parser.y', 97)
401
+ def _reduce_17(val, _values, result)
402
+ @jot.push(0)
403
+ result
404
+ end
405
+ .,.,
406
+
407
+ module_eval(<<'.,.,', 'parser.y', 99)
408
+ def _reduce_18(val, _values, result)
409
+ @jot.push(1)
410
+ result
411
+ end
412
+ .,.,
413
+
414
+ # reduce 19 omitted
415
+
416
+ # reduce 20 omitted
417
+
418
+ def _reduce_none(val, _values, result)
419
+ val[0]
420
+ end
421
+
422
+ end # class Parser
423
+ end # module RazyK