Module: Ibex::NormalizeParameterValidation

Included in:
Normalizer
Defined in:
lib/ibex/normalize/parameter_validation.rb,
sig/ibex/normalize/parameter_validation.rbs

Overview

Static validation and collection of parameterized user rule definitions.

Instance Method Summary collapse

Instance Method Details

#gather_parameter_templatesvoid

This method returns an undefined value.

RBS:

  • () -> void



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/ibex/normalize/parameter_validation.rb', line 9

def gather_parameter_templates
  # @type self: Normalizer
  @parameter_templates = {} #: Hash[String, Array[Frontend::AST::Rule]]
  @parameter_formals = {} #: Hash[String, Array[String]]
  plain_rules = {} #: Hash[String, Frontend::AST::Rule]
  @rule_documentation = validated_rule_documentation

  @ast.rules.each do |rule|
    if parameterized_rule?(rule)
      gather_parameterized_rule(rule, plain_rules)
    else
      reject_mixed_parameterized_rule(rule) if @parameter_templates.key?(rule.lhs)
      plain_rules[rule.lhs] ||= rule
    end
  end
  validate_parameter_terminal_collisions
  @ast.rules.each { |rule| validate_parameter_references(rule) }
end

#gather_parameterized_rule(rule, plain_rules) ⇒ void

This method returns an undefined value.

RBS:

  • (Frontend::AST::Rule rule, Hash[String, Frontend::AST::Rule] plain_rules) -> void

Parameters:



29
30
31
32
33
34
35
36
37
38
# File 'lib/ibex/normalize/parameter_validation.rb', line 29

def gather_parameterized_rule(rule, plain_rules)
  # @type self: Normalizer
  reject_mixed_parameterized_rule(rule) if plain_rules.key?(rule.lhs)
  duplicate = rule.parameters.tally.find { |_name, count| count > 1 }&.first
  fail_at(rule.loc, "duplicate parameter #{duplicate} in rule #{rule.lhs}") if duplicate

  validate_parameter_formals(rule)
  @parameter_formals[rule.lhs] ||= rule.parameters
  (@parameter_templates[rule.lhs] ||= Array.new(0)) << rule
end

#parameter_template?(name) ⇒ Boolean

RBS:

  • (String name) -> bool

Parameters:

  • name (String)

Returns:

  • (Boolean)


136
137
138
# File 'lib/ibex/normalize/parameter_validation.rb', line 136

def parameter_template?(name)
  @parameter_templates.key?(name)
end

#parameterized_rule?(rule) ⇒ Boolean

RBS:

  • (Frontend::AST::Rule rule) -> bool

Parameters:

Returns:

  • (Boolean)


131
132
133
# File 'lib/ibex/normalize/parameter_validation.rb', line 131

def parameterized_rule?(rule)
  !rule.parameters.empty?
end

#reject_argument_named_reference(item) ⇒ bot

RBS:

  • (Frontend::AST::SymbolReference | Frontend::AST::ParameterizedReference item) -> bot

Parameters:

Returns:

  • (bot)


111
112
113
114
# File 'lib/ibex/normalize/parameter_validation.rb', line 111

def reject_argument_named_reference(item)
  # @type self: Normalizer
  fail_at(item.loc, "named references are not allowed in parameter arguments")
end

#reject_mixed_parameterized_rule(rule) ⇒ bot

RBS:

  • (Frontend::AST::Rule rule) -> bot

Parameters:

Returns:

  • (bot)


54
55
56
57
# File 'lib/ibex/normalize/parameter_validation.rb', line 54

def reject_mixed_parameterized_rule(rule)
  # @type self: Normalizer
  fail_at(rule.loc, "rule #{rule.lhs} has both plain and parameterized definitions")
end

#validate_parameter_call(reference) ⇒ void

This method returns an undefined value.

RBS:

  • (Frontend::AST::ParameterizedReference reference) -> void

Parameters:



117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/ibex/normalize/parameter_validation.rb', line 117

def validate_parameter_call(reference)
  # @type self: Normalizer
  formals = @parameter_formals[reference.name]
  fail_at(reference.loc, "undefined parameterized rule #{reference.name}") unless formals
  return if reference.arguments.length == formals.length

  fail_at(
    reference.loc,
    "parameterized rule #{reference.name} expects #{formals.length} arguments, " \
    "got #{reference.arguments.length}"
  )
end

#validate_parameter_formals(rule) ⇒ void

This method returns an undefined value.

RBS:

  • (Frontend::AST::Rule rule) -> void

Parameters:



41
42
43
44
45
46
47
48
49
50
51
# File 'lib/ibex/normalize/parameter_validation.rb', line 41

def validate_parameter_formals(rule)
  # @type self: Normalizer
  expected = @parameter_formals[rule.lhs]
  return unless expected && expected != rule.parameters

  fail_at(
    rule.loc,
    "parameterized rule #{rule.lhs} uses inconsistent parameters " \
    "(expected #{expected.join(', ')}, got #{rule.parameters.join(', ')})"
  )
end

#validate_parameter_item(item, formals, inside_argument:) ⇒ void

This method returns an undefined value.

RBS:

  • (Frontend::AST::item item, Array[String] formals, inside_argument: bool) -> void

Parameters:

  • item (Frontend::AST::item)
  • formals (Array[String])
  • inside_argument: (Boolean)


80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/ibex/normalize/parameter_validation.rb', line 80

def validate_parameter_item(item, formals, inside_argument:)
  # @type self: Normalizer
  case item
  when Frontend::AST::ParameterizedReference
    validate_parameterized_item(item, formals, inside_argument: inside_argument)
  when Frontend::AST::SymbolReference
    reject_argument_named_reference(item) if inside_argument && item.named_reference
  when Frontend::AST::Group
    item.alternatives.flatten.each do |child|
      validate_parameter_item(child, formals, inside_argument: inside_argument)
    end
  when Frontend::AST::Optional, Frontend::AST::Star, Frontend::AST::Plus
    validate_parameter_item(item.item, formals, inside_argument: inside_argument)
  when Frontend::AST::SeparatedList
    validate_parameter_item(item.item, formals, inside_argument: inside_argument)
    validate_parameter_item(item.separator, formals, inside_argument: inside_argument)
  end
end

#validate_parameter_references(rule) ⇒ void

This method returns an undefined value.

RBS:

  • (Frontend::AST::Rule rule) -> void

Parameters:



70
71
72
73
74
75
76
77
# File 'lib/ibex/normalize/parameter_validation.rb', line 70

def validate_parameter_references(rule)
  # @type self: Normalizer
  rule.alternatives.each do |alternative|
    alternative.items.each do |item|
      validate_parameter_item(item, rule.parameters, inside_argument: false)
    end
  end
end

#validate_parameter_terminal_collisionsvoid

This method returns an undefined value.

RBS:

  • () -> void



60
61
62
63
64
65
66
67
# File 'lib/ibex/normalize/parameter_validation.rb', line 60

def validate_parameter_terminal_collisions
  # @type self: Normalizer
  @parameter_templates.each do |name, rules|
    next unless @declared_tokens.key?(name) || @precedence.key?(name)

    fail_at(rules.fetch(0).loc, "parameterized rule #{name} collides with terminal #{name}")
  end
end

#validate_parameterized_item(item, formals, inside_argument:) ⇒ void

This method returns an undefined value.

RBS:

  • (Frontend::AST::ParameterizedReference item, Array[String] formals, inside_argument: bool) -> void

Parameters:



100
101
102
103
104
105
106
107
108
# File 'lib/ibex/normalize/parameter_validation.rb', line 100

def validate_parameterized_item(item, formals, inside_argument:)
  # @type self: Normalizer
  if formals.include?(item.name)
    fail_at(item.loc, "formal #{item.name} cannot be used as a parameterized rule name")
  end
  validate_parameter_call(item)
  reject_argument_named_reference(item) if inside_argument && item.named_reference
  item.arguments.each { |argument| validate_parameter_item(argument, formals, inside_argument: true) }
end