Module: Ibex::LALR::OnErrorReductions
- Defined in:
- lib/ibex/lalr/on_error_reductions.rb,
sig/ibex/lalr/on_error_reductions.rbs
Overview
Delays syntax-error detection by filling only otherwise erroneous table cells with one uniquely highest-priority declared reduction.
Class Method Summary collapse
- .apply(grammar, states) ⇒ Object
- .apply_state(grammar, state, priorities, terminal_ids) ⇒ Object
- .reduction_priorities(grammar) ⇒ Object
- .selected_production(grammar, state, priorities) ⇒ Object
Instance Method Summary collapse
- #apply_state(grammar, state, priorities, terminal_ids) ⇒ IR::AutomatonState
- #selected_production(grammar, state, priorities) ⇒ Integer?
- #self?.apply ⇒ Array[IR::AutomatonState]
- #self?.reduction_priorities ⇒ Hash[Integer, Integer]
Class Method Details
.apply(grammar, states) ⇒ Object
9 10 11 12 13 14 15 |
# File 'lib/ibex/lalr/on_error_reductions.rb', line 9 def apply(grammar, states) priorities = reduction_priorities(grammar) return states if priorities.empty? terminal_ids = grammar.terminals.reject { |terminal| terminal.name == "error" }.map(&:id) states.map { |state| apply_state(grammar, state, priorities, terminal_ids) } end |
.apply_state(grammar, state, priorities, terminal_ids) ⇒ Object
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/ibex/lalr/on_error_reductions.rb', line 32 def apply_state(grammar, state, priorities, terminal_ids) production_id = selected_production(grammar, state, priorities) return state unless production_id reduction = { type: :reduce, production: production_id } #: IR::reduce_action actions = state.actions.dup terminal_ids.each do |token_id| action = actions[token_id] actions[token_id] = reduction if action.nil? || action[:type] == :error end IR::AutomatonState.new( id: state.id, items: state.items, transitions: state.transitions, actions: actions, gotos: state.gotos, default_action: state.default_action, conflicts: state.conflicts ) end |
.reduction_priorities(grammar) ⇒ Object
19 20 21 22 23 24 25 26 27 28 |
# File 'lib/ibex/lalr/on_error_reductions.rb', line 19 def reduction_priorities(grammar) priorities = {} #: Hash[Integer, Integer] grammar.recovery[:on_error_reduce].each_with_index do |names, priority| names.each do |name| symbol = grammar.symbol(name) || raise(Ibex::Error, "missing on-error reduction symbol #{name}") priorities[symbol.id] = priority end end priorities end |
.selected_production(grammar, state, priorities) ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/ibex/lalr/on_error_reductions.rb', line 50 def selected_production(grammar, state, priorities) candidates = state.items.filter_map do |item| next if item.production.negative? production = grammar.productions.fetch(item.production) next unless item.dot == production.rhs.length priority = priorities[production.lhs] [priority, production.id] if priority end.uniq highest = candidates.filter_map(&:first).max return unless highest productions = candidates.filter_map { |priority, production| production if priority == highest }.uniq productions.one? ? productions.fetch(0) : nil end |
Instance Method Details
#apply_state(grammar, state, priorities, terminal_ids) ⇒ IR::AutomatonState
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/ibex/lalr/on_error_reductions.rb', line 32 def apply_state(grammar, state, priorities, terminal_ids) production_id = selected_production(grammar, state, priorities) return state unless production_id reduction = { type: :reduce, production: production_id } #: IR::reduce_action actions = state.actions.dup terminal_ids.each do |token_id| action = actions[token_id] actions[token_id] = reduction if action.nil? || action[:type] == :error end IR::AutomatonState.new( id: state.id, items: state.items, transitions: state.transitions, actions: actions, gotos: state.gotos, default_action: state.default_action, conflicts: state.conflicts ) end |
#selected_production(grammar, state, priorities) ⇒ Integer?
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/ibex/lalr/on_error_reductions.rb', line 50 def selected_production(grammar, state, priorities) candidates = state.items.filter_map do |item| next if item.production.negative? production = grammar.productions.fetch(item.production) next unless item.dot == production.rhs.length priority = priorities[production.lhs] [priority, production.id] if priority end.uniq highest = candidates.filter_map(&:first).max return unless highest productions = candidates.filter_map { |priority, production| production if priority == highest }.uniq productions.one? ? productions.fetch(0) : nil end |
#self?.apply ⇒ Array[IR::AutomatonState]
9 |
# File 'sig/ibex/lalr/on_error_reductions.rbs', line 9
def self?.apply: (IR::Grammar grammar, Array[IR::AutomatonState] states) -> Array[IR::AutomatonState]
|
#self?.reduction_priorities ⇒ Hash[Integer, Integer]
12 |
# File 'sig/ibex/lalr/on_error_reductions.rbs', line 12
def self?.reduction_priorities: (IR::Grammar grammar) -> Hash[Integer, Integer]
|