lib/antelope/generation/tableizer.rb in antelope-0.1.8 vs lib/antelope/generation/tableizer.rb in antelope-0.1.9

- old
+ new

@@ -36,10 +36,11 @@ # @see #tablize # @see #conflictize def call tablize conflictize + defaultize end # Construct a table based on the grammar. The table itself is # an array whose elements are hashes; the index of the array # corresponds to the state ID, and the keys of the hashes @@ -65,11 +66,12 @@ table[state.id][look.name] << [:reduce, rule.production.id] end if rule.production.id.zero? - table[state.id][:"$"] = [[:accept, rule.production.id]] + table[state.id][:$end] = + [[:accept, rule.production.id]] end end end end @@ -92,11 +94,11 @@ next end terminal = grammar.precedence_for(on) - rule_part, other_part = data.sort_by { |(t, d)| t } + rule_part, other_part = data.sort_by { |(t, _)| t } unless other_part[0] == :state $stderr.puts \ "Could not determine move for #{on} in state " \ "#{state} (reduce/reduce conflict)" @@ -115,9 +117,35 @@ "#{state} (shift/reduce conflict)" when 1 @table[state][on] = rule_part when -1 @table[state][on] = other_part + end + end + end + end + + # Reduce many transitions into a single `$default` transition. + # This only works if there is no `$empty` transition; if there + # is an `$empty` transition, then the `$default` transition is + # set to be the `$empty` transition. + # + # @return [void] + def defaultize + max = @table.map { |s| s.keys.size }.max + @table.each_with_index do |state| + if state.key?(:$empty) + state[:$default] = state[:$empty] + else + common = state.group_by { |k, v| v }.values. + sort_by(&:size).first + + if common.size > (max / 2) + action = common[0][1] + + keys = common.map(&:first) + state.delete_if { |k, _| keys.include?(k) } + state[:$default] = action end end end end end