racc 1.4.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. data/.gitattributes +2 -0
  2. data/.gitignore +7 -0
  3. data/COPYING +515 -0
  4. data/ChangeLog +846 -0
  5. data/DEPENDS +4 -0
  6. data/README.en.rdoc +86 -0
  7. data/README.ja.rdoc +96 -0
  8. data/Rakefile +15 -0
  9. data/TODO +5 -0
  10. data/bin/racc +308 -0
  11. data/bin/racc2y +195 -0
  12. data/bin/y2racc +339 -0
  13. data/doc/en/NEWS.en.rdoc +282 -0
  14. data/doc/en/command.en.html +78 -0
  15. data/doc/en/debug.en.rdoc +20 -0
  16. data/doc/en/grammar.en.rdoc +230 -0
  17. data/doc/en/index.en.html +10 -0
  18. data/doc/en/parser.en.rdoc +74 -0
  19. data/doc/en/usage.en.html +92 -0
  20. data/doc/ja/NEWS.ja.rdoc +307 -0
  21. data/doc/ja/command.ja.html +94 -0
  22. data/doc/ja/debug.ja.rdoc +36 -0
  23. data/doc/ja/grammar.ja.rdoc +348 -0
  24. data/doc/ja/index.ja.html +10 -0
  25. data/doc/ja/parser.ja.rdoc +125 -0
  26. data/doc/ja/usage.ja.html +414 -0
  27. data/ext/racc/cparse/MANIFEST +4 -0
  28. data/ext/racc/cparse/cparse.c +824 -0
  29. data/ext/racc/cparse/depend +1 -0
  30. data/ext/racc/cparse/extconf.rb +7 -0
  31. data/fastcache/extconf.rb +2 -0
  32. data/fastcache/fastcache.c +185 -0
  33. data/lib/racc.rb +6 -0
  34. data/lib/racc/compat.rb +40 -0
  35. data/lib/racc/debugflags.rb +59 -0
  36. data/lib/racc/exception.rb +15 -0
  37. data/lib/racc/grammar.rb +1115 -0
  38. data/lib/racc/grammarfileparser.rb +559 -0
  39. data/lib/racc/info.rb +16 -0
  40. data/lib/racc/iset.rb +91 -0
  41. data/lib/racc/logfilegenerator.rb +214 -0
  42. data/lib/racc/parser.rb +439 -0
  43. data/lib/racc/parserfilegenerator.rb +511 -0
  44. data/lib/racc/pre-setup +13 -0
  45. data/lib/racc/sourcetext.rb +34 -0
  46. data/lib/racc/state.rb +971 -0
  47. data/lib/racc/statetransitiontable.rb +316 -0
  48. data/lib/racc/static.rb +5 -0
  49. data/misc/dist.sh +31 -0
  50. data/sample/array.y +67 -0
  51. data/sample/array2.y +59 -0
  52. data/sample/calc-ja.y +66 -0
  53. data/sample/calc.y +65 -0
  54. data/sample/conflict.y +15 -0
  55. data/sample/hash.y +60 -0
  56. data/sample/lalr.y +17 -0
  57. data/sample/lists.y +57 -0
  58. data/sample/syntax.y +46 -0
  59. data/sample/yyerr.y +46 -0
  60. data/setup.rb +1587 -0
  61. data/tasks/doc.rb +12 -0
  62. data/tasks/email.rb +55 -0
  63. data/tasks/file.rb +37 -0
  64. data/tasks/gem.rb +37 -0
  65. data/tasks/test.rb +16 -0
  66. data/test/assets/chk.y +126 -0
  67. data/test/assets/conf.y +16 -0
  68. data/test/assets/digraph.y +29 -0
  69. data/test/assets/echk.y +118 -0
  70. data/test/assets/err.y +60 -0
  71. data/test/assets/expect.y +7 -0
  72. data/test/assets/firstline.y +4 -0
  73. data/test/assets/ichk.y +102 -0
  74. data/test/assets/intp.y +546 -0
  75. data/test/assets/mailp.y +437 -0
  76. data/test/assets/newsyn.y +25 -0
  77. data/test/assets/noend.y +4 -0
  78. data/test/assets/nonass.y +41 -0
  79. data/test/assets/normal.y +27 -0
  80. data/test/assets/norule.y +4 -0
  81. data/test/assets/nullbug1.y +25 -0
  82. data/test/assets/nullbug2.y +15 -0
  83. data/test/assets/opt.y +123 -0
  84. data/test/assets/percent.y +35 -0
  85. data/test/assets/recv.y +97 -0
  86. data/test/assets/rrconf.y +14 -0
  87. data/test/assets/scan.y +72 -0
  88. data/test/assets/syntax.y +50 -0
  89. data/test/assets/unterm.y +5 -0
  90. data/test/assets/useless.y +12 -0
  91. data/test/assets/yyerr.y +46 -0
  92. data/test/bench.y +36 -0
  93. data/test/helper.rb +88 -0
  94. data/test/infini.y +8 -0
  95. data/test/scandata/brace +7 -0
  96. data/test/scandata/gvar +1 -0
  97. data/test/scandata/normal +4 -0
  98. data/test/scandata/percent +18 -0
  99. data/test/scandata/slash +10 -0
  100. data/test/src.intp +34 -0
  101. data/test/start.y +20 -0
  102. data/test/test_chk_y.rb +51 -0
  103. data/test/test_grammar_file_parser.rb +15 -0
  104. data/test/test_racc_command.rb +155 -0
  105. data/test/test_scan_y.rb +51 -0
  106. data/test/testscanner.rb +51 -0
  107. data/web/racc.en.rhtml +42 -0
  108. data/web/racc.ja.rhtml +51 -0
  109. metadata +166 -0
@@ -0,0 +1,13 @@
1
+ def generate_parser_text_rb(target)
2
+ return if File.exist?(srcfile(target))
3
+ $stderr.puts "generating #{target}..."
4
+ File.open(target, 'w') {|f|
5
+ f.puts "module Racc"
6
+ f.puts " PARSER_TEXT = <<'__end_of_file__'"
7
+ f.puts File.read(srcfile('parser.rb'))
8
+ f.puts "__end_of_file__"
9
+ f.puts "end"
10
+ }
11
+ end
12
+
13
+ generate_parser_text_rb 'parser-text.rb'
@@ -0,0 +1,34 @@
1
+ #
2
+ # $Id$
3
+ #
4
+ # Copyright (c) 1999-2006 Minero Aoki
5
+ #
6
+ # This program is free software.
7
+ # You can distribute/modify this program under the terms of
8
+ # the GNU LGPL, Lesser General Public License version 2.1.
9
+ # For details of LGPL, see the file "COPYING".
10
+ #
11
+
12
+ module Racc
13
+
14
+ class SourceText
15
+ def initialize(text, filename, lineno)
16
+ @text = text
17
+ @filename = filename
18
+ @lineno = lineno
19
+ end
20
+
21
+ attr_reader :text
22
+ attr_reader :filename
23
+ attr_reader :lineno
24
+
25
+ def to_s
26
+ "#<SourceText #{location()}>"
27
+ end
28
+
29
+ def location
30
+ "#{@filename}:#{@lineno}"
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,971 @@
1
+ #
2
+ # $Id$
3
+ #
4
+ # Copyright (c) 1999-2006 Minero Aoki
5
+ #
6
+ # This program is free software.
7
+ # You can distribute/modify this program under the terms of
8
+ # the GNU LGPL, Lesser General Public License version 2.1.
9
+ # For details of the GNU LGPL, see the file "COPYING".
10
+ #
11
+
12
+ require 'racc/iset'
13
+ require 'racc/statetransitiontable'
14
+ require 'racc/exception'
15
+ require 'forwardable'
16
+
17
+ module Racc
18
+
19
+ # A table of LALR states.
20
+ class States
21
+
22
+ include Enumerable
23
+
24
+ def initialize(grammar, debug_flags = DebugFlags.new)
25
+ @grammar = grammar
26
+ @symboltable = grammar.symboltable
27
+ @d_state = debug_flags.state
28
+ @d_la = debug_flags.la
29
+ @d_prec = debug_flags.prec
30
+ @states = []
31
+ @statecache = {}
32
+ @actions = ActionTable.new(@grammar, self)
33
+ @nfa_computed = false
34
+ @dfa_computed = false
35
+ end
36
+
37
+ attr_reader :grammar
38
+ attr_reader :actions
39
+
40
+ def size
41
+ @states.size
42
+ end
43
+
44
+ def inspect
45
+ '#<state table>'
46
+ end
47
+
48
+ alias to_s inspect
49
+
50
+ def [](i)
51
+ @states[i]
52
+ end
53
+
54
+ def each_state(&block)
55
+ @states.each(&block)
56
+ end
57
+
58
+ alias each each_state
59
+
60
+ def each_index(&block)
61
+ @states.each_index(&block)
62
+ end
63
+
64
+ extend Forwardable
65
+
66
+ def_delegator "@actions", :shift_n
67
+ def_delegator "@actions", :reduce_n
68
+ def_delegator "@actions", :nt_base
69
+
70
+ def should_report_srconflict?
71
+ srconflict_exist? and
72
+ (n_srconflicts() != @grammar.n_expected_srconflicts)
73
+ end
74
+
75
+ def srconflict_exist?
76
+ n_srconflicts() != 0
77
+ end
78
+
79
+ def n_srconflicts
80
+ @n_srconflicts ||= inject(0) {|sum, st| sum + st.n_srconflicts }
81
+ end
82
+
83
+ def rrconflict_exist?
84
+ n_rrconflicts() != 0
85
+ end
86
+
87
+ def n_rrconflicts
88
+ @n_rrconflicts ||= inject(0) {|sum, st| sum + st.n_rrconflicts }
89
+ end
90
+
91
+ def state_transition_table
92
+ @state_transition_table ||= StateTransitionTable.generate(self.dfa)
93
+ end
94
+
95
+ #
96
+ # NFA (Non-deterministic Finite Automaton) Computation
97
+ #
98
+
99
+ public
100
+
101
+ def nfa
102
+ return self if @nfa_computed
103
+ compute_nfa
104
+ @nfa_computed = true
105
+ self
106
+ end
107
+
108
+ private
109
+
110
+ def compute_nfa
111
+ @grammar.init
112
+ # add state 0
113
+ core_to_state [ @grammar[0].ptrs[0] ]
114
+ # generate LALR states
115
+ cur = 0
116
+ @gotos = []
117
+ while cur < @states.size
118
+ generate_states @states[cur] # state is added here
119
+ cur += 1
120
+ end
121
+ @actions.init
122
+ end
123
+
124
+ def generate_states(state)
125
+ puts "dstate: #{state}" if @d_state
126
+
127
+ table = {}
128
+ state.closure.each do |ptr|
129
+ if sym = ptr.dereference
130
+ addsym table, sym, ptr.next
131
+ end
132
+ end
133
+ table.each do |sym, core|
134
+ puts "dstate: sym=#{sym} ncore=#{core}" if @d_state
135
+
136
+ dest = core_to_state(core.to_a)
137
+ state.goto_table[sym] = dest
138
+ id = sym.nonterminal?() ? @gotos.size : nil
139
+ g = Goto.new(id, sym, state, dest)
140
+ @gotos.push g if sym.nonterminal?
141
+ state.gotos[sym] = g
142
+ puts "dstate: #{state.ident} --#{sym}--> #{dest.ident}" if @d_state
143
+
144
+ # check infinite recursion
145
+ if state.ident == dest.ident and state.closure.size == 1
146
+ raise CompileError,
147
+ sprintf("Infinite recursion: state %d, with rule %d",
148
+ state.ident, state.ptrs[0].rule.ident)
149
+ end
150
+ end
151
+ end
152
+
153
+ def addsym(table, sym, ptr)
154
+ unless s = table[sym]
155
+ table[sym] = s = ISet.new
156
+ end
157
+ s.add ptr
158
+ end
159
+
160
+ def core_to_state(core)
161
+ #
162
+ # convert CORE to a State object.
163
+ # If matching state does not exist, create it and add to the table.
164
+ #
165
+
166
+ k = fingerprint(core)
167
+ unless dest = @statecache[k]
168
+ # not registered yet
169
+ dest = State.new(@states.size, core)
170
+ @states.push dest
171
+
172
+ @statecache[k] = dest
173
+
174
+ puts "core_to_state: create state ID #{dest.ident}" if @d_state
175
+ else
176
+ if @d_state
177
+ puts "core_to_state: dest is cached ID #{dest.ident}"
178
+ puts "core_to_state: dest core #{dest.core.join(' ')}"
179
+ end
180
+ end
181
+
182
+ dest
183
+ end
184
+
185
+ def fingerprint(arr)
186
+ arr.map {|i| i.ident }.pack('L*')
187
+ end
188
+
189
+ #
190
+ # DFA (Deterministic Finite Automaton) Generation
191
+ #
192
+
193
+ public
194
+
195
+ def dfa
196
+ return self if @dfa_computed
197
+ nfa
198
+ compute_dfa
199
+ @dfa_computed = true
200
+ self
201
+ end
202
+
203
+ private
204
+
205
+ def compute_dfa
206
+ la = lookahead()
207
+ @states.each do |state|
208
+ state.la = la
209
+ resolve state
210
+ end
211
+ set_accept
212
+ @states.each do |state|
213
+ pack state
214
+ end
215
+ check_useless
216
+ end
217
+
218
+ def lookahead
219
+ #
220
+ # lookahead algorithm ver.3 -- from bison 1.26
221
+ #
222
+
223
+ gotos = @gotos
224
+ if @d_la
225
+ puts "\n--- goto ---"
226
+ gotos.each_with_index {|g, i| print i, ' '; p g }
227
+ end
228
+
229
+ ### initialize_LA()
230
+ ### set_goto_map()
231
+ la_rules = []
232
+ @states.each do |state|
233
+ state.check_la la_rules
234
+ end
235
+
236
+ ### initialize_F()
237
+ f = create_tmap(gotos.size)
238
+ reads = []
239
+ edge = []
240
+ gotos.each do |goto|
241
+ goto.to_state.goto_table.each do |t, st|
242
+ if t.terminal?
243
+ f[goto.ident] |= (1 << t.ident)
244
+ elsif t.nullable?
245
+ edge.push goto.to_state.gotos[t].ident
246
+ end
247
+ end
248
+ if edge.empty?
249
+ reads.push nil
250
+ else
251
+ reads.push edge
252
+ edge = []
253
+ end
254
+ end
255
+ digraph f, reads
256
+ if @d_la
257
+ puts "\n--- F1 (reads) ---"
258
+ print_tab gotos, reads, f
259
+ end
260
+
261
+ ### build_relations()
262
+ ### compute_FOLLOWS
263
+ path = nil
264
+ edge = []
265
+ lookback = Array.new(la_rules.size, nil)
266
+ includes = []
267
+ gotos.each do |goto|
268
+ goto.symbol.heads.each do |ptr|
269
+ path = record_path(goto.from_state, ptr.rule)
270
+ lastgoto = path.last
271
+ st = lastgoto ? lastgoto.to_state : goto.from_state
272
+ if st.conflict?
273
+ addrel lookback, st.rruleid(ptr.rule), goto
274
+ end
275
+ path.reverse_each do |g|
276
+ break if g.symbol.terminal?
277
+ edge.push g.ident
278
+ break unless g.symbol.nullable?
279
+ end
280
+ end
281
+ if edge.empty?
282
+ includes.push nil
283
+ else
284
+ includes.push edge
285
+ edge = []
286
+ end
287
+ end
288
+ includes = transpose(includes)
289
+ digraph f, includes
290
+ if @d_la
291
+ puts "\n--- F2 (includes) ---"
292
+ print_tab gotos, includes, f
293
+ end
294
+
295
+ ### compute_lookaheads
296
+ la = create_tmap(la_rules.size)
297
+ lookback.each_with_index do |arr, i|
298
+ if arr
299
+ arr.each do |g|
300
+ la[i] |= f[g.ident]
301
+ end
302
+ end
303
+ end
304
+ if @d_la
305
+ puts "\n--- LA (lookback) ---"
306
+ print_tab la_rules, lookback, la
307
+ end
308
+
309
+ la
310
+ end
311
+
312
+ def create_tmap(size)
313
+ Array.new(size, 0) # use Integer as bitmap
314
+ end
315
+
316
+ def addrel(tbl, i, item)
317
+ if a = tbl[i]
318
+ a.push item
319
+ else
320
+ tbl[i] = [item]
321
+ end
322
+ end
323
+
324
+ def record_path(begst, rule)
325
+ st = begst
326
+ path = []
327
+ rule.symbols.each do |t|
328
+ goto = st.gotos[t]
329
+ path.push goto
330
+ st = goto.to_state
331
+ end
332
+ path
333
+ end
334
+
335
+ def transpose(rel)
336
+ new = Array.new(rel.size, nil)
337
+ rel.each_with_index do |arr, idx|
338
+ if arr
339
+ arr.each do |i|
340
+ addrel new, i, idx
341
+ end
342
+ end
343
+ end
344
+ new
345
+ end
346
+
347
+ def digraph(map, relation)
348
+ n = relation.size
349
+ index = Array.new(n, nil)
350
+ vertices = []
351
+ @infinity = n + 2
352
+
353
+ index.each_index do |i|
354
+ if not index[i] and relation[i]
355
+ traverse i, index, vertices, map, relation
356
+ end
357
+ end
358
+ end
359
+
360
+ def traverse(i, index, vertices, map, relation)
361
+ vertices.push i
362
+ index[i] = height = vertices.size
363
+
364
+ if rp = relation[i]
365
+ rp.each do |proci|
366
+ unless index[proci]
367
+ traverse proci, index, vertices, map, relation
368
+ end
369
+ if index[i] > index[proci]
370
+ # circulative recursion !!!
371
+ index[i] = index[proci]
372
+ end
373
+ map[i] |= map[proci]
374
+ end
375
+ end
376
+
377
+ if index[i] == height
378
+ while true
379
+ proci = vertices.pop
380
+ index[proci] = @infinity
381
+ break if i == proci
382
+
383
+ map[proci] |= map[i]
384
+ end
385
+ end
386
+ end
387
+
388
+ # for debug
389
+ def print_atab(idx, tab)
390
+ tab.each_with_index do |i,ii|
391
+ printf '%-20s', idx[ii].inspect
392
+ p i
393
+ end
394
+ end
395
+
396
+ def print_tab(idx, rel, tab)
397
+ tab.each_with_index do |bin,i|
398
+ print i, ' ', idx[i].inspect, ' << '; p rel[i]
399
+ print ' '
400
+ each_t(@symboltable, bin) {|t| print ' ', t }
401
+ puts
402
+ end
403
+ end
404
+
405
+ # for debug
406
+ def print_tab_i(idx, rel, tab, i)
407
+ bin = tab[i]
408
+ print i, ' ', idx[i].inspect, ' << '; p rel[i]
409
+ print ' '
410
+ each_t(@symboltable, bin) {|t| print ' ', t }
411
+ end
412
+
413
+ # for debug
414
+ def printb(i)
415
+ each_t(@symboltable, i) do |t|
416
+ print t, ' '
417
+ end
418
+ puts
419
+ end
420
+
421
+ def each_t(tbl, set)
422
+ 0.upto( set.size ) do |i|
423
+ (0..7).each do |ii|
424
+ if set[idx = i * 8 + ii] == 1
425
+ yield tbl[idx]
426
+ end
427
+ end
428
+ end
429
+ end
430
+
431
+ #
432
+ # resolve
433
+ #
434
+
435
+ def resolve(state)
436
+ if state.conflict?
437
+ resolve_rr state, state.ritems
438
+ resolve_sr state, state.stokens
439
+ else
440
+ if state.rrules.empty?
441
+ # shift
442
+ state.stokens.each do |t|
443
+ state.action[t] = @actions.shift(state.goto_table[t])
444
+ end
445
+ else
446
+ # reduce
447
+ state.defact = @actions.reduce(state.rrules[0])
448
+ end
449
+ end
450
+ end
451
+
452
+ def resolve_rr(state, r)
453
+ r.each do |item|
454
+ item.each_la(@symboltable) do |t|
455
+ act = state.action[t]
456
+ if act
457
+ unless act.kind_of?(Reduce)
458
+ raise "racc: fatal: #{act.class} in action table"
459
+ end
460
+ # Cannot resolve R/R conflict (on t).
461
+ # Reduce with upper rule as default.
462
+ state.rr_conflict act.rule, item.rule, t
463
+ else
464
+ # No conflict.
465
+ state.action[t] = @actions.reduce(item.rule)
466
+ end
467
+ end
468
+ end
469
+ end
470
+
471
+ def resolve_sr(state, s)
472
+ s.each do |stok|
473
+ goto = state.goto_table[stok]
474
+ act = state.action[stok]
475
+
476
+ unless act
477
+ # no conflict
478
+ state.action[stok] = @actions.shift(goto)
479
+ else
480
+ unless act.kind_of?(Reduce)
481
+ puts 'DEBUG -------------------------------'
482
+ p stok
483
+ p act
484
+ state.action.each do |k,v|
485
+ print k.inspect, ' ', v.inspect, "\n"
486
+ end
487
+ raise "racc: fatal: #{act.class} in action table"
488
+ end
489
+
490
+ # conflict on stok
491
+
492
+ rtok = act.rule.precedence
493
+ case do_resolve_sr(stok, rtok)
494
+ when :Reduce
495
+ # action is already set
496
+
497
+ when :Shift
498
+ # overwrite
499
+ act.decref
500
+ state.action[stok] = @actions.shift(goto)
501
+
502
+ when :Error
503
+ act.decref
504
+ state.action[stok] = @actions.error
505
+
506
+ when :CantResolve
507
+ # shift as default
508
+ act.decref
509
+ state.action[stok] = @actions.shift(goto)
510
+ state.sr_conflict stok, act.rule
511
+ end
512
+ end
513
+ end
514
+ end
515
+
516
+ ASSOC = {
517
+ :Left => :Reduce,
518
+ :Right => :Shift,
519
+ :Nonassoc => :Error
520
+ }
521
+
522
+ def do_resolve_sr(stok, rtok)
523
+ puts "resolve_sr: s/r conflict: rtok=#{rtok}, stok=#{stok}" if @d_prec
524
+
525
+ unless rtok and rtok.precedence
526
+ puts "resolve_sr: no prec for #{rtok}(R)" if @d_prec
527
+ return :CantResolve
528
+ end
529
+ rprec = rtok.precedence
530
+
531
+ unless stok and stok.precedence
532
+ puts "resolve_sr: no prec for #{stok}(S)" if @d_prec
533
+ return :CantResolve
534
+ end
535
+ sprec = stok.precedence
536
+
537
+ ret = if rprec == sprec
538
+ ASSOC[rtok.assoc] or
539
+ raise "racc: fatal: #{rtok}.assoc is not Left/Right/Nonassoc"
540
+ else
541
+ (rprec > sprec) ? (:Reduce) : (:Shift)
542
+ end
543
+
544
+ puts "resolve_sr: resolved as #{ret.id2name}" if @d_prec
545
+ ret
546
+ end
547
+
548
+ #
549
+ # complete
550
+ #
551
+
552
+ def set_accept
553
+ anch = @symboltable.anchor
554
+ init_state = @states[0].goto_table[@grammar.start]
555
+ targ_state = init_state.action[anch].goto_state
556
+ acc_state = targ_state.action[anch].goto_state
557
+
558
+ acc_state.action.clear
559
+ acc_state.goto_table.clear
560
+ acc_state.defact = @actions.accept
561
+ end
562
+
563
+ def pack(state)
564
+ ### find most frequently used reduce rule
565
+ act = state.action
566
+ arr = Array.new(@grammar.size, 0)
567
+ act.each do |t, a|
568
+ arr[a.ruleid] += 1 if a.kind_of?(Reduce)
569
+ end
570
+ i = arr.max
571
+ s = (i > 0) ? arr.index(i) : nil
572
+
573
+ ### set & delete default action
574
+ if s
575
+ r = @actions.reduce(s)
576
+ if not state.defact or state.defact == r
577
+ act.delete_if {|t, a| a == r }
578
+ state.defact = r
579
+ end
580
+ else
581
+ state.defact ||= @actions.error
582
+ end
583
+ end
584
+
585
+ def check_useless
586
+ used = []
587
+ @actions.each_reduce do |act|
588
+ if not act or act.refn == 0
589
+ act.rule.useless = true
590
+ else
591
+ t = act.rule.target
592
+ used[t.ident] = t
593
+ end
594
+ end
595
+ @symboltable.nt_base.upto(@symboltable.nt_max - 1) do |n|
596
+ unless used[n]
597
+ @symboltable[n].useless = true
598
+ end
599
+ end
600
+ end
601
+
602
+ end # class StateTable
603
+
604
+
605
+ # A LALR state.
606
+ class State
607
+
608
+ def initialize(ident, core)
609
+ @ident = ident
610
+ @core = core
611
+ @goto_table = {}
612
+ @gotos = {}
613
+ @stokens = nil
614
+ @ritems = nil
615
+ @action = {}
616
+ @defact = nil
617
+ @rrconf = nil
618
+ @srconf = nil
619
+
620
+ @closure = make_closure(@core)
621
+ end
622
+
623
+ attr_reader :ident
624
+ alias stateid ident
625
+ alias hash ident
626
+
627
+ attr_reader :core
628
+ attr_reader :closure
629
+
630
+ attr_reader :goto_table
631
+ attr_reader :gotos
632
+
633
+ attr_reader :stokens
634
+ attr_reader :ritems
635
+ attr_reader :rrules
636
+
637
+ attr_reader :action
638
+ attr_accessor :defact # default action
639
+
640
+ attr_reader :rrconf
641
+ attr_reader :srconf
642
+
643
+ def inspect
644
+ "<state #{@ident}>"
645
+ end
646
+
647
+ alias to_s inspect
648
+
649
+ def ==(oth)
650
+ @ident == oth.ident
651
+ end
652
+
653
+ alias eql? ==
654
+
655
+ def make_closure(core)
656
+ set = ISet.new
657
+ core.each do |ptr|
658
+ set.add ptr
659
+ if t = ptr.dereference and t.nonterminal?
660
+ set.update_a t.expand
661
+ end
662
+ end
663
+ set.to_a
664
+ end
665
+
666
+ def check_la(la_rules)
667
+ @conflict = false
668
+ s = []
669
+ r = []
670
+ @closure.each do |ptr|
671
+ if t = ptr.dereference
672
+ if t.terminal?
673
+ s[t.ident] = t
674
+ if t.ident == 1 # $error
675
+ @conflict = true
676
+ end
677
+ end
678
+ else
679
+ r.push ptr.rule
680
+ end
681
+ end
682
+ unless r.empty?
683
+ if not s.empty? or r.size > 1
684
+ @conflict = true
685
+ end
686
+ end
687
+ s.compact!
688
+ @stokens = s
689
+ @rrules = r
690
+
691
+ if @conflict
692
+ @la_rules_i = la_rules.size
693
+ @la_rules = r.map {|i| i.ident }
694
+ la_rules.concat r
695
+ else
696
+ @la_rules_i = @la_rules = nil
697
+ end
698
+ end
699
+
700
+ def conflict?
701
+ @conflict
702
+ end
703
+
704
+ def rruleid(rule)
705
+ if i = @la_rules.index(rule.ident)
706
+ @la_rules_i + i
707
+ else
708
+ puts '/// rruleid'
709
+ p self
710
+ p rule
711
+ p @rrules
712
+ p @la_rules_i
713
+ raise 'racc: fatal: cannot get reduce rule id'
714
+ end
715
+ end
716
+
717
+ def la=(la)
718
+ return unless @conflict
719
+ i = @la_rules_i
720
+ @ritems = r = []
721
+ @rrules.each do |rule|
722
+ r.push Item.new(rule, la[i])
723
+ i += 1
724
+ end
725
+ end
726
+
727
+ def rr_conflict(high, low, ctok)
728
+ c = RRconflict.new(@ident, high, low, ctok)
729
+
730
+ @rrconf ||= {}
731
+ if a = @rrconf[ctok]
732
+ a.push c
733
+ else
734
+ @rrconf[ctok] = [c]
735
+ end
736
+ end
737
+
738
+ def sr_conflict(shift, reduce)
739
+ c = SRconflict.new(@ident, shift, reduce)
740
+
741
+ @srconf ||= {}
742
+ if a = @srconf[shift]
743
+ a.push c
744
+ else
745
+ @srconf[shift] = [c]
746
+ end
747
+ end
748
+
749
+ def n_srconflicts
750
+ @srconf ? @srconf.size : 0
751
+ end
752
+
753
+ def n_rrconflicts
754
+ @rrconf ? @rrconf.size : 0
755
+ end
756
+
757
+ end # class State
758
+
759
+
760
+ #
761
+ # Represents a transition on the grammar.
762
+ # "Real goto" means a transition by nonterminal,
763
+ # but this class treats also terminal's.
764
+ # If one is a terminal transition, .ident returns nil.
765
+ #
766
+ class Goto
767
+ def initialize(ident, sym, from, to)
768
+ @ident = ident
769
+ @symbol = sym
770
+ @from_state = from
771
+ @to_state = to
772
+ end
773
+
774
+ attr_reader :ident
775
+ attr_reader :symbol
776
+ attr_reader :from_state
777
+ attr_reader :to_state
778
+
779
+ def inspect
780
+ "(#{@from_state.ident}-#{@symbol}->#{@to_state.ident})"
781
+ end
782
+ end
783
+
784
+
785
+ # LALR item. A set of rule and its lookahead tokens.
786
+ class Item
787
+ def initialize(rule, la)
788
+ @rule = rule
789
+ @la = la
790
+ end
791
+
792
+ attr_reader :rule
793
+ attr_reader :la
794
+
795
+ def each_la(tbl)
796
+ la = @la
797
+ 0.upto(la.size - 1) do |i|
798
+ (0..7).each do |ii|
799
+ if la[idx = i * 8 + ii] == 1
800
+ yield tbl[idx]
801
+ end
802
+ end
803
+ end
804
+ end
805
+ end
806
+
807
+
808
+ # The table of LALR actions. Actions are either of
809
+ # Shift, Reduce, Accept and Error.
810
+ class ActionTable
811
+
812
+ def initialize(rt, st)
813
+ @grammar = rt
814
+ @statetable = st
815
+
816
+ @reduce = []
817
+ @shift = []
818
+ @accept = nil
819
+ @error = nil
820
+ end
821
+
822
+ def init
823
+ @grammar.each do |rule|
824
+ @reduce.push Reduce.new(rule)
825
+ end
826
+ @statetable.each do |state|
827
+ @shift.push Shift.new(state)
828
+ end
829
+ @accept = Accept.new
830
+ @error = Error.new
831
+ end
832
+
833
+ def reduce_n
834
+ @reduce.size
835
+ end
836
+
837
+ def reduce(i)
838
+ case i
839
+ when Rule then i = i.ident
840
+ when Integer then ;
841
+ else
842
+ raise "racc: fatal: wrong class #{i.class} for reduce"
843
+ end
844
+
845
+ r = @reduce[i] or raise "racc: fatal: reduce action #{i.inspect} not exist"
846
+ r.incref
847
+ r
848
+ end
849
+
850
+ def each_reduce(&block)
851
+ @reduce.each(&block)
852
+ end
853
+
854
+ def shift_n
855
+ @shift.size
856
+ end
857
+
858
+ def shift(i)
859
+ case i
860
+ when State then i = i.ident
861
+ when Integer then ;
862
+ else
863
+ raise "racc: fatal: wrong class #{i.class} for shift"
864
+ end
865
+
866
+ @shift[i] or raise "racc: fatal: shift action #{i} does not exist"
867
+ end
868
+
869
+ def each_shift(&block)
870
+ @shift.each(&block)
871
+ end
872
+
873
+ attr_reader :accept
874
+ attr_reader :error
875
+
876
+ end
877
+
878
+
879
+ class Shift
880
+ def initialize(goto)
881
+ @goto_state = goto
882
+ end
883
+
884
+ attr_reader :goto_state
885
+
886
+ def goto_id
887
+ @goto_state.ident
888
+ end
889
+
890
+ def inspect
891
+ "<shift #{@goto_state.ident}>"
892
+ end
893
+ end
894
+
895
+
896
+ class Reduce
897
+ def initialize(rule)
898
+ @rule = rule
899
+ @refn = 0
900
+ end
901
+
902
+ attr_reader :rule
903
+ attr_reader :refn
904
+
905
+ def ruleid
906
+ @rule.ident
907
+ end
908
+
909
+ def inspect
910
+ "<reduce #{@rule.ident}>"
911
+ end
912
+
913
+ def incref
914
+ @refn += 1
915
+ end
916
+
917
+ def decref
918
+ @refn -= 1
919
+ raise 'racc: fatal: act.refn < 0' if @refn < 0
920
+ end
921
+ end
922
+
923
+ class Accept
924
+ def inspect
925
+ "<accept>"
926
+ end
927
+ end
928
+
929
+ class Error
930
+ def inspect
931
+ "<error>"
932
+ end
933
+ end
934
+
935
+ class SRconflict
936
+ def initialize(sid, shift, reduce)
937
+ @stateid = sid
938
+ @shift = shift
939
+ @reduce = reduce
940
+ end
941
+
942
+ attr_reader :stateid
943
+ attr_reader :shift
944
+ attr_reader :reduce
945
+
946
+ def to_s
947
+ sprintf('state %d: S/R conflict rule %d reduce and shift %s',
948
+ @stateid, @reduce.ruleid, @shift.to_s)
949
+ end
950
+ end
951
+
952
+ class RRconflict
953
+ def initialize(sid, high, low, tok)
954
+ @stateid = sid
955
+ @high_prec = high
956
+ @low_prec = low
957
+ @token = tok
958
+ end
959
+
960
+ attr_reader :stateid
961
+ attr_reader :high_prec
962
+ attr_reader :low_prec
963
+ attr_reader :token
964
+
965
+ def to_s
966
+ sprintf('state %d: R/R conflict with rule %d and %d on %s',
967
+ @stateid, @high_prec.ident, @low_prec.ident, @token.to_s)
968
+ end
969
+ end
970
+
971
+ end