Parent

Included Modules

Racc::States

A table of LALR states.

Constants

ASSOC

Attributes

grammar[R]
actions[R]

Public Class Methods

new(grammar, debug_flags = DebugFlags.new) click to toggle source
    # File lib/racc/state.rb, line 24
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

Public Instance Methods

[](i) click to toggle source
    # File lib/racc/state.rb, line 50
50:     def [](i)
51:       @states[i]
52:     end
dfa() click to toggle source

DFA (Deterministic Finite Automaton) Generation

     # File lib/racc/state.rb, line 195
195:     def dfa
196:       return self if @dfa_computed
197:       nfa
198:       compute_dfa
199:       @dfa_computed = true
200:       self
201:     end
each(&block) click to toggle source
Alias for: each_state
each_index(&block) click to toggle source
    # File lib/racc/state.rb, line 60
60:     def each_index(&block)
61:       @states.each_index(&block)
62:     end
each_state(&block) click to toggle source
    # File lib/racc/state.rb, line 54
54:     def each_state(&block)
55:       @states.each(&block)
56:     end
Also aliased as: each
inspect() click to toggle source
    # File lib/racc/state.rb, line 44
44:     def inspect
45:       '#<state table>'
46:     end
Also aliased as: to_s
n_rrconflicts() click to toggle source
    # File lib/racc/state.rb, line 87
87:     def n_rrconflicts
88:       @n_rrconflicts ||= inject(0) {|sum, st| sum + st.n_rrconflicts }
89:     end
n_srconflicts() click to toggle source
    # File lib/racc/state.rb, line 79
79:     def n_srconflicts
80:       @n_srconflicts ||= inject(0) {|sum, st| sum + st.n_srconflicts }
81:     end
nfa() click to toggle source

NFA (Non-deterministic Finite Automaton) Computation

     # File lib/racc/state.rb, line 101
101:     def nfa
102:       return self if @nfa_computed
103:       compute_nfa
104:       @nfa_computed = true
105:       self
106:     end
rrconflict_exist?() click to toggle source
    # File lib/racc/state.rb, line 83
83:     def rrconflict_exist?
84:       n_rrconflicts() != 0
85:     end
should_report_srconflict?() click to toggle source
    # File lib/racc/state.rb, line 70
70:     def should_report_srconflict?
71:       srconflict_exist? and
72:           (n_srconflicts() != @grammar.n_expected_srconflicts)
73:     end
size() click to toggle source
    # File lib/racc/state.rb, line 40
40:     def size
41:       @states.size
42:     end
srconflict_exist?() click to toggle source
    # File lib/racc/state.rb, line 75
75:     def srconflict_exist?
76:       n_srconflicts() != 0
77:     end
state_transition_table() click to toggle source
    # File lib/racc/state.rb, line 91
91:     def state_transition_table
92:       @state_transition_table ||= StateTransitionTable.generate(self.dfa)
93:     end
to_s() click to toggle source
Alias for: inspect

Private Instance Methods

addrel(tbl, i, item) click to toggle source
     # File lib/racc/state.rb, line 316
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
addsym(table, sym, ptr) click to toggle source
     # File lib/racc/state.rb, line 153
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
check_useless() click to toggle source
     # File lib/racc/state.rb, line 585
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
compute_dfa() click to toggle source
     # File lib/racc/state.rb, line 205
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
compute_nfa() click to toggle source
     # File lib/racc/state.rb, line 110
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
core_to_state(core) click to toggle source
     # File lib/racc/state.rb, line 160
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
create_tmap(size) click to toggle source
     # File lib/racc/state.rb, line 312
312:     def create_tmap(size)
313:       Array.new(size, 0)   # use Integer as bitmap
314:     end
digraph(map, relation) click to toggle source
     # File lib/racc/state.rb, line 347
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
do_resolve_sr(stok, rtok) click to toggle source
     # File lib/racc/state.rb, line 522
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
each_t(tbl, set) click to toggle source
     # File lib/racc/state.rb, line 421
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
fingerprint(arr) click to toggle source
     # File lib/racc/state.rb, line 185
185:     def fingerprint(arr)
186:       arr.map {|i| i.ident }.pack('L*')
187:     end
generate_states(state) click to toggle source
     # File lib/racc/state.rb, line 124
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
lookahead() click to toggle source
     # File lib/racc/state.rb, line 218
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
pack(state) click to toggle source
     # File lib/racc/state.rb, line 563
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
printb(i) click to toggle source

for debug

     # File lib/racc/state.rb, line 414
414:     def printb(i)
415:       each_t(@symboltable, i) do |t|
416:         print t, ' '
417:       end
418:       puts
419:     end
record_path(begst, rule) click to toggle source
     # File lib/racc/state.rb, line 324
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
resolve(state) click to toggle source

resolve

     # File lib/racc/state.rb, line 435
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
resolve_rr(state, r) click to toggle source
     # File lib/racc/state.rb, line 452
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
resolve_sr(state, s) click to toggle source
     # File lib/racc/state.rb, line 471
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
set_accept() click to toggle source

complete

     # File lib/racc/state.rb, line 552
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
transpose(rel) click to toggle source
     # File lib/racc/state.rb, line 335
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
traverse(i, index, vertices, map, relation) click to toggle source
     # File lib/racc/state.rb, line 360
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

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.