depager 0.2.3 → 0.3.0.b20160729

Sign up to get free protection for your applications and to get access to all the features.
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