Class: Racc::Grammar

Inherits:
Object show all
Extended by:
Forwardable
Defined in:
lib/racc/grammar.rb

Defined Under Namespace

Classes: DefinitionEnv, PrecedenceDefinitionEnv

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(debug_flags = DebugFlags.new) ⇒ Grammar

Returns a new instance of Grammar.



24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/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
  @error_on_expect_mismatch = nil
  @prec_table = []
  @prec_table_closed = false
  @closed = false
  @states = nil
end

Instance Attribute Details

#error_on_expect_mismatchObject

Returns the value of attribute error_on_expect_mismatch.



40
41
42
# File 'lib/racc/grammar.rb', line 40

def error_on_expect_mismatch
  @error_on_expect_mismatch
end

#n_expected_srconflictsObject

Returns the value of attribute n_expected_srconflicts.



39
40
41
# File 'lib/racc/grammar.rb', line 39

def n_expected_srconflicts
  @n_expected_srconflicts
end

#startObject (readonly)

Returns the value of attribute start.



37
38
39
# File 'lib/racc/grammar.rb', line 37

def start
  @start
end

#symboltableObject (readonly)

Returns the value of attribute symboltable.



38
39
40
# File 'lib/racc/grammar.rb', line 38

def symboltable
  @symboltable
end

Class Method Details

.define(&block) ⇒ Object

Dynamic Generation Interface



203
204
205
206
207
# File 'lib/racc/grammar.rb', line 203

def Grammar.define(&block)
  env = DefinitionEnv.new
  env.instance_eval(&block)
  env.grammar
end

Instance Method Details

#[](x) ⇒ Object



42
43
44
# File 'lib/racc/grammar.rb', line 42

def [](x)
  @rules[x]
end

#add(rule) ⇒ Object

Grammar Definition Interface

Raises:

  • (ArgumentError)


168
169
170
171
# File 'lib/racc/grammar.rb', line 168

def add(rule)
  raise ArgumentError, "rule added after the Grammar closed" if @closed
  @rules.push rule
end

#added?(sym) ⇒ Boolean

Returns:

  • (Boolean)


173
174
175
# File 'lib/racc/grammar.rb', line 173

def added?(sym)
  @rules.detect {|r| r.target == sym }
end

#declare_precedence(assoc, syms) ⇒ Object

Raises:



182
183
184
185
# File 'lib/racc/grammar.rb', line 182

def declare_precedence(assoc, syms)
  raise CompileError, "precedence table defined twice" if @prec_table_closed
  @prec_table.push [assoc, syms]
end

#dfaObject Also known as: states



122
123
124
# File 'lib/racc/grammar.rb', line 122

def dfa
  (@states ||= States.new(self)).dfa
end

#each_index(&block) ⇒ Object



52
53
54
# File 'lib/racc/grammar.rb', line 52

def each_index(&block)
  @rules.each_index(&block)
end

#each_rule(&block) ⇒ Object Also known as: each



46
47
48
# File 'lib/racc/grammar.rb', line 46

def each_rule(&block)
  @rules.each(&block)
end

#each_useless_nonterminalObject



94
95
96
97
98
99
100
# File 'lib/racc/grammar.rb', line 94

def each_useless_nonterminal
  return to_enum __method__ unless block_given?

  @symboltable.each_nonterminal do |sym|
    yield sym if sym.useless?
  end
end

#each_useless_ruleObject



110
111
112
113
114
115
116
# File 'lib/racc/grammar.rb', line 110

def each_useless_rule
  return to_enum __method__ unless block_given?

  each do |r|
    yield r if r.useless?
  end
end

#each_with_index(&block) ⇒ Object



56
57
58
# File 'lib/racc/grammar.rb', line 56

def each_with_index(&block)
  @rules.each_with_index(&block)
end

#end_precedence_declaration(reverse) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
# File 'lib/racc/grammar.rb', line 187

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

#initObject

Computation

Raises:



411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
# File 'lib/racc/grammar.rb', line 411

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

#intern(value, dummy = false) ⇒ Object



74
75
76
# File 'lib/racc/grammar.rb', line 74

def intern(value, dummy = false)
  @symboltable.intern(value, dummy)
end

#n_useless_nonterminalsObject



90
91
92
# File 'lib/racc/grammar.rb', line 90

def n_useless_nonterminals
  @n_useless_nonterminals ||= each_useless_nonterminal.count
end

#n_useless_rulesObject



106
107
108
# File 'lib/racc/grammar.rb', line 106

def n_useless_rules
  @n_useless_rules ||= each_useless_rule.count
end

#nfaObject



118
119
120
# File 'lib/racc/grammar.rb', line 118

def nfa
  (@states ||= States.new(self)).nfa
end

#nonterminal_baseObject



82
83
84
# File 'lib/racc/grammar.rb', line 82

def nonterminal_base
  @symboltable.nt_base
end

#parser_classObject



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/racc/grammar.rb', line 132

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

#sizeObject



60
61
62
# File 'lib/racc/grammar.rb', line 60

def size
  @rules.size
end

#start_symbol=(s) ⇒ Object

Raises:



177
178
179
180
# File 'lib/racc/grammar.rb', line 177

def start_symbol=(s)
  raise CompileError, "start symbol set twice'" if @start
  @start = s
end

#state_transition_tableObject



128
129
130
# File 'lib/racc/grammar.rb', line 128

def state_transition_table
  states().state_transition_table
end

#symbolsObject



78
79
80
# File 'lib/racc/grammar.rb', line 78

def symbols
  @symboltable.symbols
end

#to_sObject



64
65
66
# File 'lib/racc/grammar.rb', line 64

def to_s
  "<Racc::Grammar>"
end

#useless_nonterminal_exist?Boolean

Returns:

  • (Boolean)


86
87
88
# File 'lib/racc/grammar.rb', line 86

def useless_nonterminal_exist?
  n_useless_nonterminals() != 0
end

#useless_rule_exist?Boolean

Returns:

  • (Boolean)


102
103
104
# File 'lib/racc/grammar.rb', line 102

def useless_rule_exist?
  n_useless_rules() != 0
end

#write_log(path) ⇒ Object



158
159
160
161
162
# File 'lib/racc/grammar.rb', line 158

def write_log(path)
  File.open(path, 'w') {|f|
    LogFileGenerator.new(states()).output f
  }
end