Class: Ibex::Normalizer

Overview

Converts a frontend AST into immutable Grammar IR.

Constant Summary collapse

RESERVED_NAMES =

: Array

%w[result val _values].freeze
RUBY_KEYWORDS =
%w[
  __ENCODING__ __FILE__ __LINE__ alias and begin break case class def defined do else elsif end ensure false for if
  in module next nil not or redo rescue retry return self super then true undef unless until when while yield
].freeze
DEFAULT_MAX_PARAMETER_SPECIALIZATIONS =

: Array

1_000
DEFAULT_MAX_INLINE_EXPANSIONS =
10_000

Instance Method Summary collapse

Constructor Details

#initialize(input, mode: :default, max_parameter_specializations: DEFAULT_MAX_PARAMETER_SPECIALIZATIONS, max_inline_expansions: DEFAULT_MAX_INLINE_EXPANSIONS) ⇒ Normalizer

Returns a new instance of Normalizer.

Raises:

  • (ArgumentError)


94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/ibex/normalize.rb', line 94

def initialize(input, mode: :default, max_parameter_specializations: DEFAULT_MAX_PARAMETER_SPECIALIZATIONS,
               max_inline_expansions: DEFAULT_MAX_INLINE_EXPANSIONS)
  validate_positive_limit!(:max_parameter_specializations, max_parameter_specializations)
  validate_positive_limit!(:max_inline_expansions, max_inline_expansions)
  normalized_mode = mode.to_sym
  raise ArgumentError, "mode must be :default or :extended" unless %i[default extended].include?(normalized_mode)

  @resolution = input if input.is_a?(Frontend::Resolution)
  ast = input.is_a?(Frontend::Resolution) ? input.root : input
  normalized_mode = :extended if ast.is_a?(Frontend::AST::Root) && ast.extended
  fail_at(ast.loc, "fragments must be resolved before normalization") if ast.is_a?(Frontend::AST::Fragment)
  unresolved = ast.declarations.find { |declaration| declaration.is_a?(Frontend::AST::Include) }
  fail_at(unresolved.loc, "includes must be resolved before normalization") if unresolved

  @ast = ast
  @mode = normalized_mode #: IR::grammar_mode
  @symbols = [] #: Array[IR::GrammarSymbol]
  @symbols_by_name = {} #: Hash[String, IR::GrammarSymbol]
  @productions = [] #: Array[IR::Production]
  @warnings = [] #: Array[IR::grammar_warning]
  @helper_sequence = 0
  @current_include_chain = [] #: Array[IR::source_provenance]
  @parameter_specializations = {} #: Hash[[String, Array[String]], String]
  @parameter_worklist = [] #: Array[Hash[Symbol, untyped]]
  @parameter_worklist_active = false
  @max_parameter_specializations = max_parameter_specializations
  @max_inline_expansions = max_inline_expansions
  @inline_expansion_count = 0
  @inline_symbol_ids = Set.new #: Set[Integer]
  @inline_rule_by_symbol = {} #: Hash[Integer, String]
end

Instance Method Details

#normalizeObject



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/ibex/normalize.rb', line 127

def normalize
  read_declarations
  gather_parameter_templates
  gather_inline_rules
  intern_reserved_symbols
  intern_declared_terminals
  intern_user_nonterminals
  normalize_user_productions
  expand_inline_rules
  validate_value_printers
  validate_recovery_declarations
  validate_grammar
  IR::Grammar.new(class_name: @ast.class_name, superclass: @ast.superclass, start: @start_name,
                  expect: @expected_conflicts, options: @options, symbols: @symbols,
                  mode: @mode, starts: @start_names,
                  expect_rr: @expected_rr_conflicts,
                  parser_parameters: @parser_parameters,
                  value_printers: @value_printers.values,
                  grammar_tests: @grammar_tests,
                  lexer: normalize_lexer,
                  recovery: {
                    sync_tokens: @recovery_sync_tokens,
                    on_error_reduce: @on_error_reduce_groups
                  },
                  productions: @productions, user_code: normalized_user_code,
                  conversions: @conversions, warnings: @warnings, user_code_chunks: normalized_user_code_chunks,
                  source_provenance: {
                    file: @ast.loc.file, root: @resolution&.root_directory, byte_span: nil
                  })
end