depager 0.2.3 → 0.3.0.b20250423

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