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:



29
30
31
# File 'lib/antelope/generation/tableizer.rb', line 29

def initialize(grammar)
  @grammar = grammar
end

Instance Attribute Details

#conflictsObject (readonly)

Returns the value of attribute conflicts.



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

def conflicts
  @conflicts
end

#grammarAce::Grammar

The grammar that the table is based off of.

Returns:



12
13
14
# File 'lib/antelope/generation/tableizer.rb', line 12

def grammar
  @grammar
end

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

All rules in the grammar.

Returns:



22
23
24
# File 'lib/antelope/generation/tableizer.rb', line 22

def rules
  @rules
end

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

The table itself.

Returns:

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


17
18
19
# File 'lib/antelope/generation/tableizer.rb', line 17

def table
  @table
end

Instance Method Details

#callvoid

This method returns an undefined value.

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



38
39
40
41
# File 'lib/antelope/generation/tableizer.rb', line 38

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:



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/antelope/generation/tableizer.rb', line 86

def conflictize
  @conflicts = Hash.new { |h, k| h[k] = {} }
  @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)

      rule_part, other_part = data.sort_by { |(t, d)| t }

      unless other_part[0] == :state
        $stderr.puts \
          "Could not determine move for #{on} in state " \
          "#{state} (reduce/reduce conflict)"
        next
      end

      result = @rules[rule_part[1]].prec <=> terminal

      case result
      when 0
        conflicts[state][on] = [
          rule_part, other_part, terminal, @rules[rule_part[1]].prec
        ]
        $stderr.puts \
          "Could not determine move for #{on} in state " \
          "#{state} (shift/reduce conflict)"
      when 1
        @table[state][on] = rule_part
      when -1
        @table[state][on] = other_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).



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

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.production.id] = rule.production
      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