depager 0.1.9

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 (53) hide show
  1. data/ChangeLog +4 -0
  2. data/Manifest.txt +52 -0
  3. data/README.en +64 -0
  4. data/README.ja +128 -0
  5. data/bin/depager +47 -0
  6. data/data/depager/misc/depager-mode.el +209 -0
  7. data/data/depager/sample/extension/paction.dr +15 -0
  8. data/data/depager/sample/extension/pactiontest.dr +14 -0
  9. data/data/depager/sample/pl0d/pl0ds.dr +334 -0
  10. data/data/depager/sample/pl0d/pl0test.pl0 +34 -0
  11. data/data/depager/sample/sample_calc/calc.action.dr +33 -0
  12. data/data/depager/sample/sample_calc/calc.astdf.dr +54 -0
  13. data/data/depager/sample/sample_calc/calc.astl.action.dr +66 -0
  14. data/data/depager/sample/sample_calc/calc.astl.dr +55 -0
  15. data/data/depager/sample/sample_calc/calc.atree.dr +43 -0
  16. data/data/depager/sample/sample_calc/calc.cst.dr +45 -0
  17. data/data/depager/sample/sample_calc/calc.dr +43 -0
  18. data/data/depager/sample/sample_calc/calc.lex.dr +29 -0
  19. data/data/depager/sample/sample_calc/calc.nvaction.dr +33 -0
  20. data/data/depager/sample/sample_calc/calc_prec.nvaction.dr +31 -0
  21. data/data/depager/sample/slex_test/slextest1.dr +37 -0
  22. data/data/depager/sample/slex_test/slextest2.dr +33 -0
  23. data/lib/depager.rb +608 -0
  24. data/lib/depager/Rakefile +30 -0
  25. data/lib/depager/action.rb +47 -0
  26. data/lib/depager/ast_base.dr +232 -0
  27. data/lib/depager/ast_base.rb +1249 -0
  28. data/lib/depager/astdf.rb +10 -0
  29. data/lib/depager/astl.rb +14 -0
  30. data/lib/depager/atree.dr +55 -0
  31. data/lib/depager/atree.rb +336 -0
  32. data/lib/depager/cst.dr +182 -0
  33. data/lib/depager/cst.rb +625 -0
  34. data/lib/depager/lex.dr +76 -0
  35. data/lib/depager/lex.rb +306 -0
  36. data/lib/depager/lr.rb +604 -0
  37. data/lib/depager/nvaction.rb +21 -0
  38. data/lib/depager/parse_action.rb +24 -0
  39. data/lib/depager/parser.rb +248 -0
  40. data/lib/depager/psrtmpl.rb +33 -0
  41. data/lib/depager/slex.dr +161 -0
  42. data/lib/depager/slex.rb +646 -0
  43. data/lib/depager/srp.rb +50 -0
  44. data/lib/depager/template/astdf.erbs +57 -0
  45. data/lib/depager/template/astl.erbs +57 -0
  46. data/lib/depager/template/extension_lalr_master.erb +51 -0
  47. data/lib/depager/template/extension_lalr_slave.erb +107 -0
  48. data/lib/depager/template/simple.erb +21 -0
  49. data/lib/depager/template/single_lalr_parser.erb +97 -0
  50. data/lib/depager/utils.rb +355 -0
  51. data/lib/depager/version.rb +9 -0
  52. data/setup.rb +1585 -0
  53. metadata +103 -0
@@ -0,0 +1,76 @@
1
+ %defext LexerExtension
2
+ %extend NVAction ('depager/nvaction.rb')
3
+ %decorate @NVAction
4
+ #%decorate ShiftReducePrinter ('depager/srp.rb')
5
+ %param :none
6
+ %hook prerulelist /%LEX\{\s*\Z/ skip
7
+ %banner '%LEX{ ... }'
8
+ %mixin ActionParser ('depager/parse_action')
9
+ %inner{
10
+ def init_parser
11
+ super
12
+ @code = []
13
+ end
14
+ def lex
15
+ until @file.eof?
16
+ until @line.empty? do
17
+ case @line
18
+ when /\A\s+/
19
+ #skip blank
20
+ when /\A%\}\s*\Z/
21
+ @line = $'
22
+ yield nil,nil
23
+ when /\A\/(([^\/\\]+|\\.)*)\//, /\A'([^'\\]+|\\.)*\'/
24
+ yield :LEX, "/\\A#{$1}/"
25
+ when /\A\{/
26
+ yield :ACTION, parse_action
27
+ /./=~'.'
28
+ when /\A(.)/
29
+ yield $&, $&
30
+ else
31
+ raise RuntimeError, "must not happen #{line}"
32
+ end
33
+ @line = $'
34
+ end
35
+ getline
36
+ end
37
+ yield nil, nil
38
+ end
39
+ %}
40
+ %%
41
+
42
+ #begin-rule
43
+ start:
44
+ lexactlist
45
+ {
46
+ g_parser.optinner << %{
47
+ def lex
48
+ begin
49
+ until @line.empty? do
50
+ case @line
51
+ #{_lexactlist}
52
+ else
53
+ raise RuntimeError, "must not happen \#{@line}"
54
+ end
55
+ @oldline = @line
56
+ @line = $'
57
+ end
58
+ end while @line = getline
59
+ yield nil, nil
60
+ end
61
+ }; #code
62
+ }
63
+ ;
64
+ lexactlist:
65
+ lexact { [ _lexact ] }
66
+ | lexactlist lexact { _lexactlist << _lexact }
67
+ ;
68
+ lexact:
69
+ lexlist ACTION { "when #{_lexlist.join(', ')}\n#{_ACTION}" }
70
+ ;
71
+ lexlist:
72
+ LEX { [ _LEX ] }
73
+ | lexlist ',' LEX { _lexlist << _LEX }
74
+ ;
75
+ #end-rule
76
+ %%
@@ -0,0 +1,306 @@
1
+
2
+ ###
3
+ ### LexerExtension - Depager Extension (master)
4
+ ###
5
+ require 'pp.rb'
6
+ require 'depager/parser.rb'
7
+ require 'depager/parse_action'
8
+
9
+
10
+ module D4LexerExtension #:nodoc:all
11
+ end
12
+
13
+ class LexerExtension #:nodoc:all
14
+ include Depager::ExtensionUtils
15
+
16
+ attr_accessor :h2p
17
+
18
+ def initialize
19
+ @master = self
20
+ @hook = []
21
+ @h2p = {}
22
+ init_parser
23
+ end
24
+
25
+ def __regext__ p
26
+ super p, :none, nil
27
+
28
+ @hook[0] = LexerExtension_prerulelist.new(p, @nparam, self)
29
+ @h2p['prerulelist'] = @hook[0]
30
+ p.prerulelist.push [@hook[0], :do_parse]
31
+
32
+ regext p
33
+ end
34
+
35
+ ### Inner Code
36
+
37
+ end
38
+
39
+ ### Outer Code
40
+
41
+ ###
42
+ ### LexerExtension_prerulelist - Part of Depager Extension (slave)
43
+ ###
44
+ module D4LexerExtension_prerulelist #:nodoc:all
45
+ end
46
+
47
+ class LexerExtension_prerulelist < Basis #:nodoc:all
48
+ include Depager::ExtensionUtils
49
+
50
+ include ActionParser
51
+
52
+ ### Reduce Table
53
+ reduce_table = [
54
+ [ -1, 1 ],
55
+ [ 0, 1 ],
56
+ [ 1, 1 ],
57
+ [ 1, 2 ],
58
+ [ 2, 2 ],
59
+ [ 3, 1 ],
60
+ [ 3, 3 ],
61
+ ]
62
+ ### Extension Params
63
+ nparams = {
64
+ 'NVAction' => 2,
65
+ }
66
+ ### Term to Int
67
+ t2i = {
68
+ nil => 0,
69
+ false => 1,
70
+ :ACTION => 2,
71
+ :LEX => 3,
72
+ "," => 4,
73
+ }
74
+ ### Int to Term
75
+ i2t = [
76
+ nil,
77
+ false,
78
+ :ACTION,
79
+ :LEX,
80
+ ",",
81
+ ]
82
+ ### Action Table
83
+ action_table = [
84
+ [ nil, nil, nil, 3, nil, ],
85
+ [ ACC, nil, nil, nil, nil, ],
86
+ [ nil, nil, nil, 3, nil, ],
87
+ [ nil, nil, nil, nil, nil, ],
88
+ [ nil, nil, nil, nil, nil, ],
89
+ [ nil, nil, 7, nil, 8, ],
90
+ [ nil, nil, nil, nil, nil, ],
91
+ [ nil, nil, nil, nil, nil, ],
92
+ [ nil, nil, nil, 9, nil, ],
93
+ [ nil, nil, nil, nil, nil, ],
94
+ ]
95
+ ### Default Reduce Table
96
+ defred_table = [
97
+ nil,
98
+ nil,
99
+ -1,
100
+ -5,
101
+ -2,
102
+ nil,
103
+ -3,
104
+ -4,
105
+ nil,
106
+ -6,
107
+ ]
108
+ defred_after_shift_table = [
109
+ nil,
110
+ nil,
111
+ nil,
112
+ -5,
113
+ -2,
114
+ nil,
115
+ -3,
116
+ -4,
117
+ nil,
118
+ -6,
119
+ ]
120
+ ### Nonterm to Int
121
+ nt2i = {
122
+ :start => 0,
123
+ :lexactlist => 1,
124
+ :lexact => 2,
125
+ :lexlist => 3,
126
+ }
127
+ ### Int to Nonterm
128
+ i2nt = [
129
+ :start,
130
+ :lexactlist,
131
+ :lexact,
132
+ :lexlist,
133
+ ]
134
+ ### Goto Table
135
+ goto_table = [
136
+ [ 1, 2, 4, 5, ],
137
+ [ nil, nil, nil, nil, ],
138
+ [ nil, nil, 6, 5, ],
139
+ [ nil, nil, nil, nil, ],
140
+ [ nil, nil, nil, nil, ],
141
+ [ nil, nil, nil, nil, ],
142
+ [ nil, nil, nil, nil, ],
143
+ [ nil, nil, nil, nil, ],
144
+ [ nil, nil, nil, nil, ],
145
+ [ nil, nil, nil, nil, ],
146
+ ]
147
+
148
+ Tables = [ reduce_table, nparams, action_table,
149
+ defred_table, defred_after_shift_table, goto_table,
150
+ t2i, i2t, nt2i, i2nt ]
151
+
152
+ attr_accessor :p, :m
153
+ def initialize p, nparam, master = nil
154
+ super()
155
+ @g_parser = @p = p
156
+ @master = @m = master
157
+ @nparam = nparam
158
+ @dect = D4LexerExtension_prerulelist::NVAction.new(self)
159
+ init_parser
160
+ end
161
+
162
+
163
+ def do_parse?
164
+ if @line =~ /^\s*%LEX\{\s*\Z/
165
+ @line = $'
166
+ true
167
+ else
168
+ false
169
+ end
170
+ end
171
+
172
+
173
+ def banner
174
+ "%LEX{ ... } / #{@master.class.name}"
175
+ end
176
+
177
+ ### Inner Code
178
+ def init_parser
179
+ super
180
+ @code = []
181
+ end
182
+ def lex
183
+ until @file.eof?
184
+ until @line.empty? do
185
+ case @line
186
+ when /\A\s+/
187
+ #skip blank
188
+ when /\A%\}\s*\Z/
189
+ @line = $'
190
+ yield nil,nil
191
+ when /\A\/(([^\/\\]+|\\.)*)\//, /\A'([^'\\]+|\\.)*\'/
192
+ yield :LEX, "/\\A#{$1}/"
193
+ when /\A\{/
194
+ yield :ACTION, parse_action
195
+ /./=~'.'
196
+ when /\A(.)/
197
+ yield $&, $&
198
+ else
199
+ raise RuntimeError, "must not happen #{line}"
200
+ end
201
+ @line = $'
202
+ end
203
+ getline
204
+ end
205
+ yield nil, nil
206
+ end
207
+
208
+ end
209
+
210
+ ### Outer Code
211
+
212
+ class D4LexerExtension_prerulelist::NVAction < Depager::Action #:nodoc:all
213
+ include Depager::DecoratorUtils
214
+ include ActionParser
215
+
216
+ on_reduce = [
217
+ nil,
218
+ :_act_0,
219
+ :_act_1,
220
+ :_act_2,
221
+ :_act_3,
222
+ :_act_4,
223
+ :_act_5,
224
+
225
+ ]
226
+ Tables = [on_reduce]
227
+ def initialize inside
228
+ super inside, 'NVAction'
229
+ @on_reduce, = self.class::Tables
230
+ init_parser
231
+ end
232
+
233
+
234
+ module_eval <<-'.,.,118028145942522.,.,', 'lex.dr', 43
235
+ def _act_0 val
236
+ _lexactlist = *val
237
+
238
+ g_parser.optinner << %{
239
+ def lex
240
+ begin
241
+ until @line.empty? do
242
+ case @line
243
+ #{_lexactlist}
244
+ else
245
+ raise RuntimeError, "must not happen \#{@line}"
246
+ end
247
+ @oldline = @line
248
+ @line = $'
249
+ end
250
+ end while @line = getline
251
+ yield nil, nil
252
+ end
253
+ }; #code
254
+
255
+ end
256
+
257
+ .,.,118028145942522.,.,
258
+
259
+ module_eval <<-'.,.,118028145936749.,.,', 'lex.dr', 63
260
+ def _act_1 val
261
+ _lexact = *val
262
+ [ _lexact ]
263
+
264
+ end
265
+
266
+ .,.,118028145936749.,.,
267
+
268
+ module_eval <<-'.,.,118028145915595.,.,', 'lex.dr', 64
269
+ def _act_2 val
270
+ _lexactlist, _lexact = *val
271
+ _lexactlist << _lexact
272
+
273
+ end
274
+
275
+ .,.,118028145915595.,.,
276
+
277
+ module_eval <<-'.,.,118028145922278.,.,', 'lex.dr', 67
278
+ def _act_3 val
279
+ _lexlist, _ACTION = *val
280
+ "when #{_lexlist.join(', ')}\n#{_ACTION}"
281
+
282
+ end
283
+
284
+ .,.,118028145922278.,.,
285
+
286
+ module_eval <<-'.,.,118028145957906.,.,', 'lex.dr', 70
287
+ def _act_4 val
288
+ _LEX = *val
289
+ [ _LEX ]
290
+
291
+ end
292
+
293
+ .,.,118028145957906.,.,
294
+
295
+ module_eval <<-'.,.,1180281459420.,.,', 'lex.dr', 71
296
+ def _act_5 val
297
+ _lexlist, _, _LEX = *val
298
+ _lexlist << _LEX
299
+
300
+ end
301
+
302
+ .,.,1180281459420.,.,
303
+
304
+ end
305
+
306
+
@@ -0,0 +1,604 @@
1
+ module Depager
2
+ class G
3
+ attr_accessor :rulelist, :gh, :syms, :nonterms, :terms, :closure, :ismap, :nssize, :tla
4
+ attr_accessor :precs, :epr, :epr2, :f0e, :first1
5
+ Eps = 0x3fffffff #epsilon
6
+ #Eps = []
7
+ def initialize rulelist, ts, ns, precs = nil
8
+ @nssize = ns.size
9
+ @precs = precs
10
+ @syms = ns.invert.merge(ts.invert)
11
+ @tla = @syms.size
12
+
13
+ @rulelist = rulelist
14
+ @gh = []; @nssize.times{|i| @gh[i] = []}
15
+ @epr = {}
16
+ @f0e = {}
17
+ @rulelist.each_with_index do |rule, rx|
18
+ rule.g = self
19
+ rule.n = rx
20
+ @gh[rule.l].push rule
21
+ if rule.r.empty?
22
+ @epr[rule.l] = rule.n
23
+ @f0e[rule.l] = { rule.n => [Eps] }
24
+ end
25
+ end
26
+ make_sym_first
27
+ make_sym_f0e
28
+ @closure = {}
29
+ end
30
+
31
+ def make_sym_f0e
32
+ begin
33
+ cnt = false
34
+ @rulelist.each do |rule|
35
+ rl = rule.l
36
+ if r0f0e = @f0e[rule.r[0]]
37
+ @f0e[rl] = {} unless @f0e[rl]
38
+ r0f0e.each do |ern, fst|
39
+ unless @f0e[rl][ern]
40
+ if fst.include? Eps
41
+ @f0e[rl][ern] = fst - [Eps] + first(rule.r[1...rule.r.size])
42
+ else
43
+ @f0e[rl][ern] = fst
44
+ end
45
+ cnt = true
46
+ else
47
+ if fst.include? Eps
48
+ tf = fst - [Eps] + first(rule.r[1...rule.r.size])
49
+ else
50
+ tf = fst
51
+ end
52
+ ss = tf - @f0e[rl][ern]
53
+ unless ss.empty?
54
+ @f0e[rl][ern] |= ss
55
+ cnt = true
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end while cnt
62
+ end
63
+
64
+ def make_sym_first
65
+ @first1 = {@tla => [@tla]}
66
+ @syms.each_key do |s|
67
+ if terms? s
68
+ @first1[s] = [s]
69
+ else
70
+ @first1[s] = []
71
+ @first1[s].push Eps if @epr[s]
72
+ end
73
+ end
74
+ begin
75
+ cnt = false
76
+ @syms.each_key do |s|
77
+ @gh[s].each do |rule|
78
+ rule.r.each do |es|
79
+ ss = @first1[es] - @first1[s]
80
+ unless ss.empty?
81
+ @first1[s] |= ss
82
+ cnt = true
83
+ end
84
+ break unless @first1[es].include? Eps
85
+ end
86
+ unless @first1[s].include? Eps
87
+ if rule.r.all?{|i| @first1[i].include? Eps }
88
+ @first1.push Eps
89
+ cnt = true
90
+ end
91
+ end
92
+ end if nonterms? s
93
+ end
94
+ end while cnt
95
+ end
96
+
97
+ def first p
98
+ r = []
99
+ x = 0
100
+ p.each do |i|
101
+ if i == Eps
102
+ elsif i.class == Array
103
+ i.each do |j|
104
+ r |= @first1[j]
105
+ end
106
+ break unless i.any?{|j| @epr[j] || j==Eps }
107
+ else
108
+ r |= @first1[i]
109
+ break unless @epr[i]
110
+ end
111
+ x += 1
112
+ end
113
+ r -= [Eps]
114
+ r |= [Eps] if x == p.size
115
+ return r
116
+ end
117
+
118
+ def terms? i
119
+ i && i >= @nssize
120
+ end
121
+
122
+ def nonterms? i
123
+ i && i < @nssize
124
+ end
125
+
126
+ def [](n)
127
+ @rulelist[n]
128
+ end
129
+ end
130
+
131
+ class Rule
132
+ attr_accessor :l, :r, :g, :n, :act, :epr, :prec
133
+ def initialize l, r, g = nil, n = nil, act = nil, prec = nil
134
+ @l = l
135
+ @r = r
136
+ @g = g
137
+ @n = n
138
+ @act = act
139
+ @epr = []
140
+ @prec = prec
141
+ end
142
+ def self.[] l, r, prec = nil
143
+ Rule.new l, r, nil, nil, nil, prec
144
+ end
145
+
146
+ def to_s
147
+ r = @r.map{|i| @g.syms[i]}.join(' ')
148
+ "(#{'%03s'%@n}) #{@g.syms[@l]} : #{r}"
149
+ end
150
+
151
+ def hash
152
+ (@l.hash % 37) * (@r.hash % 37)
153
+ end
154
+ def eql? i
155
+ @l == i.l && @r == i.r
156
+ end
157
+ alias == eql?
158
+
159
+ def closure1 n, la
160
+ i = 0
161
+ j = [ LRItem[self, n, la] ]
162
+ h = {j[0] => j.size-1}
163
+
164
+ while i < j.size
165
+ ji = j[i]
166
+ b = ji.rule.r[(ji.n+1) .. ji.rule.r.size]
167
+ b = [] unless b
168
+
169
+ if (x = ji.rule.r[ji.n]) && (a = @g.gh[x])
170
+ a.each do |rule|
171
+ li = LRItem[rule, 0]
172
+ if x = h[li]
173
+ j[x].la.concat @g.first(b + [ji.la])
174
+ else
175
+ li.la = @g.first(b + [ji.la])
176
+ j << li
177
+ h[li] = j.size-1
178
+ end
179
+ end
180
+ end
181
+ i += 1
182
+ end
183
+ j
184
+ end
185
+
186
+ def closure n, base=nil
187
+ i = 0
188
+ j = [base ? base : LRItem[self, n]]
189
+ s = {}
190
+
191
+ while i < j.size
192
+ ji = j[i].rule.r[j[i].n]
193
+ if @g.nonterms?(ji) && !s[ji]
194
+ s[ji] = true
195
+ if @g.closure[ji]
196
+ j.concat @g.closure[ji]
197
+ else
198
+ @g.closure[ji] = []
199
+ @g.gh[ji].each do |rule|
200
+ li = LRItem[rule, 0]
201
+ j.push li
202
+ @g.closure[ji].push li
203
+ end
204
+ end
205
+ end
206
+ i += 1
207
+ end
208
+ j
209
+ end
210
+ end
211
+
212
+ class LRItem
213
+ attr_accessor :rule, :n, :la
214
+ def initialize rule, n, la = []
215
+ @rule = rule
216
+ @n = n
217
+ @la = la
218
+ @goto = {}
219
+ end
220
+ def self.[] rule, n, la = []
221
+ LRItem.new rule, n, la
222
+ end
223
+
224
+ def hash
225
+ (@rule.hash % 37) * (@n.hash % 37)
226
+ end
227
+ def eql? i
228
+ @rule == i.rule && @n == i.n
229
+ end
230
+ alias == eql?
231
+
232
+ def to_s
233
+ la = @la.map{|i| @rule.g.syms[i] ? @rule.g.syms[i] : '$'}.join(' ')
234
+ r = @rule.r.map{|i| @rule.g.syms[i]}.insert(@n, '_').join(' ')
235
+
236
+ "(#{'%03s'%@rule.n}) #{@rule.g.syms[@rule.l]} : #{r} # #{la}"
237
+ end
238
+ def closure1 la
239
+ @rule.closure1 @n, la
240
+ end
241
+ def closure
242
+ @rule.closure @n, self
243
+ end
244
+ def goto x
245
+ return @goto[x] if @goto[x]
246
+ if @rule.r[@n] == x && @n < @rule.r.size
247
+ @goto[x] = I.new [ LRItem[@rule, @n+1] ]
248
+ else
249
+ @goto[x] = I[]
250
+ end
251
+ end
252
+ end
253
+
254
+ class I
255
+ attr_accessor :items, :n
256
+ def initialize items, n = nil
257
+ @items = items
258
+ @goto = {}
259
+ @n = n
260
+ @hash = nil
261
+ @closure = nil
262
+ end
263
+
264
+ def hash
265
+ return @hash if @hash
266
+ @hash = @items.hash
267
+ end
268
+ def eql? i
269
+ @items == i.items
270
+ end
271
+ alias == eql?
272
+
273
+ def to_s
274
+ ("I%03i = " % n) << @items.join("\n"+" "*7)
275
+ #"I#{n}= #{@items.join(' | ')}"
276
+ end
277
+ def empty?
278
+ @items.empty?
279
+ end
280
+ def self.[] items = []
281
+ I.new items
282
+ end
283
+ def closure
284
+ return @closure if @closure
285
+ r = []
286
+ @items.each do |i|
287
+ r |= i.closure
288
+ end
289
+ @closure = r
290
+ end
291
+ def gg
292
+ @goto
293
+ end
294
+ def mkgoto
295
+ r = Hash.new{|h,k| h[k]=[]}
296
+ closure.each do |c|
297
+ if c.n < c.rule.r.size
298
+ r[c.rule.r[c.n]].push LRItem[c.rule, c.n+1]
299
+ end
300
+ end
301
+ rg = []
302
+ r.each do |k, v|
303
+ rg.push [k, (@goto[k] = I.new(v))]
304
+ end
305
+ rg
306
+ end
307
+ def goto x
308
+ return @goto[x] || I.new([])
309
+ end
310
+ end
311
+
312
+ class LALRTable
313
+ attr_accessor :g, :action_table, :goto_table
314
+ attr_accessor :defred_table, :defred_after_shift_table
315
+ def initialize g
316
+ @g = g
317
+ @c = nil
318
+
319
+ items
320
+ mkset
321
+ mktable
322
+ # @g.closure.each{|k,v| warn "#{k} =>"; v.each{|i| warn " #{i}"}}
323
+ # @c.each{|i| warn "#{i}"; i.gg.each{|k,v| warn " #{@g.syms[k]} => #{v}" unless v.empty?}}
324
+ #exit
325
+ end
326
+
327
+ def items
328
+ warn '** mk LR(0) **' if $MP_DEBUG
329
+ n = 0
330
+ m = 0
331
+ c = [ I.new([ LRItem[@g[0], 0] ], 0) ]
332
+ h = {c[0] => m}
333
+
334
+ while n < c.size
335
+ c[n].mkgoto.each do|x, a|
336
+ unless a.empty?
337
+ if ha = h[a]
338
+ c[n].gg[x] = c[ha]
339
+ else
340
+ m += 1
341
+ a.n = m
342
+ c[m] = a
343
+ h[a] = m
344
+ end
345
+ end
346
+ end
347
+ n += 1
348
+ end
349
+ @c = c
350
+ end
351
+
352
+ # -1:reduce sh; 1:shift rd(=key); 0:can't resolve
353
+ def resolveconf(sh, rd)
354
+ precs = @g.precs
355
+ psh = precs[sh]
356
+ mrt = @g[rd].r.reverse.find{|i| @g.terms?(i) }
357
+ prd = @g[rd].prec || precs[mrt]
358
+
359
+ # warn "#{@g.syms[sh]} #{psh.inspect}"
360
+ # warn "#{@g[rd]} #{prd.inspect}"
361
+
362
+ if psh && prd
363
+ if psh[1] == prd[1]
364
+ # warn :LEFT ? 'reduce' : 'shift'
365
+ psh[0] == :LEFT ? -1 : 1
366
+ elsif psh[1] > prd[1]
367
+ # warn 'reduce'
368
+ -1
369
+ else
370
+ # warn 'shift'
371
+ 1
372
+ end
373
+ else
374
+ 0
375
+ end
376
+ end
377
+
378
+ def checkconf newv, oldv, key, g = nil
379
+ return newv unless oldv
380
+ if oldv == 'ACC'
381
+ warn "'ACC' conflict #{g}."
382
+ return oldv
383
+ end
384
+ # warn "\n-- N:#{newv} O:#{oldv} K:#{@g.syms[key]} "
385
+ if newv < 0 and oldv > 0
386
+ # warn "-:shift #{@g.syms[key]} go to #{oldv}"
387
+ r = resolveconf(key, -newv)
388
+ if r > 0
389
+ # warn "+:shift #{@g.syms[key]} go to #{oldv}"
390
+ oldv
391
+ elsif r < 0
392
+ # warn "+:reduce #{@g[-newv]}"
393
+ newv
394
+ else
395
+ warn "shift/reduce conflict #{@g.syms[key]} #{g}."
396
+ oldv
397
+ end
398
+ elsif newv > 0 and oldv < 0
399
+ r = resolveconf(key, -oldv)
400
+ if r > 0
401
+ # warn "shift"
402
+ newv
403
+ elsif r <0
404
+ # warn "reduce"
405
+ oldv
406
+ else
407
+ warn "shift/reduce conflict #{g}."
408
+ newv
409
+ end
410
+ elsif newv < 0 and oldv < 0
411
+ if newv == oldv
412
+ warn "?? newv == oldv == #{newv}."
413
+ newv
414
+ else
415
+ warn "reduce/reduce conflict #{g}."
416
+ newv
417
+ end
418
+ else
419
+ warn "must not happen"
420
+ newv
421
+ end
422
+ end
423
+
424
+ def mktable
425
+ warn '** mk TABLE **' if $MP_DEBUG
426
+ taction = (0...@c.size).map{ Array.new(@g.syms.size - @g.nssize) }
427
+ tgoto = (0...@c.size).map{ Array.new(@g.nssize - 1) }
428
+
429
+ @c.each_with_index do |c, i|
430
+ c.gg.each do |k, j|
431
+ next unless k
432
+ if @g.terms? k
433
+ key = k - @g.nssize
434
+ taction[i][key] = checkconf(j.n, taction[i][key], k, c )
435
+ else
436
+ tgoto[i][k - 1] = j.n
437
+ end
438
+ end
439
+ c.items.each do |j|
440
+ if j.n == j.rule.r.size and j.rule.l != 0 # $start
441
+ j.la.each do |u|
442
+ key = u - @g.nssize
443
+ taction[i][key] = checkconf(-j.rule.n, taction[i][key], u, c)
444
+ end
445
+ elsif efs = @g.f0e[j.rule.r[j.n]]
446
+ efs.each do |rn, ef|
447
+ ef.each do |es|
448
+ #fst = @g.first([es] + j.rule.r[j.n+1 ... j.rule.r.size] + [j.la])
449
+ _h = [es].concat(j.rule.r[j.n+1 ... j.rule.r.size]).push(j.la)
450
+ @g.first(_h).each do |u|
451
+ key = u - @g.nssize
452
+ taction[i][key] = checkconf(-rn, taction[i][key], u, c)
453
+ end
454
+ end
455
+ end
456
+ end
457
+ if j.rule == @g[0] && j.n == 1 # $start : ...
458
+ taction[i][0] = 'ACC'
459
+ end
460
+ end
461
+ end
462
+
463
+ @defred_table = []
464
+ taction.each_with_index do |l, x|
465
+ rs = l.select{|i| i.is_a? Integer}.uniq.compact
466
+ rs = rs.select{|i| i < 0 }
467
+ if rs.size == 1
468
+ @defred_table[x] = rs[0]
469
+ else
470
+ @defred_table[x] = nil
471
+ end
472
+ end
473
+
474
+ @defred_after_shift_table = []
475
+ taction.each_with_index do |l, x|
476
+ rs = l.select{|i| i.is_a? Integer}.uniq.compact
477
+ if rs.size == 1 and rs[0] < 0
478
+ @defred_after_shift_table[x] = rs[0]
479
+ else
480
+ @defred_after_shift_table[x] = nil
481
+ end
482
+ end
483
+
484
+ taction.each_with_index do |l, x|
485
+ if @defred_table[x]
486
+ l.size.times do |x|
487
+ l[x] = nil if l[x] && l[x] < 0
488
+ end
489
+ end
490
+ end
491
+
492
+ @action_table=taction
493
+ @goto_table=tgoto
494
+ put_table if $DEBUG
495
+ end
496
+
497
+ def put_table
498
+ syms, first1, f0e, rulelist = @g.syms, @g.first1, @g.f0e, @g.rulelist
499
+
500
+ s = syms.map{|i| "#{"%03i"%i[0]} #{i[1].inspect}"}.sort.join("\n")
501
+
502
+ f_ = first1.map {|k, v|
503
+ "#{syms[k]} => " << v.map{|i|
504
+ i == G::Eps ? ':eps' : syms[i]
505
+ }.join(' ')
506
+ }.join("\n")
507
+
508
+ e = f0e.map {|k, v|
509
+ "#{syms[k].inspect} => " << v.map{|n, f|
510
+ " #{rulelist[n]} ? " << f.map{|i|
511
+ i == G::Eps ? ':eps' : syms[i].inspect
512
+ }.join(' ')
513
+ }.join("\n")
514
+ }.join("\n")
515
+
516
+ r = rulelist.join("\n")
517
+ c = @c.join("\n")
518
+
519
+ ws = (@g.nssize ... @g.syms.size).map{|i| syms[i].to_s.size}
520
+ ws = ws.map{|i| i < 6 ? 6 : i}
521
+ a = " |"
522
+ (@g.nssize ... @g.syms.size).each_with_index{|i, x|
523
+ a << ("%0#{ws[x]}s|" % @g.syms[i])
524
+ }
525
+ a << " $default|\n"
526
+ @action_table.each_with_index{|i,x|
527
+ a << ("%03i|" % x)
528
+ i.each_with_index{|j, y|
529
+ a << ("%0#{ws[y]}s|" % j)
530
+ }
531
+ a << ("%04s,%04s|\n" % [@defred_table[x], @defred_after_shift_table[x]])
532
+ }
533
+
534
+ ws = (1 ... @g.nssize).map{|i| @g.syms[i].to_s.size}
535
+ ws = ws.map{|i| i < 6 ? 6 : i}
536
+ g = " |"
537
+ (1 ... @g.nssize).each_with_index{|i, x|
538
+ g << ("%0#{ws[x]}s|" % @g.syms[i])
539
+ }
540
+ g << "\n"
541
+ @goto_table.each_with_index{|i,x|
542
+ g << ("%03i|" % x)
543
+ i.each_with_index{|j, y|
544
+ g << ("%0#{ws[y]}s|" % j)
545
+ }
546
+ g << "\n"
547
+ }
548
+
549
+ warn "** SYMS **\n\n#{s}\n\n" <<
550
+ "** FIRST1 **\n\n#{f_}\n\n" <<
551
+ "** Eps Reduce Rule **\n\n#{e}\n\n" <<
552
+ "*** Grammar ***\n\n#{r}\n\n" <<
553
+ "*** States ***\n\n#{c}\n\n" <<
554
+ "*** Action Table ***\n\n#{a}\n" <<
555
+ "*** Goto Table ***\n\n#{g}\n"
556
+ end
557
+
558
+ def mkset
559
+ warn '** cal LA **' if $MP_DEBUG
560
+ trn = []
561
+ @c.each do |ci|
562
+ ci.items.each do |k|
563
+ k.closure1([@g.tla]).each do |j|
564
+ j.la.each do |ai|
565
+ if ai != @g.tla
566
+ ci.goto(j.rule.r[j.n]).items.each do |i|
567
+ if i.rule == j.rule && i.n == j.n+1
568
+ i.la.push ai unless i.la.include?(ai)
569
+ break
570
+ end
571
+ end
572
+ elsif ai == @g.tla
573
+ ci.goto(j.rule.r[j.n]).items.each do |i|
574
+ if i.rule == j.rule && i.n == j.n+1
575
+ trn.push [k, i]
576
+ break
577
+ end
578
+ end
579
+ end
580
+ end
581
+ end
582
+ end
583
+ end
584
+
585
+ #puts 'mk'; mk.each{|k, v| p "#{k}=>#{v}"}
586
+ #puts 'trn',trn.sort{|a,b| a[0].rule.l.to_s <=> b[0].rule.l.to_s}\
587
+ # .map{|a| "#{a[0]} => #{a[1]}"}
588
+
589
+ warn '** mk LALR(1) **' if $MP_DEBUG
590
+ @c[0].items[0].la = [@g.nssize] # '$'
591
+ begin
592
+ change = false
593
+ trn.each do |k, v|
594
+ k.la.each do |i|
595
+ unless v.la.include? i
596
+ change = true
597
+ v.la << i
598
+ end
599
+ end
600
+ end
601
+ end while change
602
+ end
603
+ end
604
+ end