Dynamic Generation Interface
# File lib/racc/grammar.rb, line 198
198: def Grammar.define(&block)
199: env = DefinitionEnv.new
200: env.instance_eval(&block)
201: env.grammar
202: end
# File lib/racc/grammar.rb, line 23
23: def initialize(debug_flags = DebugFlags.new)
24: @symboltable = SymbolTable.new
25: @debug_symbol = debug_flags.token
26: @rules = [] # :: [Rule]
27: @start = nil
28: @n_expected_srconflicts = nil
29: @prec_table = []
30: @prec_table_closed = false
31: @closed = false
32: @states = nil
33: end
# File lib/racc/grammar.rb, line 39
39: def [](x)
40: @rules[x]
41: end
Grammar Definition Interface
# File lib/racc/grammar.rb, line 163
163: def add(rule)
164: raise ArgumentError, "rule added after the Grammar closed" if @closed
165: @rules.push rule
166: end
# File lib/racc/grammar.rb, line 168
168: def added?(sym)
169: @rules.detect {|r| r.target == sym }
170: end
# File lib/racc/grammar.rb, line 177
177: def declare_precedence(assoc, syms)
178: raise CompileError, "precedence table defined twice" if @prec_table_closed
179: @prec_table.push [assoc, syms]
180: end
# File lib/racc/grammar.rb, line 117
117: def dfa
118: (@states ||= States.new(self)).dfa
119: end
# File lib/racc/grammar.rb, line 49
49: def each_index(&block)
50: @rules.each_index(&block)
51: end
# File lib/racc/grammar.rb, line 43
43: def each_rule(&block)
44: @rules.each(&block)
45: end
# File lib/racc/grammar.rb, line 53
53: def each_with_index(&block)
54: @rules.each_with_index(&block)
55: end
# File lib/racc/grammar.rb, line 182
182: def end_precedence_declaration(reverse)
183: @prec_table_closed = true
184: return if @prec_table.empty?
185: table = reverse ? @prec_table.reverse : @prec_table
186: table.each_with_index do |(assoc, syms), idx|
187: syms.each do |sym|
188: sym.assoc = assoc
189: sym.precedence = idx
190: end
191: end
192: end
Computation
# File lib/racc/grammar.rb, line 406
406: def init
407: return if @closed
408: @closed = true
409: @start ||= @rules.map {|r| r.target }.detect {|sym| not sym.dummy? }
410: raise CompileError, 'no rule in input' if @rules.empty?
411: add_start_rule
412: @rules.freeze
413: fix_ident
414: compute_hash
415: compute_heads
416: determine_terminals
417: compute_nullable_0
418: @symboltable.fix
419: compute_locate
420: @symboltable.each_nonterminal {|t| compute_expand t }
421: compute_nullable
422: compute_useless
423: end
# File lib/racc/grammar.rb, line 71
71: def intern(value, dummy = false)
72: @symboltable.intern(value, dummy)
73: end
# File lib/racc/grammar.rb, line 87
87: def n_useless_nonterminals
88: @n_useless_nonterminals ||=
89: begin
90: n = 0
91: @symboltable.each_nonterminal do |sym|
92: n += 1 if sym.useless?
93: end
94: n
95: end
96: end
# File lib/racc/grammar.rb, line 102
102: def n_useless_rules
103: @n_useless_rules ||=
104: begin
105: n = 0
106: each do |r|
107: n += 1 if r.useless?
108: end
109: n
110: end
111: end
# File lib/racc/grammar.rb, line 113
113: def nfa
114: (@states ||= States.new(self)).nfa
115: end
# File lib/racc/grammar.rb, line 79
79: def nonterminal_base
80: @symboltable.nt_base
81: end
# File lib/racc/grammar.rb, line 127
127: def parser_class
128: states = states() # cache
129: if $DEBUG
130: srcfilename = caller(1).first.slice(/\A(.*?):/, 1)
131: begin
132: write_log srcfilename + ".output"
133: rescue SystemCallError
134: end
135: report = lambda {|s| $stderr.puts "racc: #{srcfilename}: #{s}" }
136: if states.should_report_srconflict?
137: report["#{states.n_srconflicts} shift/reduce conflicts"]
138: end
139: if states.rrconflict_exist?
140: report["#{states.n_rrconflicts} reduce/reduce conflicts"]
141: end
142: g = states.grammar
143: if g.useless_nonterminal_exist?
144: report["#{g.n_useless_nonterminals} useless nonterminals"]
145: end
146: if g.useless_rule_exist?
147: report["#{g.n_useless_rules} useless rules"]
148: end
149: end
150: states.state_transition_table.parser_class
151: end
# File lib/racc/grammar.rb, line 57
57: def size
58: @rules.size
59: end
# File lib/racc/grammar.rb, line 172
172: def start_symbol=(s)
173: raise CompileError, "start symbol set twice'" if @start
174: @start = s
175: end
# File lib/racc/grammar.rb, line 123
123: def state_transition_table
124: states().state_transition_table
125: end
# File lib/racc/grammar.rb, line 75
75: def symbols
76: @symboltable.symbols
77: end
# File lib/racc/grammar.rb, line 61
61: def to_s
62: "<Racc::Grammar>"
63: end
# File lib/racc/grammar.rb, line 83
83: def useless_nonterminal_exist?
84: n_useless_nonterminals() != 0
85: end
# File lib/racc/grammar.rb, line 501
501: def _compute_expand(t, set, lock)
502: if tmp = t.expand
503: set.update tmp
504: return set
505: end
506: tok = h = nil
507: set.update_a t.heads
508: t.heads.each do |ptr|
509: tok = ptr.dereference
510: if tok and tok.nonterminal?
511: unless lock[tok.ident]
512: lock[tok.ident] = true
513: _compute_expand tok, set, lock
514: end
515: end
516: end
517: set
518: end
# File lib/racc/grammar.rb, line 427
427: def add_start_rule
428: r = Rule.new(@symboltable.dummy,
429: [@start, @symboltable.anchor, @symboltable.anchor],
430: UserAction.empty)
431: r.ident = 0
432: r.hash = 0
433: r.precedence = nil
434: @rules.unshift r
435: end
# File lib/racc/grammar.rb, line 534
534: def check_rules_nullable(rules)
535: rules.delete_if do |rule|
536: rule.null = true
537: rule.symbols.each do |t|
538: unless t.nullable?
539: rule.null = false
540: break
541: end
542: end
543: rule.nullable?
544: end
545: end
# File lib/racc/grammar.rb, line 575
575: def check_rules_useless(rules)
576: rules.delete_if do |rule|
577: rule.useless = false
578: rule.symbols.each do |sym|
579: if sym.useless?
580: rule.useless = true
581: break
582: end
583: end
584: not rule.useless?
585: end
586: end
# File lib/racc/grammar.rb, line 547
547: def check_symbols_nullable(symbols)
548: symbols.delete_if do |sym|
549: sym.heads.each do |ptr|
550: if ptr.rule.nullable?
551: sym.null = true
552: break
553: end
554: end
555: sym.nullable?
556: end
557: end
# File lib/racc/grammar.rb, line 588
588: def check_symbols_useless(s)
589: s.delete_if do |t|
590: t.heads.each do |ptr|
591: unless ptr.rule.useless?
592: t.useless = false
593: break
594: end
595: end
596: not t.useless?
597: end
598: end
Sym#expand
# File lib/racc/grammar.rb, line 495
495: def compute_expand(t)
496: puts "expand> #{t.to_s}" if @debug_symbol
497: t.expand = _compute_expand(t, ISet.new, [])
498: puts "expand< #{t.to_s}: #{t.expand.to_s}" if @debug_symbol
499: end
Rule#hash
# File lib/racc/grammar.rb, line 446
446: def compute_hash
447: hash = 4 # size of dummy rule
448: @rules.each do |rule|
449: rule.hash = hash
450: hash += (rule.size + 1)
451: end
452: end
Sym#heads
# File lib/racc/grammar.rb, line 455
455: def compute_heads
456: @rules.each do |rule|
457: rule.target.heads.push rule.ptrs[0]
458: end
459: end
Sym#locate
# File lib/racc/grammar.rb, line 480
480: def compute_locate
481: @rules.each do |rule|
482: t = nil
483: rule.ptrs.each do |ptr|
484: unless ptr.reduce?
485: tok = ptr.dereference
486: tok.locate.push ptr
487: t = tok if tok.terminal?
488: end
489: end
490: rule.precedence = t
491: end
492: end
# File lib/racc/grammar.rb, line 521
521: def compute_nullable
522: @rules.each {|r| r.null = false }
523: @symboltable.each {|t| t.null = false }
524: r = @rules.dup
525: s = @symboltable.nonterminals
526: begin
527: rs = r.size
528: ss = s.size
529: check_rules_nullable r
530: check_symbols_nullable s
531: end until rs == r.size and ss == s.size
532: end
# File lib/racc/grammar.rb, line 469
469: def compute_nullable_0
470: @symboltable.each do |s|
471: if s.terminal?
472: s.snull = false
473: else
474: s.snull = s.heads.any? {|loc| loc.reduce? }
475: end
476: end
477: end
Sym#useless?, Rule#useless? FIXME: what means “useless”?
# File lib/racc/grammar.rb, line 561
561: def compute_useless
562: @symboltable.each_terminal {|sym| sym.useless = false }
563: @symboltable.each_nonterminal {|sym| sym.useless = true }
564: @rules.each {|rule| rule.useless = true }
565: r = @rules.dup
566: s = @symboltable.nonterminals
567: begin
568: rs = r.size
569: ss = s.size
570: check_rules_useless r
571: check_symbols_useless s
572: end until r.size == rs and s.size == ss
573: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.