Object
Dynamic Generation Interface
# File racc/grammar.rb, line 201
def Grammar.define(&block)
env = DefinitionEnv.new
env.instance_eval(&block)
env.grammar
end
# File racc/grammar.rb, line 24
def initialize(debug_flags = DebugFlags.new)
@symboltable = SymbolTable.new
@debug_symbol = debug_flags.token
@rules = [] # :: [Rule]
@start = nil
@n_expected_srconflicts = nil
@prec_table = []
@prec_table_closed = false
@closed = false
@states = nil
end
Grammar Definition Interface
# File racc/grammar.rb, line 166
def add(rule)
raise ArgumentError, "rule added after the Grammar closed" if @closed
@rules.push rule
end
# File racc/grammar.rb, line 171
def added?(sym)
@rules.detect {|r| r.target == sym }
end
# File racc/grammar.rb, line 180
def declare_precedence(assoc, syms)
raise CompileError, "precedence table defined twice" if @prec_table_closed
@prec_table.push [assoc, syms]
end
# File racc/grammar.rb, line 120
def dfa
(@states ||= States.new(self)).dfa
end
# File racc/grammar.rb, line 50
def each_index(&block)
@rules.each_index(&block)
end
# File racc/grammar.rb, line 44
def each_rule(&block)
@rules.each(&block)
end
# File racc/grammar.rb, line 92
def each_useless_nonterminal
return to_enum __method__ unless block_given?
@symboltable.each_nonterminal do |sym|
yield sym if sym.useless?
end
end
# File racc/grammar.rb, line 108
def each_useless_rule
return to_enum __method__ unless block_given?
each do |r|
yield r if r.useless?
end
end
# File racc/grammar.rb, line 54
def each_with_index(&block)
@rules.each_with_index(&block)
end
# File racc/grammar.rb, line 185
def end_precedence_declaration(reverse)
@prec_table_closed = true
return if @prec_table.empty?
table = reverse ? @prec_table.reverse : @prec_table
table.each_with_index do |(assoc, syms), idx|
syms.each do |sym|
sym.assoc = assoc
sym.precedence = idx
end
end
end
Computation
# File racc/grammar.rb, line 409
def init
return if @closed
@closed = true
@start ||= @rules.map {|r| r.target }.detect {|sym| not sym.dummy? }
raise CompileError, 'no rule in input' if @rules.empty?
add_start_rule
@rules.freeze
fix_ident
compute_hash
compute_heads
determine_terminals
compute_nullable_0
@symboltable.fix
compute_locate
@symboltable.each_nonterminal {|t| compute_expand t }
compute_nullable
compute_useless
end
# File racc/grammar.rb, line 72
def intern(value, dummy = false)
@symboltable.intern(value, dummy)
end
# File racc/grammar.rb, line 88
def n_useless_nonterminals
@n_useless_nonterminals ||= each_useless_nonterminal.count
end
# File racc/grammar.rb, line 104
def n_useless_rules
@n_useless_rules ||= each_useless_rule.count
end
# File racc/grammar.rb, line 116
def nfa
(@states ||= States.new(self)).nfa
end
# File racc/grammar.rb, line 80
def nonterminal_base
@symboltable.nt_base
end
# File racc/grammar.rb, line 130
def parser_class
states = states() # cache
if $DEBUG
srcfilename = caller(1).first.slice(/\A(.*?):/, 1)
begin
write_log srcfilename + ".output"
rescue SystemCallError
end
report = lambda {|s| $stderr.puts "racc: #{srcfilename}: #{s}" }
if states.should_report_srconflict?
report["#{states.n_srconflicts} shift/reduce conflicts"]
end
if states.rrconflict_exist?
report["#{states.n_rrconflicts} reduce/reduce conflicts"]
end
g = states.grammar
if g.useless_nonterminal_exist?
report["#{g.n_useless_nonterminals} useless nonterminals"]
end
if g.useless_rule_exist?
report["#{g.n_useless_rules} useless rules"]
end
end
states.state_transition_table.parser_class
end
# File racc/grammar.rb, line 175
def start_symbol=(s)
raise CompileError, "start symbol set twice'" if @start
@start = s
end
# File racc/grammar.rb, line 126
def state_transition_table
states().state_transition_table
end
# File racc/grammar.rb, line 76
def symbols
@symboltable.symbols
end
# File racc/grammar.rb, line 84
def useless_nonterminal_exist?
n_useless_nonterminals() != 0
end