depager 0.1.9

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