Module: Ibex::NormalizeDiagnostics
- Included in:
- Normalizer
- Defined in:
- lib/ibex/normalize/diagnostics.rb,
sig/ibex/normalize/diagnostics.rbs
Overview
Static grammar diagnostics used by Normalizer.
Instance Method Summary collapse
- #productive_terminal?(grammar_symbol) ⇒ Boolean
- #productive_terminal_ids ⇒ Set[Integer]
- #reachable_symbol_ids ⇒ Set[Integer]
- #validate_grammar ⇒ void
- #validate_symbol_metadata ⇒ void
- #warn_duplicate_productions ⇒ void
- #warn_empty_language ⇒ void
- #warn_unreachable_nonterminals ⇒ void
- #warn_unreachable_terminals ⇒ void
- #warn_unused_precedence ⇒ void
- #warn_unused_terminals ⇒ void
Instance Method Details
#productive_terminal?(grammar_symbol) ⇒ Boolean
139 140 141 142 |
# File 'lib/ibex/normalize/diagnostics.rb', line 139 def productive_terminal?(grammar_symbol) # @type self: Normalizer grammar_symbol.terminal? && !grammar_symbol.reserved end |
#productive_terminal_ids ⇒ Set[Integer]
133 134 135 136 |
# File 'lib/ibex/normalize/diagnostics.rb', line 133 def productive_terminal_ids # @type self: Normalizer @symbols.select { |grammar_symbol| productive_terminal?(grammar_symbol) }.to_set(&:id) end |
#reachable_symbol_ids ⇒ Set[Integer]
60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/ibex/normalize/diagnostics.rb', line 60 def reachable_symbol_ids # @type self: Normalizer starts = @start_names.map { |name| required_symbol(name).id } reachable = Set.new(starts) loop do before = reachable.length @productions.select { |production| reachable.include?(production.lhs) }.each do |production| production.rhs.each { |id| reachable << id } end return reachable if reachable.length == before end end |
#validate_grammar ⇒ void
This method returns an undefined value.
11 12 13 14 15 16 17 18 19 20 |
# File 'lib/ibex/normalize/diagnostics.rb', line 11 def validate_grammar # @type self: Normalizer warn_duplicate_productions warn_unreachable_nonterminals warn_unreachable_terminals warn_unused_terminals warn_unused_precedence warn_empty_language end |
#validate_symbol_metadata ⇒ void
This method returns an undefined value.
23 24 25 26 27 28 29 30 31 |
# File 'lib/ibex/normalize/diagnostics.rb', line 23 def # @type self: Normalizer { display: @display_name_locations, type: @semantic_type_locations }.each do |label, locations| locations.each do |name, location| fail_hash(location, "#{label} declaration references undefined symbol #{name}") unless symbol(name) || parameter_template?(name) || (label == :type && @inline_rule_names.include?(name)) end end end |
#warn_duplicate_productions ⇒ void
This method returns an undefined value.
34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/ibex/normalize/diagnostics.rb', line 34 def warn_duplicate_productions # @type self: Normalizer seen = {} #: Hash[[Integer, Array[Integer]], Integer] @productions.each do |production| signature = [production.lhs, production.rhs] #: [Integer, Array[Integer]] if seen.key?(signature) @warnings << { type: :duplicate_production, production: production.id, original: seen[signature], loc: production.origin[:loc] } else seen[signature] = production.id end end end |
#warn_empty_language ⇒ void
This method returns an undefined value.
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/ibex/normalize/diagnostics.rb', line 114 def warn_empty_language # @type self: Normalizer productive = productive_terminal_ids loop do before = productive.length @productions.each do |production| productive << production.lhs if production.rhs.all? { |id| productive.include?(id) } end break if productive.length == before end @start_names.each do |name| next if productive.include?(required_symbol(name).id) start_symbol = required_symbol(name) @warnings << { type: :empty_language, symbol: name, loc: start_symbol.location } end end |
#warn_unreachable_nonterminals ⇒ void
This method returns an undefined value.
49 50 51 52 53 54 55 56 57 |
# File 'lib/ibex/normalize/diagnostics.rb', line 49 def warn_unreachable_nonterminals # @type self: Normalizer reachable = reachable_symbol_ids @symbols.select(&:nonterminal?).each do |grammar_symbol| next if reachable.include?(grammar_symbol.id) || grammar_symbol.name.start_with?("$") @warnings << { type: :unreachable_nonterminal, symbol: grammar_symbol.name, loc: grammar_symbol.location } end end |
#warn_unreachable_terminals ⇒ void
This method returns an undefined value.
85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/ibex/normalize/diagnostics.rb', line 85 def warn_unreachable_terminals # @type self: Normalizer reachable = reachable_symbol_ids used = @productions.flat_map(&:rhs).to_set @declared_tokens.each_key do |name| grammar_symbol = required_symbol(name) next unless used.include?(grammar_symbol.id) next if reachable.include?(grammar_symbol.id) @warnings << { type: :unreachable_terminal, symbol: name, loc: @declared_tokens[name] } end end |
#warn_unused_precedence ⇒ void
This method returns an undefined value.
99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/ibex/normalize/diagnostics.rb', line 99 def warn_unused_precedence # @type self: Normalizer referenced = @productions.each_with_object(Set.new) do |production, symbol_ids| production.rhs.each { |id| symbol_ids << id } symbol_ids << production.precedence_override if production.precedence_override end @precedence.each_key do |name| grammar_symbol = required_symbol(name) next if referenced.include?(grammar_symbol.id) @warnings << { type: :unused_precedence, symbol: name, loc: @precedence_locations[name] } end end |
#warn_unused_terminals ⇒ void
This method returns an undefined value.
74 75 76 77 78 79 80 81 82 |
# File 'lib/ibex/normalize/diagnostics.rb', line 74 def warn_unused_terminals # @type self: Normalizer used = @productions.flat_map(&:rhs).to_set @symbols.select(&:terminal?).each do |grammar_symbol| next if grammar_symbol.reserved || used.include?(grammar_symbol.id) || @precedence.key?(grammar_symbol.name) @warnings << { type: :unused_terminal, symbol: grammar_symbol.name, loc: grammar_symbol.location } end end |