Class: Ibex::Codegen::Ambiguity

Inherits:
Object
  • Object
show all
Defined in:
lib/ibex/codegen/ambiguity.rb,
sig/ibex/codegen/ambiguity.rbs

Overview

Renders a bounded ambiguity search over every parser conflict.

Constant Summary collapse

SCHEMA_VERSION =

Signature:

  • Integer

Returns:

  • (Integer)
1

Instance Method Summary collapse

Constructor Details

#initialize(automaton, max_tokens: LALR::Counterexample::DEFAULT_MAX_TOKENS, max_configurations: LALR::Counterexample::DEFAULT_MAX_CONFIGURATIONS) ⇒ Ambiguity

Returns a new instance of Ambiguity.

RBS:

  • (IR::Automaton automaton, ?max_tokens: Integer, ?max_configurations: Integer) -> void

Parameters:

  • automaton (IR::Automaton)
  • max_tokens: (Integer) (defaults to: LALR::Counterexample::DEFAULT_MAX_TOKENS)
  • max_configurations: (Integer) (defaults to: LALR::Counterexample::DEFAULT_MAX_CONFIGURATIONS)


51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/ibex/codegen/ambiguity.rb', line 51

def initialize(
  automaton,
  max_tokens: LALR::Counterexample::DEFAULT_MAX_TOKENS,
  max_configurations: LALR::Counterexample::DEFAULT_MAX_CONFIGURATIONS
)
  LALR::ConflictSearchLimits.validate!(
    max_tokens: max_tokens, max_configurations: max_configurations
  )
  @automaton = automaton
  @grammar = automaton.grammar
  @max_tokens = max_tokens
  @max_configurations = max_configurations
  @checks = check_conflicts
end

Instance Method Details

#append_check(lines, check, number) ⇒ void

This method returns an undefined value.

RBS:

  • (Array[String] lines, ambiguity_check check, Integer number) -> void

Parameters:

  • lines (Array[String])
  • check (ambiguity_check)
  • number (Integer)


160
161
162
163
164
165
166
167
168
169
170
# File 'lib/ibex/codegen/ambiguity.rb', line 160

def append_check(lines, check, number)
  lines << ""
  lines << "#{number}. State #{check.fetch(:state)}, #{check.fetch(:type)}, token #{check.fetch(:token)}"
  lines << "   Result: #{check.fetch(:result)}"
  sentence = check.fetch(:sentence)
  lines << "   Sentence: #{sentence.join(' ')}" unless sentence.empty?
  lines << "   Explored configurations: #{check.fetch(:explored_configurations)}"
  return unless check.fetch(:configuration_budget_exhausted)

  lines << "   Configuration budget exhausted before a counterexample was found."
end

#check_conflict(state, conflict) ⇒ ambiguity_check

RBS:

  • (IR::AutomatonState state, IR::conflict conflict) -> ambiguity_check

Parameters:

Returns:

  • (ambiguity_check)


132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/ibex/codegen/ambiguity.rb', line 132

def check_conflict(state, conflict)
  search = LALR::ConflictSearch.new(
    @automaton, state, conflict,
    max_tokens: @max_tokens, max_configurations: @max_configurations
  )
  result = search.call
  {
    state: state.id,
    type: conflict.fetch(:type).to_s,
    token: conflict.fetch(:symbol),
    result: result ? "ambiguous" : "not_found",
    sentence: result ? symbol_names(result.fetch(:sentence_ids)) : [],
    lookahead_index: result&.fetch(:lookahead_index),
    interpretations: result ? result.fetch(:interpretations) : [],
    explored_configurations: search.explored,
    configuration_budget_exhausted: search.exhausted?
  }
end

#check_conflictsArray[ambiguity_check]

RBS:

  • () -> Array[ambiguity_check]

Returns:

  • (Array[ambiguity_check])


125
126
127
128
129
# File 'lib/ibex/codegen/ambiguity.rb', line 125

def check_conflicts
  @automaton.states.flat_map do |state|
    state.conflicts.map { |conflict| check_conflict(state, conflict) }
  end
end

#exit_statusInteger

RBS:

  • () -> Integer

Returns:

  • (Integer)


67
68
69
70
71
72
# File 'lib/ibex/codegen/ambiguity.rb', line 67

def exit_status
  return 1 if status == "ambiguous"
  return 2 if status == "inconclusive"

  0
end

#render_textString

RBS:

  • () -> String

Returns:

  • (String)


88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/ibex/codegen/ambiguity.rb', line 88

def render_text
  counts = summary
  lines = [
    "Ibex ambiguity check v#{SCHEMA_VERSION}",
    "Algorithm: #{@automaton.algorithm}",
    "Search budget: #{@max_tokens} tokens, #{@max_configurations} configurations per conflict",
    "Result: #{status}",
    "Conflicts: #{counts.fetch(:conflicts)}, ambiguous: #{counts.fetch(:ambiguous)}, " \
    "exhausted: #{counts.fetch(:configuration_budget_exhausted)}"
  ]
  @checks.each_with_index { |check, index| append_check(lines, check, index + 1) }
  "#{lines.join("\n")}\n"
end

#statusString

RBS:

  • () -> String

Returns:

  • (String)


105
106
107
108
109
110
# File 'lib/ibex/codegen/ambiguity.rb', line 105

def status
  return "ambiguous" if @checks.any? { |check| check.fetch(:result) == "ambiguous" }
  return "inconclusive" if @checks.any? { |check| check.fetch(:configuration_budget_exhausted) }

  "no_ambiguity_found_within_bounds"
end

#summaryambiguity_summary

RBS:

  • () -> ambiguity_summary

Returns:

  • (ambiguity_summary)


113
114
115
116
117
118
119
120
121
122
# File 'lib/ibex/codegen/ambiguity.rb', line 113

def summary
  {
    conflicts: @checks.length,
    ambiguous: @checks.count { |check| check.fetch(:result) == "ambiguous" },
    not_found: @checks.count { |check| check.fetch(:result) == "not_found" },
    configuration_budget_exhausted: @checks.count do |check|
      check.fetch(:configuration_budget_exhausted)
    end
  }
end

#symbol_names(ids) ⇒ Array[String]

RBS:

  • (Array[Integer] ids) -> Array[String]

Parameters:

  • ids (Array[Integer])

Returns:

  • (Array[String])


152
153
154
155
156
157
# File 'lib/ibex/codegen/ambiguity.rb', line 152

def symbol_names(ids)
  ids.map do |id|
    symbol = @grammar.symbol_by_id(id) || raise(Ibex::Error, "missing grammar symbol id #{id}")
    symbol.display_name || symbol.name
  end
end

#to_hambiguity_document

RBS:

  • () -> ambiguity_document

Returns:

  • (ambiguity_document)


75
76
77
78
79
80
81
82
83
84
85
# File 'lib/ibex/codegen/ambiguity.rb', line 75

def to_h
  {
    ibex_check: "ambiguity",
    schema_version: SCHEMA_VERSION,
    algorithm: @automaton.algorithm,
    search: { max_tokens: @max_tokens, max_configurations: @max_configurations },
    status: status,
    summary: summary,
    conflicts: @checks
  }
end