Class: Antelope::Generation::Tableizer

Inherits:
Object
  • Object
show all
Defined in:
lib/antelope/generation/tableizer.rb

Overview

Constructs the table required for the parser.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(grammar) ⇒ Tableizer

Initialize.

Parameters:



25
26
27
# File 'lib/antelope/generation/tableizer.rb', line 25

def initialize(grammar)
  @grammar = grammar
end

Instance Attribute Details

#grammarAce::Grammar

The grammar that the table is based off of.

Returns:



10
11
12
# File 'lib/antelope/generation/tableizer.rb', line 10

def grammar
  @grammar
end

#rulesHash<(Numeric, Recognizer::Rule)>

All rules in the grammar.

Returns:



20
21
22
# File 'lib/antelope/generation/tableizer.rb', line 20

def rules
  @rules
end

#tableArray<Hash<(Symbol, Array<(Symbol, Numeric)>)>>

The table itself.

Returns:

  • (Array<Hash<(Symbol, Array<(Symbol, Numeric)>)>>)


15
16
17
# File 'lib/antelope/generation/tableizer.rb', line 15

def table
  @table
end

Instance Method Details

#callvoid

This method returns an undefined value.

Construct the table, and then check the table for conflicts.



34
35
36
37
# File 'lib/antelope/generation/tableizer.rb', line 34

def call
  tablize
  conflictize
end

#conflictizevoid

This method returns an undefined value.

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.

Raises:



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/antelope/generation/tableizer.rb', line 82

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 = 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]].precedence <=> terminal

      case result
      when 0
        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
        @table[state][on] = state_part
      end
    end
  end
end

#tablizevoid

This method returns an undefined value.

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).



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/antelope/generation/tableizer.rb', line 46

def tablize
  @table = Array.new(grammar.states.size) do
    Hash.new { |h, k| h[k] = [] }
  end
  @rules = []

  grammar.states.each do |state|
    state.transitions.each do |on, to|
      table[state.id][on] << [:state, to.id]
    end

    state.rules.each do |rule|
      @rules[rule.id] = rule
      if rule.final?
        rule.lookahead.each do |look|
          table[state.id][look.name] <<
            [:reduce, rule.production.id]
        end

        if rule.production.id.zero?
          table[state.id][:"$"] = [[:accept, rule.production.id]]
        end
      end
    end
  end

  table
end