Class: Ibex::Codegen::Ambiguity
- Inherits:
-
Object
- Object
- Ibex::Codegen::Ambiguity
- 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 =
1
Instance Method Summary collapse
- #append_check(lines, check, number) ⇒ void
- #check_conflict(state, conflict) ⇒ ambiguity_check
- #check_conflicts ⇒ Array[ambiguity_check]
- #exit_status ⇒ Integer
-
#initialize(automaton, max_tokens: LALR::Counterexample::DEFAULT_MAX_TOKENS, max_configurations: LALR::Counterexample::DEFAULT_MAX_CONFIGURATIONS) ⇒ Ambiguity
constructor
A new instance of Ambiguity.
- #render_text ⇒ String
- #status ⇒ String
- #summary ⇒ ambiguity_summary
- #symbol_names(ids) ⇒ Array[String]
- #to_h ⇒ ambiguity_document
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.
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.
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
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_conflicts ⇒ 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_status ⇒ 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_text ⇒ 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 |
#status ⇒ 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 |
#summary ⇒ 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]
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_h ⇒ 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 |