lib/antelope/generation/tableizer.rb in antelope-0.0.1 vs lib/antelope/generation/tableizer.rb in antelope-0.1.0

- old
+ new

@@ -1,32 +1,57 @@ module Antelope module Generation - class UnresolvableConflictError < StandardError; end - + # Constructs the table required for the parser. class Tableizer - attr_accessor :parser + # The grammar that the table is based off of. + # + # @return [Ace::Grammar] + attr_accessor :grammar + + # The table itself. + # + # @return [Array<Hash<(Symbol, Array<(Symbol, Numeric)>)>>] attr_accessor :table + + # All rules in the grammar. + # + # @return [Hash<(Numeric, Recognizer::Rule)>] attr_accessor :rules - def initialize(parser) - @parser = parser + # Initialize. + # + # @param grammar [Ace::Grammar] + def initialize(grammar) + @grammar = grammar end + # Construct the table, and then check the table for conflicts. + # + # @return [void] + # @see #tablize + # @see #conflictize def call tablize conflictize 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 + # correspond to acceptable tokens. The values of the hashes + # should be an array of arrays (at this point). + # + # @return [void] def tablize - @table = Array.new(parser.states.size) do + @table = Array.new(grammar.states.size) do Hash.new { |h, k| h[k] = [] } end @rules = [] - parser.states.each do |state| + grammar.states.each do |state| state.transitions.each do |on, to| table[state.id][on] << [:state, to.id] end state.rules.each do |rule| @@ -45,27 +70,34 @@ end table end + # Resolve any conflicts through precedence, if we can. If we + # can't, let the user know. This makes sure that every value + # of the hashes is a single array. + # + # @raise [UnresolvableConflictError] if a conflict could not be + # resolved using precedence rules. + # @return [void] def conflictize @table.each_with_index do |v, state| v.each do |on, data| if data.size == 1 @table[state][on] = data[0] next end - terminal = parser.presidence_for(on) + terminal = grammar.precedence_for(on) state_part = data.select { |(t, d)| t == :state }.first rule_part = data.select { |(t, d)| t == :reduce}.first - result = @rules[rule_part[1]].presidence <=> terminal + result = @rules[rule_part[1]].precedence <=> terminal case result when 0 - p v, terminal, @rules[rule_part[1]].presidence + p v, terminal, @rules[rule_part[1]].precedence raise UnresolvableConflictError, "Could not determine move for #{on} in state #{state}" when 1 @table[state][on] = rule_part when -1