Module: RailroadDiagrams::Transform::Lint

Defined in:
lib/railroad_diagrams/transform/lint.rb

Overview

Finds likely grammar mistakes without changing the rules.

Examples:

Transform::Lint.call([['entry', NonTerminal.new('missing')]])

Defined Under Namespace

Classes: Warning

Class Method Summary collapse

Class Method Details

.call(rules) ⇒ Object

Returns warnings for the given ordered rule pairs.

Examples:

Transform::Lint.call([['entry', Terminal.new('a')]])


19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/railroad_diagrams/transform/lint.rb', line 19

def call(rules)
  definitions = rules.map(&:first)
  references = []
  warnings = []

  rules.each_with_index do |(name, node), index|
    warnings << Warning.new(:duplicate_definition, name, name, "duplicate rule definition: #{name}") if definitions[0...index].include?(name)

    node.each_node do |item|
      if item.is_a?(NonTerminal)
        target = item.instance_variable_get(:@text)
        references << target
        warnings << Warning.new(:undefined_reference, name, target, "undefined rule: #{target}") unless definitions.include?(target)
      elsif item.is_a?(Choice)
        check_choice(item, name, warnings)
      end
    end
  end

  definitions.uniq.drop(1).each do |name|
    next if references.include?(name)

    warnings << Warning.new(:unreferenced_rule, name, name, "rule is never referenced: #{name}")
  end
  warnings.uniq { |warning| [warning.kind, warning.rule, warning.name, warning.message] }
end