razyk 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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