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

Instance Method Details

#productive_terminal?(grammar_symbol) ⇒ Boolean

RBS:

  • (IR::GrammarSymbol grammar_symbol) -> bool

Parameters:

Returns:

  • (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_idsSet[Integer]

RBS:

  • () -> Set[Integer]

Returns:

  • (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_idsSet[Integer]

RBS:

  • () -> Set[Integer]

Returns:

  • (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_grammarvoid

This method returns an undefined value.

RBS:

  • () -> void



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_metadatavoid

This method returns an undefined value.

RBS:

  • () -> void



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_productionsvoid

This method returns an undefined value.

RBS:

  • () -> void



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_languagevoid

This method returns an undefined value.

RBS:

  • () -> void



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_nonterminalsvoid

This method returns an undefined value.

RBS:

  • () -> void



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_terminalsvoid

This method returns an undefined value.

RBS:

  • () -> void



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_precedencevoid

This method returns an undefined value.

RBS:

  • () -> void



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_terminalsvoid

This method returns an undefined value.

RBS:

  • () -> void



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