Module: Ibex::NormalizeExpander
- Included in:
- Normalizer
- Defined in:
- lib/ibex/normalize/expander.rb,
sig/ibex/normalize/expander.rbs
Overview
Production and EBNF expansion used by Normalizer.
Instance Method Summary collapse
- #add_group_production(helper, rhs, item) ⇒ void
- #add_production(lhs_name, rhs_names, action, precedence_name, origin, documentation = nil, node = nil) ⇒ void
- #build_optional(item, base) ⇒ String
- #build_plus(item, base) ⇒ String
- #build_separated_list(item, base, separator) ⇒ String
- #build_star(item, base) ⇒ String
- #expand_group(item) ⇒ String
- #expand_inline_action(item, context_length, named_refs) ⇒ String
- #expand_optional(item) ⇒ String
- #expand_plus(item) ⇒ String
- #expand_separated_list(item) ⇒ String
- #expand_star(item) ⇒ String
- #group_value_expression(length) ⇒ String
- #new_helper(kind, location) ⇒ String
- #normalize_action(action, named_refs) ⇒ IR::Action?
- #normalize_alternative(rule, alternative) ⇒ void
- #normalize_item(item) ⇒ String
- #normalize_user_productions ⇒ void
- #normalized_alternative_items(alternative) ⇒ Array[Frontend::AST::item]
- #synthetic_action(expression, location) ⇒ IR::Action
- #synthetic_origin(kind, item) ⇒ Hash[Symbol, untyped]
Instance Method Details
#add_group_production(helper, rhs, item) ⇒ void
This method returns an undefined value.
164 165 166 167 168 |
# File 'lib/ibex/normalize/expander.rb', line 164 def add_group_production(helper, rhs, item) # @type self: Normalizer expression = group_value_expression(rhs.length) add_production(helper, rhs, synthetic_action(expression, item.loc), nil, synthetic_origin(:group, item)) end |
#add_production(lhs_name, rhs_names, action, precedence_name, origin, documentation = nil, node = nil) ⇒ void
This method returns an undefined value.
211 212 213 214 215 216 217 218 219 220 |
# File 'lib/ibex/normalize/expander.rb', line 211 def add_production(lhs_name, rhs_names, action, precedence_name, origin, documentation = nil, node = nil) # @type self: Normalizer lhs = symbol(lhs_name) || intern(lhs_name, :nonterminal, location: origin[:loc]) rhs = rhs_names.map { |name| symbol(name)&.id || fail_hash(origin[:loc], "undefined symbol #{name}") } precedence = precedence_name && symbol(precedence_name) fail_hash(origin[:loc], "undefined precedence symbol #{precedence_name}") if precedence_name && !precedence @productions << IR::Production.new(id: @productions.length, lhs: lhs.id, rhs: rhs, action: action, precedence_override: precedence&.id, origin: origin, documentation: documentation, expansion: resolved_expansion, node: node) end |
#build_optional(item, base) ⇒ String
87 88 89 90 91 92 93 |
# File 'lib/ibex/normalize/expander.rb', line 87 def build_optional(item, base) # @type self: Normalizer helper = new_helper("optional", item.loc) add_production(helper, [], synthetic_action("nil", item.loc), nil, synthetic_origin(:optional, item)) add_production(helper, [base], synthetic_action("val[0]", item.loc), nil, synthetic_origin(:optional, item)) helper end |
#build_plus(item, base) ⇒ String
120 121 122 123 124 125 126 127 |
# File 'lib/ibex/normalize/expander.rb', line 120 def build_plus(item, base) # @type self: Normalizer helper = new_helper("plus", item.loc) add_production(helper, [base], synthetic_action("[val[0]]", item.loc), nil, synthetic_origin(:plus, item)) add_production(helper, [helper, base], synthetic_action("val[0] + [val[1]]", item.loc), nil, synthetic_origin(:plus, item)) helper end |
#build_separated_list(item, base, separator) ⇒ String
138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/ibex/normalize/expander.rb', line 138 def build_separated_list(item, base, separator) # @type self: Normalizer helper = new_helper("separated_list", item.loc) unless item.nonempty add_production(helper, [], synthetic_action("[]", item.loc), nil, synthetic_origin(:separated_list, item)) end add_production(helper, [base], synthetic_action("[val[0]]", item.loc), nil, synthetic_origin(:separated_list, item)) add_production(helper, [helper, separator, base], synthetic_action("val[0] + [val[2]]", item.loc), nil, synthetic_origin(:separated_list, item)) helper end |
#build_star(item, base) ⇒ String
103 104 105 106 107 108 109 110 |
# File 'lib/ibex/normalize/expander.rb', line 103 def build_star(item, base) # @type self: Normalizer helper = new_helper("star", item.loc) add_production(helper, [], synthetic_action("[]", item.loc), nil, synthetic_origin(:star, item)) add_production(helper, [helper, base], synthetic_action("val[0] + [val[1]]", item.loc), nil, synthetic_origin(:star, item)) helper end |
#expand_group(item) ⇒ String
152 153 154 155 156 157 158 159 160 161 |
# File 'lib/ibex/normalize/expander.rb', line 152 def (item) # @type self: Normalizer reject_group_named_references(item) helper = new_helper("group", item.loc) item.alternatives.each do |alternative| rhs = alternative.map { |child| normalize_item(child) } add_group_production(helper, rhs, item) end helper end |
#expand_inline_action(item, context_length, named_refs) ⇒ String
70 71 72 73 74 75 76 77 |
# File 'lib/ibex/normalize/expander.rb', line 70 def (item, context_length, named_refs) # @type self: Normalizer helper = new_helper("inline", item.loc) action = IR::Action.new(code: item.code, location: item.loc.to_h, named_refs: named_refs.map(&:dup), context_length: context_length) add_production(helper, [], action, nil, { kind: :inline_action, loc: item.loc.to_h }) helper end |
#expand_optional(item) ⇒ String
80 81 82 83 84 |
# File 'lib/ibex/normalize/expander.rb', line 80 def (item) # @type self: Normalizer base = normalize_item(item.item) build_optional(item, base) end |
#expand_plus(item) ⇒ String
113 114 115 116 117 |
# File 'lib/ibex/normalize/expander.rb', line 113 def (item) # @type self: Normalizer base = normalize_item(item.item) build_plus(item, base) end |
#expand_separated_list(item) ⇒ String
130 131 132 133 134 135 |
# File 'lib/ibex/normalize/expander.rb', line 130 def (item) # @type self: Normalizer base = normalize_item(item.item) separator = normalize_item(item.separator) build_separated_list(item, base, separator) end |
#expand_star(item) ⇒ String
96 97 98 99 100 |
# File 'lib/ibex/normalize/expander.rb', line 96 def (item) # @type self: Normalizer base = normalize_item(item.item) build_star(item, base) end |
#group_value_expression(length) ⇒ String
171 172 173 174 175 176 177 |
# File 'lib/ibex/normalize/expander.rb', line 171 def group_value_expression(length) # @type self: Normalizer return "nil" if length.zero? return "val[0]" if length == 1 "val" end |
#new_helper(kind, location) ⇒ String
180 181 182 183 184 185 186 |
# File 'lib/ibex/normalize/expander.rb', line 180 def new_helper(kind, location) # @type self: Normalizer @helper_sequence += 1 name = "$#{kind}_#{@helper_sequence}" intern(name, :nonterminal, location: location.to_h) name end |
#normalize_action(action, named_refs) ⇒ IR::Action?
202 203 204 205 206 207 |
# File 'lib/ibex/normalize/expander.rb', line 202 def normalize_action(action, named_refs) # @type self: Normalizer return nil unless action IR::Action.new(code: action.code, location: action.loc.to_h, named_refs: named_refs) end |
#normalize_alternative(rule, alternative) ⇒ void
This method returns an undefined value.
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/ibex/normalize/expander.rb', line 20 def normalize_alternative(rule, alternative) # @type self: Normalizer rhs = [] #: Array[String] named_refs = [] #: Array[IR::named_ref] items = normalized_alternative_items(alternative) items.each do |item| if item.is_a?(Frontend::AST::InlineAction) rhs << (item, rhs.length, named_refs) next end rhs << normalize_item(item) add_named_reference(item, named_refs, rhs.length - 1) end action = normalize_action(alternative.action, named_refs) node = normalize_node_annotation(alternative, rhs) add_production(rule.lhs, rhs, action, alternative.precedence, { kind: :user, loc: alternative.loc.to_h }, rule.documentation, node) end |
#normalize_item(item) ⇒ String
56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/ibex/normalize/expander.rb', line 56 def normalize_item(item) # @type self: Normalizer return symbol_for_reference(item).name if item.is_a?(Frontend::AST::SymbolReference) return specialize_parameterized_reference(item) if item.is_a?(Frontend::AST::ParameterizedReference) return (item) if item.is_a?(Frontend::AST::Group) return (item) if item.is_a?(Frontend::AST::Optional) return (item) if item.is_a?(Frontend::AST::Star) return (item) if item.is_a?(Frontend::AST::Plus) return (item) if item.is_a?(Frontend::AST::SeparatedList) fail_at(item.loc, "unsupported nested EBNF expression") end |
#normalize_user_productions ⇒ void
This method returns an undefined value.
9 10 11 12 13 14 15 16 17 |
# File 'lib/ibex/normalize/expander.rb', line 9 def normalize_user_productions # @type self: Normalizer @ast.rules.each do |rule| next if parameterized_rule?(rule) @current_include_chain = @resolution&.include_chain_for(rule) || [] rule.alternatives.each { |alternative| normalize_alternative(rule, alternative) } end end |
#normalized_alternative_items(alternative) ⇒ Array[Frontend::AST::item]
41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/ibex/normalize/expander.rb', line 41 def normalized_alternative_items(alternative) # @type self: Normalizer explicit = alternative.items.grep(Frontend::AST::Empty) if explicit.any? fail_at(explicit.first.loc, "%empty must be the only item in an alternative") unless alternative.items.one? return [] end if alternative.items.empty? && (@mode.to_sym == :extended || @ast.extended) @warnings << { type: :implicit_empty, loc: alternative.loc.to_h } end alternative.items end |
#synthetic_action(expression, location) ⇒ IR::Action
189 190 191 192 193 |
# File 'lib/ibex/normalize/expander.rb', line 189 def synthetic_action(expression, location) # @type self: Normalizer code = @options[:result_var] ? " result = #{expression} " : " #{expression} " IR::Action.new(code: code, location: location.to_h) end |
#synthetic_origin(kind, item) ⇒ Hash[Symbol, untyped]
196 197 198 199 |
# File 'lib/ibex/normalize/expander.rb', line 196 def synthetic_origin(kind, item) # @type self: Normalizer { kind: :"#{kind}_expansion", expression: NormalizeExpression.render(item), loc: item.loc.to_h } end |