depager 0.2.3 → 0.3.0.b20160729

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.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/README.en +4 -19
  3. data/README.ja +42 -79
  4. data/bin/depager +42 -45
  5. data/examples/action_pl0d/pl0d.action.dr +421 -0
  6. data/examples/action_pl0d/test.pl0ds +49 -0
  7. data/examples/c89/c89.dr +493 -496
  8. data/examples/c89/test.c89 +10 -10
  9. data/examples/extension/astdf.rb +10 -0
  10. data/examples/extension/atree.dr +55 -0
  11. data/examples/{sample_calc → extension}/calc.atree.dr +42 -43
  12. data/examples/extension/calc.simple_action.dr +33 -0
  13. data/examples/extension/paction.dr +16 -15
  14. data/examples/extension/pactiontest.dr +14 -14
  15. data/examples/extension/simple_action.rb +44 -0
  16. data/examples/pl0d/pl0ds.dr +337 -334
  17. data/examples/pl0d/test.pl0ds +33 -33
  18. data/examples/rie_calc/calc.rie.dr +57 -0
  19. data/examples/rie_calc/test.calc +4 -0
  20. data/examples/rie_dcuse/dcuse.rie.dr +71 -0
  21. data/examples/rie_dcuse/test.dcuse +1 -0
  22. data/examples/rie_pl0/orig_ex/exerrdg.pl0 +44 -0
  23. data/examples/rie_pl0/orig_ex/exerrm.pl0 +19 -0
  24. data/examples/rie_pl0/orig_ex/exerrmre.pl0 +20 -0
  25. data/examples/rie_pl0/orig_ex/exerrtok.pl0 +18 -0
  26. data/examples/rie_pl0/orig_ex/exmdg.pl0 +40 -0
  27. data/examples/rie_pl0/orig_ex/exmdgwwl.pl0 +43 -0
  28. data/examples/rie_pl0/orig_ex/exmrw.pl0 +22 -0
  29. data/examples/rie_pl0/orig_ex/exmwwl.pl0 +18 -0
  30. data/examples/rie_pl0/orig_ex/exnorw.pl0 +17 -0
  31. data/examples/rie_pl0/pl0.rie.dr +450 -0
  32. data/examples/rie_pl0/test.pl0 +10 -0
  33. data/examples/sample_calc/calc.action.dr +33 -33
  34. data/examples/sample_calc/calc.ast.action.dr +65 -66
  35. data/examples/sample_calc/calc.ast.dr +55 -55
  36. data/examples/sample_calc/calc.cst.dr +45 -45
  37. data/examples/sample_calc/calc.dr +43 -43
  38. data/examples/sample_calc/calc.lex.dr +29 -29
  39. data/examples/sample_calc/{calc_prec.nvaction.dr → calc_prec.action.dr} +31 -31
  40. data/examples/slex_test/divreg.slex.dr +29 -29
  41. data/examples/slex_test/ljoin.slex.dr +36 -36
  42. data/examples/slex_test/test.divreg +1 -1
  43. data/examples/slex_test/test.ljoin +3 -3
  44. data/lib/depager.rb +582 -670
  45. data/lib/depager/grammar.rb +256 -291
  46. data/lib/depager/lr.rb +574 -579
  47. data/lib/depager/parser.rb +282 -277
  48. data/lib/depager/ruby/plugins/_rie_debug.rb +35 -0
  49. data/lib/depager/ruby/plugins/action.rb +53 -43
  50. data/lib/depager/ruby/plugins/ast.dr +364 -269
  51. data/lib/depager/ruby/plugins/ast.rb +1367 -1308
  52. data/lib/depager/ruby/plugins/cst.dr +172 -180
  53. data/lib/depager/ruby/plugins/cst.rb +587 -626
  54. data/lib/depager/ruby/plugins/lex.dr +85 -89
  55. data/lib/depager/ruby/plugins/lex.rb +310 -336
  56. data/lib/depager/ruby/plugins/rie.dr +723 -0
  57. data/lib/depager/ruby/plugins/rie.rb +1653 -0
  58. data/lib/depager/ruby/plugins/slex.dr +202 -200
  59. data/lib/depager/ruby/plugins/slex.rb +780 -817
  60. data/lib/depager/ruby/plugins/srp.rb +56 -51
  61. data/lib/depager/ruby/templates/extension_lalr_master.erb +46 -51
  62. data/lib/depager/ruby/templates/extension_lalr_slave.erb +99 -107
  63. data/lib/depager/ruby/templates/single_lalr_parser.erb +115 -117
  64. data/lib/depager/utils.rb +148 -318
  65. data/lib/depager/version.rb +4 -3
  66. metadata +52 -60
  67. data/ChangeLog +0 -16
  68. data/data/depager/pre-setup.rb +0 -3
  69. data/examples/c89/c89.tab.rb +0 -7127
  70. data/examples/pl0d/pl0ds.tab.rb +0 -2698
  71. data/examples/sample_calc/calc.action.tab.rb +0 -457
  72. data/examples/sample_calc/calc.ast.action.tab.rb +0 -749
  73. data/examples/sample_calc/calc.ast.tab.rb +0 -665
  74. data/examples/sample_calc/calc.astdf.dr +0 -54
  75. data/examples/sample_calc/calc.astdf.tab.rb +0 -672
  76. data/examples/sample_calc/calc.atree.tab.rb +0 -451
  77. data/examples/sample_calc/calc.cst.tab.rb +0 -644
  78. data/examples/sample_calc/calc.lex.tab.rb +0 -374
  79. data/examples/sample_calc/calc.nvaction.dr +0 -33
  80. data/examples/sample_calc/calc.nvaction.tab.rb +0 -465
  81. data/examples/sample_calc/calc.tab.rb +0 -365
  82. data/examples/sample_calc/calc_prec.nvaction.tab.rb +0 -431
  83. data/examples/slex_test/divreg.slex.tab.rb +0 -303
  84. data/examples/slex_test/ljoin.slex.tab.rb +0 -370
  85. data/lib/depager/ruby/plugins/_ast_tmpl.rb +0 -73
  86. data/lib/depager/ruby/plugins/astdf.rb +0 -6
  87. data/lib/depager/ruby/plugins/atree.dr +0 -55
  88. data/lib/depager/ruby/plugins/atree.rb +0 -347
  89. data/lib/depager/ruby/plugins/nvaction.rb +0 -19
  90. data/lib/depager/ruby/templates/simple.erb +0 -23
  91. data/setup.rb +0 -1585
@@ -1,579 +1,574 @@
1
- require 'pp'
2
- require 'depager/grammar.rb'
3
-
4
- module Depager::ParsingMethod
5
- class Grammar
6
- end
7
- end
8
-
9
- module Depager::LALR
10
- class SingleParserGenerator < Simple::SingleGenerator
11
- Tmplfile = 'single_lalr_parser.erb'
12
- def initialize d_parser
13
- super
14
- @parsing_method = LALR
15
- @basis_name = @d_parser.target_name + '.new()'
16
- end
17
- end
18
-
19
- class ExtensionParserGenerator < Simple::ExtensionGenerator
20
- TmplfileMaster = "#{Tmpldir}/extension_lalr_master.erb"
21
- TmplfileSlave = "#{Tmpldir}/extension_lalr_slave.erb"
22
- def initialize d_parser
23
- super
24
- @parsing_method = LALR
25
- @basis_name = 'self'
26
- end
27
- end
28
-
29
- Eps = Depager::ParsingMethod::Grammar::Eps
30
- TLA = Eps - 1
31
- class Grammar < Depager::ParsingMethod::Grammar
32
- attr_accessor :memo_closure
33
- def initialize_depend
34
- @first1[TLA] = [TLA]
35
- @sym_mask[TLA] = (1 << @sym_mask.size)
36
- @mask_sym << TLA
37
- make_sym_f0e
38
- @memo_closure = {}
39
- @memo_closure1 = {}
40
- end
41
-
42
- def make_sym_f0e
43
- @f0e = {}
44
- @empty_rules.each do |lhs, rule_no|
45
- @f0e[lhs] = { rule_no => symset([Eps]) }
46
- end
47
- begin
48
- changed = false
49
- @rulelist.each do |rule|
50
- next unless @f0e[rule.rhs[0]]
51
-
52
- lhs, rhs = rule.lhs, rule.rhs
53
- @f0e[lhs] ||= {}
54
- @f0e[rhs[0]].each do |n, fst|
55
- @f0e[lhs][n] ||= symset()
56
- if fst.include? Eps
57
- fst = fst.dup
58
- fst.delete(Eps)
59
- fst.merge!(first(rhs[1 .. -1]))
60
- end
61
- unless fst.subset_of? @f0e[lhs][n]
62
- @f0e[lhs][n].merge! fst
63
- changed = true
64
- end
65
- end
66
- end
67
- end while changed
68
- end
69
-
70
- def closure1 rule, n, la
71
- key = [rule.n, n, la]
72
- return @memo_closure1[key] if @memo_closure1[key]
73
-
74
- result = [ LRItem[rule, n, symset(la)] ]
75
- memo = n == 0 ? { result[0].rule.n => result[0] } : {}
76
- memo2 = {}
77
- i = 0
78
- while i < result.size
79
- ri = result[i] ; i += 1
80
- dotsym = ri.dotsym
81
- next unless nonterms? dotsym
82
-
83
- b = first(ri.dotrest)
84
- if b.delete(Eps) then b.merge! ri.la
85
- elsif memo2[ ri ] then next
86
- end
87
- memo2[ ri ] = true
88
-
89
- lhs_to_rule[dotsym].each do |rule|
90
- if li = memo[rule.n]
91
- unless b.subset_of? li.la
92
- li.la.merge! b
93
- result << li
94
- end
95
- else
96
- li = memo[rule.n] = LRItem[rule, 0, b]
97
- result << li
98
- end
99
- end
100
- end
101
-
102
- result.uniq!
103
- @memo_closure1[key] = result
104
- end
105
-
106
- def closure rule, n, base=nil
107
- i = 0; appended = {}
108
- result = [base ? base : LRItem[rule, n]]
109
- memo = memo_closure
110
-
111
- while i < result.size
112
- ds = result[i].dotsym
113
- if nonterms?(ds) && !appended[ds]
114
- unless memo[ds]
115
- memo[ds] = []
116
- lhs_to_rule[ds].each do |rule|
117
- memo[ds] << LRItem[rule, 0]
118
- end
119
- end
120
- result.concat memo[ds]
121
- appended[ds] = true
122
- end
123
- i += 1
124
- end
125
- result
126
- end
127
- end
128
- class Rule < Depager::ParsingMethod::Rule
129
- end
130
-
131
- class LRItem
132
- attr_accessor :rule, :n, :la
133
- def initialize rule, n, la = nil
134
- @rule = rule
135
- @n = n
136
- @la = la || rule.grammar.symset()
137
- @_hash = nil
138
- end
139
- def self.[] rule, n, la = nil
140
- LRItem.new rule, n, la
141
- end
142
-
143
- def hash
144
- return @_hash if @_hash
145
- @_hash = (@rule.hash * 217 + @n.hash) % 76511
146
- end
147
- def eql? i
148
- @rule == i.rule && @n == i.n
149
- end
150
- alias == eql?
151
-
152
- def to_s
153
- la = @la.map{|i| @rule.grammar.symname i}.sort.join(' ')
154
- lhs = @rule.grammar.symname @rule.lhs
155
- rhs = @rule.rhs.map{|i| @rule.grammar.symname i}.insert(@n, '_').join(' ')
156
-
157
- str = "(#{'%03s' % @rule.n}) #{lhs} : #{rhs}"
158
- str << "\n # #{la}" if $MP_DEBUG && $MP_DEBUG.match(/l/)
159
- return str
160
- end
161
- def closure1 la
162
- @rule.grammar.closure1 @rule, @n, la
163
- end
164
- def closure
165
- @rule.grammar.closure @rule, @n, self
166
- end
167
- def dotsym
168
- @rule.rhs[@n]
169
- end
170
- def dotrest
171
- @rule.rhs[@n+1 .. -1]
172
- end
173
- end
174
-
175
- class State
176
- attr_accessor :items, :n
177
- def initialize items, n = nil
178
- @items = items
179
- @goto = {}
180
- @n = n
181
- @closure = nil
182
- @_hash = nil
183
- end
184
-
185
- def hash
186
- return @_hash if @_hash
187
- @_hash = @items.hash
188
- end
189
- def eql? i
190
- @items == i.items
191
- end
192
- alias == eql?
193
-
194
- def to_s
195
- ("I%03i = \n" % n) << @items.map{|i| " #{i}"}.join("\n")
196
- end
197
- def empty?
198
- @items.empty?
199
- end
200
- def self.[] items = []
201
- State.new items
202
- end
203
- def closure
204
- return @closure if @closure
205
- r = []
206
- @items.each do |i|
207
- r |= i.closure
208
- end
209
- @closure = r
210
- end
211
- def gg
212
- @goto
213
- end
214
- def mkgoto
215
- r = Hash.new{|h,k| h[k]=[]}
216
- closure.each do |c|
217
- if c.n < c.rule.rhs.size
218
- r[c.dotsym].push LRItem[c.rule, c.n+1]
219
- end
220
- end
221
- rg = []
222
- r.each do |k, v|
223
- rg.push [k, (@goto[k] = State.new(v))]
224
- end
225
- rg
226
- end
227
- def goto x
228
- return @goto[x] || State.new([])
229
- end
230
- end
231
-
232
- class Table
233
- attr_accessor :grammar, :action_table, :goto_table, :states
234
- attr_accessor :defred_table, :defred_after_shift_table
235
- def initialize grammar
236
- @grammar = grammar
237
- @states = nil
238
- @warning_list = []
239
-
240
- items
241
- mkset
242
- mktable
243
- end
244
-
245
- def items
246
- warn '** LR(0) **' if $MP_DEBUG
247
- n = 0
248
- m = 0
249
- states = [ State.new([ LRItem[grammar[0], 0] ], 0) ]
250
- memo = {states[0] => m}
251
-
252
- while n < states.size
253
- states[n].mkgoto.each do |x, a|
254
- unless a.empty?
255
- if memo_a = memo[a]
256
- states[n].gg[x] = states[memo_a]
257
- else
258
- m += 1
259
- a.n = m
260
- states[m] = a
261
- memo[a] = m
262
- end
263
- end
264
- end
265
- n += 1
266
- end
267
- @states = states
268
- end
269
-
270
- # -1:reduce sh; 1:shift rd(=key); 0:can't resolve
271
- def resolveconf(sh, rd)
272
- precs = grammar.precs
273
- psh = precs[sh]
274
- mrt = grammar[rd].rhs.reverse.find{|i| grammar.terms?(i) }
275
- prd = grammar[rd].prec || precs[mrt]
276
-
277
- # warn "#{grammar.syms[sh]} #{psh.inspect}"
278
- # warn "#{grammar[rd]} #{prd.inspect}"
279
-
280
- if psh && prd
281
- if psh[1] == prd[1]
282
- # warn :LEFT ? 'reduce' : 'shift'
283
- psh[0] == :LEFT ? -1 : 1
284
- elsif psh[1] > prd[1]
285
- # warn 'reduce'
286
- -1
287
- else
288
- # warn 'shift'
289
- 1
290
- end
291
- else
292
- 0
293
- end
294
- end
295
-
296
- def checkconf newv, oldv, key, g = nil
297
- return newv unless oldv
298
-
299
- rl = grammar.rulelist
300
- syms = grammar.syms
301
- if oldv == 'ACC'
302
- @warning_list << "'ACC' conflict #{g}."
303
- return oldv
304
- end
305
- # warn "\n-- N:#{newv} O:#{oldv} K:#{grammar.syms[key]} "
306
- if newv < 0 and oldv > 0
307
- # warn "-:shift #{grammar.syms[key]} go to #{oldv}"
308
- r = resolveconf(key, -newv)
309
- if r > 0
310
- # warn "+:shift #{grammar.syms[key]} go to #{oldv}"
311
- oldv
312
- elsif r < 0
313
- # warn "+:reduce #{grammar[-newv]}"
314
- newv
315
- else
316
- @warning_list <<
317
- ("shift/reduce conflict #{syms[key]}.\n #{g}\n" <<
318
- " shift : #{syms[key]}\n" <<
319
- " reduce: #{rl[-newv]}")
320
- oldv
321
- end
322
- elsif newv > 0 and oldv < 0
323
- r = resolveconf(key, -oldv)
324
- if r > 0
325
- # warn "shift"
326
- newv
327
- elsif r <0
328
- # warn "reduce"
329
- oldv
330
- else
331
- @warning_list <<
332
- ("shift/reduce conflict #{syms[key]}.\n #{g}\n" <<
333
- " shift : #{syms[key]}\n" <<
334
- " reduce: #{rl[-oldv]}")
335
- newv
336
- end
337
- elsif newv < 0 and oldv < 0
338
- unless newv == oldv
339
- @warning_list <<
340
- ("reduce/reduce conflict #{syms[key]}.\n #{g}\n" <<
341
- " reduce: #{rl[-newv]}\n" <<
342
- " reduce: #{rl[-oldv]}" )
343
- newv
344
- end
345
- else
346
- warn "must not happen"
347
- newv
348
- end
349
- end
350
-
351
- def mktable
352
- warn '** TABLE **' if $MP_DEBUG
353
- taction = (0...@states.size).map{ Array.new(grammar.syms.size - grammar.nonterms.size) }
354
- tgoto = (0...@states.size).map{ Array.new(grammar.nonterms.size - 1) }
355
-
356
- @states.each_with_index do |c, i|
357
- c.gg.each do |k, j|
358
- next unless k
359
- if grammar.terms? k
360
- key = k - grammar.nonterms.size
361
- taction[i][key] = checkconf(j.n, taction[i][key], k, c )
362
- else
363
- tgoto[i][k - 1] = j.n
364
- end
365
- end
366
- c.items.each do |j|
367
- if j.n == j.rule.rhs.size and j.rule.lhs != 0 # $start
368
- j.la.each do |u|
369
- key = u - grammar.nonterms.size
370
- taction[i][key] = checkconf(-j.rule.n, taction[i][key], u, c)
371
- end
372
- elsif efs = grammar.f0e[j.dotsym]
373
- efs.each do |rn, ef|
374
- ef.each do |es|
375
- fst = grammar.symset
376
- j.la.each do |la|
377
- fst |= grammar.first [es, *j.dotrest].push(la)
378
- end
379
- fst.each do |u|
380
- key = u - grammar.nonterms.size
381
- taction[i][key] = checkconf(-rn, taction[i][key], u, c)
382
- end
383
- end
384
- end
385
- end
386
- if j.rule == grammar[0] && j.n == 1 # $start : ...
387
- taction[i][0] = 'ACC'
388
- end
389
- end
390
- end
391
-
392
- @defred_table = []
393
- taction.each_with_index do |l, x|
394
- rs = l.select{|i| i.is_a? Integer}.uniq.compact
395
- rs = rs.select{|i| i < 0 }
396
- if rs.size == 1
397
- @defred_table[x] = rs[0]
398
- else
399
- @defred_table[x] = nil
400
- end
401
- end
402
-
403
- @defred_after_shift_table = []
404
- taction.each_with_index do |l, x|
405
- rs = l.select{|i| i.is_a? Integer}.uniq.compact
406
- if rs.size == 1 and rs[0] < 0
407
- @defred_after_shift_table[x] = rs[0]
408
- else
409
- @defred_after_shift_table[x] = nil
410
- end
411
- end
412
-
413
- taction.each_with_index do |l, x|
414
- if @defred_table[x]
415
- l.size.times do |x|
416
- l[x] = nil if l[x] && l[x] < 0
417
- end
418
- end
419
- end
420
-
421
- @action_table=taction
422
- @goto_table=tgoto
423
- end
424
-
425
- def check_table dp
426
- @warning_list.each{|i| dp.warning i }
427
-
428
- if $MP_DEBUG
429
- gen_state_info
430
- verbose dp if $MP_VERBOSE
431
- end
432
- end
433
-
434
- def mkset
435
- warn '** LA **' if $MP_DEBUG
436
- trn = []
437
- @states.each do |state|
438
- state.items.each do |sitem|
439
- sitem.closure1([TLA]).each do |citem|
440
- next if citem.n == citem.rule.rhs.size
441
- gi = state.goto(citem.dotsym).items
442
- i = gi.find{|j| j.rule == citem.rule && j.n == citem.n+1 }
443
- trn << [sitem, i] if citem.la.include? TLA
444
- i.la.merge!(citem.la).delete(TLA)
445
- end
446
- end
447
- end
448
-
449
- warn '** LALR(1) **' if $MP_DEBUG
450
- @states[0].items[0].la = @grammar.symset([grammar.nonterms.size]) # '$'
451
- begin
452
- changed = false
453
- trn.each do |k, v|
454
- unless k.la.subset_of?(v.la)
455
- v.la.merge!(k.la)
456
- changed
457
- end
458
- end
459
- end while changed
460
- end
461
- end
462
- end
463
-
464
- class Depager::LALR::Table
465
- def state_info
466
- @state_info
467
- end
468
-
469
- #puts grammar.closure.values.join("\n")
470
- #puts "-----"
471
- #puts grammar.memo_closure1.sort_by{|k,v| k}.map{|k,v| "#{k.inspect}:\n#{v.join("\n")}"}
472
- #puts 'mk'; mk.each{|k, v| p "#{k}=>#{v}"}
473
- #trn = trn.uniq
474
- #puts 'trn',trn.map{|a| "<#{a[2].n}>#{a[0]} => <#{a[3].n}>#{a[1]}"}
475
-
476
- def gen_state_info
477
- g = grammar
478
- @state_info = []
479
- @action_table.each_with_index {|s,x|
480
- shi, red, acc = "", "", ""
481
- s.each_with_index {|t, y|
482
- next unless t
483
- hd = (" %-15s" % g.symname(y + g.nonterms.size))
484
- if t == 'ACC'
485
- acc = "#{hd} accept\n\n"
486
- elsif t < 0
487
- red << "#{hd} reduce using rule #{-t} (#{g.symname g[-t].lhs})\n"
488
- else
489
- shi << "#{hd} shift, and goto to state #{t}\n"
490
- end
491
- }
492
- if t = @defred_table[x]
493
- as = @defred_after_shift_table[x] ? " [after shift]" : ""
494
- red << (" %-15s" % '$default') <<
495
- "reduce using rule #{-t} (#{g.symname g[-t].lhs}) #{as}\n"
496
- end
497
-
498
- @state_info << (@states[x].to_s << "\n\n#{shi}\n#{red}\n#{acc}")
499
- }
500
- end
501
-
502
- def verbose dp
503
- g, output = grammar, []
504
-
505
- if $MP_DEBUG.match(/f/)
506
- output << "** FIRST1 **"
507
- str = g.first1.map{|k, v|
508
- "#{g.symname k} => #{v.map{|i| g.symname i}.join(' ')}"
509
- }.join("\n")
510
- output << "#{str}\n\n"
511
- end
512
-
513
- if $MP_DEBUG.match(/e/)
514
- output << "** Empty Reduction **"
515
- str = g.f0e.map {|k, v|
516
- "#{g.symname k} =>\n" << v.map{|n, f|
517
- " #{rulelist[n]} ? #{f.map{|i| g.symname i}.join(' ')}"
518
- }.join("\n")
519
- }.join("\n")
520
- output << "#{str}\n\n"
521
- end
522
-
523
- if $MP_DEBUG.match(/s/)
524
- output << "** SYMBOLS **"
525
- str = g.syms.map{|k,_| "#{"%03i" % k} #{ g.symname k}"}.sort.join("\n")
526
- output << "#{str}\n\n"
527
- end
528
-
529
- if $MP_DEBUG.match(/g/)
530
- output << "*** Grammar ***"
531
- str = g.rulelist.join("\n")
532
- output << "#{str}\n\n"
533
- end
534
-
535
- if $MP_DEBUG.match(/c/)
536
- output << "*** States ***"
537
- output << @state_info.to_s
538
- end
539
-
540
- nssize = g.nonterms.size
541
- if $MP_DEBUG.match(/t/)
542
- output << "*** Action Table ***"
543
- ws = (nssize...g.syms.size).map{|i| j = g.symname(i).size; j < 6 ? 6 : j}
544
- str = " |"
545
- (nssize...g.syms.size).each_with_index{|i, x|
546
- str << ("%0#{ws[x]}s|" % g.symname(i))
547
- }; str << " $default|\n"
548
-
549
- @action_table.each_with_index{|i,x|
550
- str << ("%03i|" % x)
551
- i.each_with_index{|j, y|
552
- str << ("%0#{ws[y]}s|" % j)
553
- }
554
- str << ("%04s,%04s|\n" % [@defred_table[x], @defred_after_shift_table[x]])
555
- }
556
- output << "#{str}\n\n"
557
-
558
- output << "*** Goto Table ***"
559
- ws = (1...nssize).map{|i| j = g.symname(i).size; j < 6 ? 6 : j}
560
- str = " |"
561
- (1...nssize).each_with_index{|i, x|
562
- str << ("%0#{ws[x]}s|" % g.symname(i))
563
- }; str << "\n"
564
-
565
- @goto_table.each_with_index{|i,x|
566
- str << ("%03i|" % x)
567
- i.each_with_index{|j, y|
568
- str << ("%0#{ws[y]}s|" % j)
569
- }
570
- str << "\n"
571
- }
572
- output << "#{str}\n\n"
573
- end
574
-
575
- File.open("#{File.basename(dp.files.fname, '.dr')}.output", "w"){|f|
576
- f.write output.join("\n")
577
- }
578
- end
579
- end
1
+ # -*- coding: utf-8 -*-
2
+ require 'depager/grammar.rb'
3
+
4
+ module Depager::LALR
5
+ class ParserGenerator < Depager::ParserGenerator
6
+ def initialize d_parser
7
+ super
8
+ @parsing_method = Depager::LALR
9
+ end
10
+
11
+ def parser_code_template
12
+ File.read("#{TEMPLATES_DIR}/single_lalr_parser.erb")
13
+ end
14
+ end
15
+
16
+ class ExtensionGenerator < Depager::ExtensionGenerator
17
+ def initialize d_parser
18
+ super
19
+ @parsing_method = Depager::LALR
20
+ end
21
+
22
+ def master_code_template
23
+ File.read("#{TEMPLATES_DIR}/extension_lalr_master.erb")
24
+ end
25
+
26
+ def slave_code_template
27
+ File.read("#{TEMPLATES_DIR}/extension_lalr_slave.erb")
28
+ end
29
+ end
30
+
31
+ EPS = Depager::EPS
32
+ TLA = EPS - 1
33
+
34
+ class Grammar < Depager::Grammar
35
+ attr_accessor :memo_closure
36
+ def initialize_depend
37
+ @first1[TLA] = [TLA]
38
+ @sym_mask[TLA] = (1 << @sym_mask.size)
39
+ @mask_sym << TLA
40
+ make_sym_f0e
41
+ @memo_closure = {}
42
+ @memo_closure1 = {}
43
+ end
44
+
45
+ def make_sym_f0e
46
+ @f0e = {}
47
+ @empty_rules.each do |lhs, rule_no|
48
+ @f0e[lhs] = { rule_no => symset([EPS]) }
49
+ end
50
+ begin
51
+ changed = false
52
+ @rulelist.each do |rule|
53
+ next unless @f0e[rule.rhs[0]]
54
+
55
+ lhs, rhs = rule.lhs, rule.rhs
56
+ @f0e[lhs] ||= {}
57
+ @f0e[rhs[0]].each do |n, fst|
58
+ @f0e[lhs][n] ||= symset()
59
+ if fst.include? EPS
60
+ fst = fst.dup
61
+ fst.delete(EPS)
62
+ fst.merge!(first(rhs[1 .. -1]))
63
+ end
64
+ unless fst.subset_of? @f0e[lhs][n]
65
+ @f0e[lhs][n].merge! fst
66
+ changed = true
67
+ end
68
+ end
69
+ end
70
+ end while changed
71
+ end
72
+
73
+ def closure1 rule, n, la
74
+ key = [rule.n, n, la]
75
+ return @memo_closure1[key] if @memo_closure1[key]
76
+
77
+ result = [ LRItem[rule, n, symset(la)] ]
78
+ memo = n == 0 ? { result[0].rule.n => result[0] } : {}
79
+ memo2 = {}
80
+ i = 0
81
+ while i < result.size
82
+ ri = result[i] ; i += 1
83
+ dotsym = ri.dotsym
84
+ next unless nonterm? dotsym
85
+
86
+ b = first(ri.dotrest)
87
+ if b.delete(EPS) then b.merge! ri.la
88
+ elsif memo2[ ri ] then next
89
+ end
90
+ memo2[ ri ] = true
91
+
92
+ lhs_to_rule[dotsym].each do |rule|
93
+ if li = memo[rule.n]
94
+ unless b.subset_of? li.la
95
+ li.la.merge! b
96
+ result << li
97
+ end
98
+ else
99
+ li = memo[rule.n] = LRItem[rule, 0, b]
100
+ result << li
101
+ end
102
+ end
103
+ end
104
+
105
+ result.uniq!
106
+ @memo_closure1[key] = result
107
+ end
108
+
109
+ def closure rule, n, base=nil
110
+ i = 0; appended = {}
111
+ result = [base ? base : LRItem[rule, n]]
112
+ memo = memo_closure
113
+
114
+ while i < result.size
115
+ ds = result[i].dotsym
116
+ if nonterm?(ds) && !appended[ds]
117
+ unless memo[ds]
118
+ memo[ds] = []
119
+ lhs_to_rule[ds].each do |rule|
120
+ memo[ds] << LRItem[rule, 0]
121
+ end
122
+ end
123
+ result.concat memo[ds]
124
+ appended[ds] = true
125
+ end
126
+ i += 1
127
+ end
128
+ result
129
+ end
130
+ end
131
+
132
+ class Rule < Depager::Rule
133
+ end
134
+
135
+ class LRItem
136
+ attr_accessor :rule, :n, :la
137
+ def initialize rule, n, la = nil
138
+ @rule = rule
139
+ @n = n
140
+ @la = la || rule.grammar.symset()
141
+ @_hash = nil
142
+ end
143
+ def self.[] rule, n, la = nil
144
+ LRItem.new rule, n, la
145
+ end
146
+
147
+ def hash
148
+ return @_hash if @_hash
149
+ @_hash = (@rule.hash * 217 + @n.hash) % 76511
150
+ end
151
+ def eql? i
152
+ @rule == i.rule && @n == i.n
153
+ end
154
+ alias == eql?
155
+
156
+ def to_s
157
+ la = @la.map{|i| @rule.grammar.symname i}.sort.join(' ')
158
+ lhs = @rule.grammar.symname @rule.lhs
159
+ rhs = @rule.rhs.map{|i| @rule.grammar.symname i}.insert(@n, '_').join(' ')
160
+
161
+ str = "(#{'%03s' % @rule.n}) #{lhs} : #{rhs}"
162
+ str << "\n # #{la}" if Depager.debug_mode?(:l)
163
+ return str
164
+ end
165
+ def closure1 la
166
+ @rule.grammar.closure1 @rule, @n, la
167
+ end
168
+ def closure
169
+ @rule.grammar.closure @rule, @n, self
170
+ end
171
+ def dotsym
172
+ @rule.rhs[@n]
173
+ end
174
+ def dotrest
175
+ @rule.rhs[@n+1 .. -1]
176
+ end
177
+ end
178
+
179
+ class State
180
+ attr_accessor :items, :n
181
+ def initialize items, n = nil
182
+ @items = items
183
+ @goto = {}
184
+ @n = n
185
+ @closure = nil
186
+ @_hash = nil
187
+ end
188
+
189
+ def hash
190
+ return @_hash if @_hash
191
+ @_hash = @items.hash
192
+ end
193
+ def eql? i
194
+ @items == i.items
195
+ end
196
+ alias == eql?
197
+
198
+ def to_s
199
+ ("I%03i = \n" % n) << @items.map{|i| i.to_s }.join("\n").lines.map{|i| " #{i}"}.join
200
+ end
201
+ def empty?
202
+ @items.empty?
203
+ end
204
+ def self.[] items = []
205
+ State.new items
206
+ end
207
+ def closure
208
+ return @closure if @closure
209
+ r = []
210
+ @items.each do |i|
211
+ r |= i.closure
212
+ end
213
+ @closure = r
214
+ end
215
+ def gg
216
+ @goto
217
+ end
218
+ def mkgoto
219
+ r = Hash.new{|h,k| h[k]=[]}
220
+ closure.each do |c|
221
+ if c.n < c.rule.rhs.size
222
+ r[c.dotsym].push LRItem[c.rule, c.n+1]
223
+ end
224
+ end
225
+ rg = []
226
+ r.each do |k, v|
227
+ rg.push [k, (@goto[k] = State.new(v))]
228
+ end
229
+ rg
230
+ end
231
+ def goto x
232
+ return @goto[x] || State.new([])
233
+ end
234
+ end
235
+
236
+ class Table
237
+ attr_accessor :grammar, :action_table, :goto_table, :states
238
+ attr_accessor :defred_table, :defred_after_shift_table
239
+ def initialize grammar
240
+ @grammar = grammar
241
+ @states = nil
242
+ @warning_list = []
243
+
244
+ items
245
+ mkset
246
+ mktable
247
+ end
248
+
249
+ def items
250
+ warn '** LR(0) **' if Depager.debug_mode?
251
+ n = 0
252
+ m = 0
253
+ states = [ State.new([ LRItem[grammar[0], 0] ], 0) ]
254
+ memo = {states[0] => m}
255
+
256
+ while n < states.size
257
+ states[n].mkgoto.each do |x, a|
258
+ unless a.empty?
259
+ if memo_a = memo[a]
260
+ states[n].gg[x] = states[memo_a]
261
+ else
262
+ m += 1
263
+ a.n = m
264
+ states[m] = a
265
+ memo[a] = m
266
+ end
267
+ end
268
+ end
269
+ n += 1
270
+ end
271
+ @states = states
272
+ end
273
+
274
+ # -1:reduce sh; 1:shift rd(=key); 0:can't resolve
275
+ def resolveconf(sh, rd)
276
+ precs = grammar.precs
277
+ psh = precs[sh]
278
+ mrt = grammar[rd].rhs.reverse.find{|i| grammar.term?(i) }
279
+ prd = grammar[rd].prec || precs[mrt]
280
+
281
+ if psh && prd
282
+ if psh[1] == prd[1]
283
+ # warn :LEFT ? 'reduce' : 'shift'
284
+ psh[0] == :LEFT ? -1 : 1
285
+ elsif psh[1] > prd[1]
286
+ # warn 'reduce'
287
+ -1
288
+ else
289
+ # warn 'shift'
290
+ 1
291
+ end
292
+ else
293
+ 0
294
+ end
295
+ end
296
+
297
+ def checkconf newv, oldv, key, g = nil
298
+ return newv unless oldv
299
+
300
+ rl = grammar.rulelist
301
+ syms = grammar.syms
302
+ if oldv == 'ACC'
303
+ @warning_list << "'ACC' conflict #{g}."
304
+ return oldv
305
+ end
306
+ # warn "\n-- N:#{newv} O:#{oldv} K:#{grammar.syms[key]} "
307
+ if newv < 0 and oldv > 0
308
+ # warn "-:shift #{grammar.syms[key]} go to #{oldv}"
309
+ r = resolveconf(key, -newv)
310
+ if r > 0
311
+ # warn "+:shift #{grammar.syms[key]} go to #{oldv}"
312
+ oldv
313
+ elsif r < 0
314
+ # warn "+:reduce #{grammar[-newv]}"
315
+ newv
316
+ else
317
+ @warning_list <<
318
+ ("shift/reduce conflict #{syms[key]}.\n #{g}\n" <<
319
+ " shift : #{syms[key]}\n" <<
320
+ " reduce: #{rl[-newv]}")
321
+ oldv
322
+ end
323
+ elsif newv > 0 and oldv < 0
324
+ r = resolveconf(key, -oldv)
325
+ if r > 0
326
+ # warn "shift"
327
+ newv
328
+ elsif r <0
329
+ # warn "reduce"
330
+ oldv
331
+ else
332
+ @warning_list <<
333
+ ("shift/reduce conflict #{syms[key]}.\n #{g}\n" <<
334
+ " shift : #{syms[key]}\n" <<
335
+ " reduce: #{rl[-oldv]}")
336
+ newv
337
+ end
338
+ elsif newv < 0 and oldv < 0
339
+ unless newv == oldv
340
+ @warning_list <<
341
+ ("reduce/reduce conflict #{syms[key]}.\n #{g}\n" <<
342
+ " reduce: #{rl[-newv]}\n" <<
343
+ " reduce: #{rl[-oldv]}" )
344
+ newv
345
+ end
346
+ else
347
+ warn "must not happen"
348
+ newv
349
+ end
350
+ end
351
+
352
+ def mktable
353
+ warn '** TABLE **' if Depager.debug_mode?
354
+ taction = (0...@states.size).map{ Array.new(grammar.syms.size - grammar.nonterms.size) }
355
+ tgoto = (0...@states.size).map{ Array.new(grammar.nonterms.size - 1) }
356
+
357
+ @states.each_with_index do |c, i|
358
+ c.gg.each do |k, j|
359
+ next unless k
360
+ if grammar.term? k
361
+ key = k - grammar.nonterms.size
362
+ taction[i][key] = checkconf(j.n, taction[i][key], k, c )
363
+ else
364
+ tgoto[i][k - 1] = j.n
365
+ end
366
+ end
367
+ c.items.each do |j|
368
+ if j.n == j.rule.rhs.size and j.rule.lhs != 0 # $start
369
+ j.la.each do |u|
370
+ key = u - grammar.nonterms.size
371
+ taction[i][key] = checkconf(-j.rule.n, taction[i][key], u, c)
372
+ end
373
+ elsif efs = grammar.f0e[j.dotsym]
374
+ efs.each do |rn, ef|
375
+ ef.each do |es|
376
+ fst = grammar.symset
377
+ j.la.each do |la|
378
+ fst |= grammar.first [es, *j.dotrest].push(la)
379
+ end
380
+ fst.each do |u|
381
+ key = u - grammar.nonterms.size
382
+ taction[i][key] = checkconf(-rn, taction[i][key], u, c)
383
+ end
384
+ end
385
+ end
386
+ end
387
+ if j.rule == grammar[0] && j.n == 1 # $start : ...
388
+ taction[i][0] = 'ACC'
389
+ end
390
+ end
391
+ end
392
+
393
+ @defred_table = []
394
+ taction.each_with_index do |l, x|
395
+ rs = l.select{|i| i.is_a? Integer}.uniq.compact
396
+ rs = rs.select{|i| i < 0 }
397
+ if rs.size == 1
398
+ @defred_table[x] = rs[0]
399
+ else
400
+ @defred_table[x] = nil
401
+ end
402
+ end
403
+
404
+ @defred_after_shift_table = []
405
+ taction.each_with_index do |l, x|
406
+ rs = l.select{|i| i.is_a? Integer}.uniq.compact
407
+ if rs.size == 1 and rs[0] < 0
408
+ @defred_after_shift_table[x] = rs[0]
409
+ else
410
+ @defred_after_shift_table[x] = nil
411
+ end
412
+ end
413
+
414
+ taction.each_with_index do |l, x|
415
+ if @defred_table[x]
416
+ l.size.times do |x|
417
+ l[x] = nil if l[x] && l[x] < 0
418
+ end
419
+ end
420
+ end
421
+
422
+ @action_table=taction
423
+ @goto_table=tgoto
424
+ end
425
+
426
+ def check_table dp
427
+ @warning_list.each{|i| dp.warning i }
428
+
429
+ if Depager.debug_mode?
430
+ gen_state_info
431
+ verbose dp if Depager.verbose_mode?
432
+ end
433
+ end
434
+
435
+ def mkset
436
+ warn '** LA **' if Depager.debug_mode?
437
+ trn = []
438
+ @states.each do |state|
439
+ state.items.each do |sitem|
440
+ sitem.closure1([TLA]).each do |citem|
441
+ next if citem.n == citem.rule.rhs.size
442
+ gi = state.goto(citem.dotsym).items
443
+ i = gi.find{|j| j.rule == citem.rule && j.n == citem.n+1 }
444
+ trn << [sitem, i] if citem.la.include? TLA
445
+ i.la.merge!(citem.la).delete(TLA)
446
+ end
447
+ end
448
+ end
449
+
450
+ warn '** LALR(1) **' if Depager.debug_mode?
451
+ @states[0].items[0].la = @grammar.symset([grammar.nonterms.size]) # '$'
452
+ begin
453
+ changed = false
454
+ trn.each do |k, v|
455
+ unless k.la.subset_of?(v.la)
456
+ v.la.merge!(k.la)
457
+ changed
458
+ end
459
+ end
460
+ end while changed
461
+ end
462
+ end
463
+ end
464
+
465
+ class Depager::LALR::Table
466
+ def state_info
467
+ @state_info
468
+ end
469
+
470
+ def gen_state_info
471
+ g = grammar
472
+ @state_info = []
473
+ @action_table.each_with_index {|s,x|
474
+ shi, red, acc = "", "", ""
475
+ s.each_with_index {|t, y|
476
+ next unless t
477
+ hd = (" %-15s" % g.symname(y + g.nonterms.size))
478
+ if t == 'ACC'
479
+ acc = "#{hd} accept"
480
+ elsif t < 0
481
+ red << "#{hd} reduce using rule #{-t} (#{g.symname g[-t].lhs})\n"
482
+ else
483
+ shi << "#{hd} shift, and goto to state #{t}\n"
484
+ end
485
+ }
486
+ if t = @defred_table[x]
487
+ as = @defred_after_shift_table[x] ? " [after shift]" : ""
488
+ red << (" %-15s" % '$default') <<
489
+ "reduce using rule #{-t} (#{g.symname g[-t].lhs}) #{as}"
490
+ end
491
+
492
+ @state_info << (@states[x].to_s << "\n\n#{shi}\n#{red}\n#{acc}").strip
493
+ }
494
+ end
495
+
496
+ def verbose dp
497
+ g, output = grammar, []
498
+
499
+ if Depager.debug_mode?(:f)
500
+ output << "** FIRST1 **"
501
+ str = g.first1.map{|k, v|
502
+ "#{g.symname k} => #{v.map{|i| g.symname i}.join(' ')}"
503
+ }.join("\n")
504
+ output << "#{str}\n\n"
505
+ end
506
+
507
+ if Depager.debug_mode?(:e)
508
+ output << "** Empty Reduction **"
509
+ str = g.f0e.map {|k, v|
510
+ "#{g.symname k} =>\n" << v.map{|n, f|
511
+ " #{rulelist[n]} ? #{f.map{|i| g.symname i}.join(' ')}"
512
+ }.join("\n")
513
+ }.join("\n")
514
+ output << "#{str}\n\n"
515
+ end
516
+
517
+ if Depager.debug_mode?(:s)
518
+ output << "** SYMBOLS **"
519
+ str = g.syms.map{|k,_| "#{"%03i" % k} #{ g.symname k}"}.sort.join("\n")
520
+ output << "#{str}\n\n"
521
+ end
522
+
523
+ if Depager.debug_mode?(:g)
524
+ output << "*** Grammar ***"
525
+ str = g.rulelist.join("\n")
526
+ output << "#{str}\n\n"
527
+ end
528
+
529
+ if Depager.debug_mode?(:c)
530
+ output << "*** States ***"
531
+ str = @state_info.join("\n\n").strip
532
+ output << "#{str}\n\n"
533
+ end
534
+
535
+ nssize = g.nonterms.size
536
+ if Depager.debug_mode?(:t)
537
+ output << "*** Action Table ***"
538
+ ws = (nssize...g.syms.size).map{|i| j = g.symname(i).size; j < 6 ? 6 : j}
539
+ str = " |"
540
+ (nssize...g.syms.size).each_with_index{|i, x|
541
+ str << ("%0#{ws[x]}s|" % g.symname(i))
542
+ }; str << " $default|\n"
543
+
544
+ @action_table.each_with_index{|i,x|
545
+ str << ("%03i|" % x)
546
+ i.each_with_index{|j, y|
547
+ str << ("%0#{ws[y]}s|" % j)
548
+ }
549
+ str << ("%04s,%04s|\n" % [@defred_table[x], @defred_after_shift_table[x]])
550
+ }
551
+ output << "#{str}\n\n"
552
+
553
+ output << "*** Goto Table ***"
554
+ ws = (1...nssize).map{|i| j = g.symname(i).size; j < 6 ? 6 : j}
555
+ str = " |"
556
+ (1...nssize).each_with_index{|i, x|
557
+ str << ("%0#{ws[x]}s|" % g.symname(i))
558
+ }; str << "\n"
559
+
560
+ @goto_table.each_with_index{|i,x|
561
+ str << ("%03i|" % x)
562
+ i.each_with_index{|j, y|
563
+ str << ("%0#{ws[y]}s|" % j)
564
+ }
565
+ str << "\n"
566
+ }
567
+ output << "#{str}\n\n"
568
+ end
569
+
570
+ File.open("#{File.basename(dp.file.path, '.dr')}.output", "w"){|f|
571
+ f.write output.join("\n")
572
+ }
573
+ end
574
+ end