Class: Ibex::IR::Grammar

Inherits:
Object
  • Object
show all
Defined in:
lib/ibex/ir/grammar_ir.rb,
sig/ibex/ir/grammar_ir.rbs

Overview

Immutable normalized grammar exchanged between pipeline stages.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(class_name:, superclass:, start:, expect:, options:, symbols:, productions:, user_code:, conversions:, warnings:, user_code_chunks: nil, source_provenance: nil, expect_rr: nil, parser_parameters: [], value_printers: [], grammar_tests: [], recovery: nil, lexer: nil, mode: :default, starts: nil, parser_contract: ParserContract.new) ⇒ Grammar

rubocop:disable Metrics/AbcSize, Metrics/ParameterLists Immutable current IR is constructed from explicit public fields.

RBS:

  • (class_name: String, superclass: String?, start: String, expect: Integer, ?expect_rr: Integer?, options: grammar_options, symbols: Array[GrammarSymbol], productions: Array[Production], user_code: Hash[String, String], conversions: Hash[String, String], warnings: Array[grammar_warning], ?user_code_chunks: user_code_chunks?, ?parser_parameters: Array[parser_parameter], ?value_printers: Array[value_printer], ?grammar_tests: Array[grammar_test], ?recovery: recovery_policy?, ?lexer: Lexer?, ?mode: grammar_mode, ?starts: Array[String]?, ?parser_contract: ParserContract, ?source_provenance: source_provenance?) -> void

Parameters:

  • class_name: (String)
  • superclass: (String, nil)
  • start: (String)
  • expect: (Integer)
  • options: (grammar_options)
  • symbols: (Array[GrammarSymbol])
  • productions: (Array[Production])
  • user_code: (Hash[String, String])
  • conversions: (Hash[String, String])
  • warnings: (Array[grammar_warning])
  • expect_rr: (Integer, nil) (defaults to: nil)
  • user_code_chunks: (user_code_chunks, nil) (defaults to: nil)
  • parser_parameters: (Array[parser_parameter]) (defaults to: [])
  • value_printers: (Array[value_printer]) (defaults to: [])
  • grammar_tests: (Array[grammar_test]) (defaults to: [])
  • recovery: (recovery_policy, nil) (defaults to: nil)
  • lexer: (Lexer, nil) (defaults to: nil)
  • mode: (grammar_mode) (defaults to: :default)
  • starts: (Array[String], nil) (defaults to: nil)
  • parser_contract: (ParserContract) (defaults to: ParserContract.new)
  • source_provenance: (source_provenance, nil) (defaults to: nil)


193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/ibex/ir/grammar_ir.rb', line 193

def initialize(class_name:, superclass:, start:, expect:, options:, symbols:, productions:, user_code:,
               conversions:, warnings:, user_code_chunks: nil,
               source_provenance: nil, expect_rr: nil, parser_parameters: [], value_printers: [],
               grammar_tests: [], recovery: nil, lexer: nil, mode: :default, starts: nil,
               parser_contract: ParserContract.new)
  initialize_current(
    class_name: class_name, superclass: superclass, start: start, expect: expect, options: options,
    symbols: symbols, productions: productions, user_code: user_code, conversions: conversions,
    warnings: warnings, user_code_chunks: user_code_chunks,
    source_provenance: source_provenance, expect_rr: expect_rr,
    parser_parameters: parser_parameters, value_printers: value_printers, grammar_tests: grammar_tests,
    recovery: recovery, lexer: lexer, mode: mode, starts: starts, parser_contract: parser_contract
  )
end

Instance Attribute Details

#class_nameString (readonly)

Signature:

  • String

Returns:

  • (String)


159
160
161
# File 'lib/ibex/ir/grammar_ir.rb', line 159

def class_name
  @class_name
end

#conversionsHash[String, String] (readonly)

Signature:

  • Hash[String, String]

Returns:

  • (Hash[String, String])


176
177
178
# File 'lib/ibex/ir/grammar_ir.rb', line 176

def conversions
  @conversions
end

#expectInteger (readonly)

Signature:

  • Integer

Returns:

  • (Integer)


164
165
166
# File 'lib/ibex/ir/grammar_ir.rb', line 164

def expect
  @expect
end

#expect_rrInteger? (readonly)

Signature:

  • Integer?

Returns:

  • (Integer, nil)


165
166
167
# File 'lib/ibex/ir/grammar_ir.rb', line 165

def expect_rr
  @expect_rr
end

#grammar_testsArray[grammar_test] (readonly)

Signature:

  • Array[grammar_test]

Returns:

  • (Array[grammar_test])


168
169
170
# File 'lib/ibex/ir/grammar_ir.rb', line 168

def grammar_tests
  @grammar_tests
end

#lexerLexer? (readonly)

Signature:

  • Lexer?

Returns:



169
170
171
# File 'lib/ibex/ir/grammar_ir.rb', line 169

def lexer
  @lexer
end

#modegrammar_mode (readonly)

Signature:

  • grammar_mode

Returns:

  • (grammar_mode)


163
164
165
# File 'lib/ibex/ir/grammar_ir.rb', line 163

def mode
  @mode
end

#optionsgrammar_options (readonly)

Signature:

  • grammar_options

Returns:

  • (grammar_options)


171
172
173
# File 'lib/ibex/ir/grammar_ir.rb', line 171

def options
  @options
end

#parser_contractParserContract (readonly)

Signature:

  • ParserContract

Returns:



180
181
182
# File 'lib/ibex/ir/grammar_ir.rb', line 180

def parser_contract
  @parser_contract
end

#parser_parametersArray[parser_parameter] (readonly)

Signature:

  • Array[parser_parameter]

Returns:

  • (Array[parser_parameter])


166
167
168
# File 'lib/ibex/ir/grammar_ir.rb', line 166

def parser_parameters
  @parser_parameters
end

#productionsArray[Production] (readonly)

Signature:

  • Array[Production]

Returns:



173
174
175
# File 'lib/ibex/ir/grammar_ir.rb', line 173

def productions
  @productions
end

#recoveryrecovery_policy (readonly)

Signature:

  • recovery_policy

Returns:

  • (recovery_policy)


170
171
172
# File 'lib/ibex/ir/grammar_ir.rb', line 170

def recovery
  @recovery
end

#schema_versionInteger (readonly)

Signature:

  • Integer

Returns:

  • (Integer)


178
179
180
# File 'lib/ibex/ir/grammar_ir.rb', line 178

def schema_version
  @schema_version
end

#source_provenancesource_provenance? (readonly)

Signature:

  • source_provenance?

Returns:



179
180
181
# File 'lib/ibex/ir/grammar_ir.rb', line 179

def source_provenance
  @source_provenance
end

#startString (readonly)

Signature:

  • String

Returns:

  • (String)


161
162
163
# File 'lib/ibex/ir/grammar_ir.rb', line 161

def start
  @start
end

#startsArray[String] (readonly)

Signature:

  • Array[String]

Returns:

  • (Array[String])


162
163
164
# File 'lib/ibex/ir/grammar_ir.rb', line 162

def starts
  @starts
end

#superclassString? (readonly)

Signature:

  • String?

Returns:

  • (String, nil)


160
161
162
# File 'lib/ibex/ir/grammar_ir.rb', line 160

def superclass
  @superclass
end

#symbolsArray[GrammarSymbol] (readonly)

Signature:

  • Array[GrammarSymbol]

Returns:



172
173
174
# File 'lib/ibex/ir/grammar_ir.rb', line 172

def symbols
  @symbols
end

#user_codeHash[String, String] (readonly)

Signature:

  • Hash[String, String]

Returns:

  • (Hash[String, String])


174
175
176
# File 'lib/ibex/ir/grammar_ir.rb', line 174

def user_code
  @user_code
end

#user_code_chunksuser_code_chunks (readonly)

Signature:

  • user_code_chunks

Returns:



175
176
177
# File 'lib/ibex/ir/grammar_ir.rb', line 175

def user_code_chunks
  @user_code_chunks
end

#value_printersArray[value_printer] (readonly)

Signature:

  • Array[value_printer]

Returns:

  • (Array[value_printer])


167
168
169
# File 'lib/ibex/ir/grammar_ir.rb', line 167

def value_printers
  @value_printers
end

#warningsArray[grammar_warning] (readonly)

Signature:

  • Array[grammar_warning]

Returns:

  • (Array[grammar_warning])


177
178
179
# File 'lib/ibex/ir/grammar_ir.rb', line 177

def warnings
  @warnings
end

Instance Method Details

#append_optional_metadata(value) ⇒ void

This method returns an undefined value.

RBS:

  • (Hash[Symbol, Object?] value) -> void

Parameters:

  • value (Hash[Symbol, Object?])


292
293
294
295
296
297
298
299
# File 'lib/ibex/ir/grammar_ir.rb', line 292

def (value)
  (value)
  (value)
  value[:user_code_chunks] = @user_code_chunks.transform_values { |chunks| chunks.map(&:to_h) } \
    unless @user_code_chunks.empty?
  value[:source_provenance] = @source_provenance
  value[:parser_contract] = @parser_contract.to_h
end

#append_parser_metadata(value) ⇒ void

This method returns an undefined value.

RBS:

  • (Hash[Symbol, Object?] value) -> void

Parameters:

  • value (Hash[Symbol, Object?])


302
303
304
305
306
307
308
309
310
# File 'lib/ibex/ir/grammar_ir.rb', line 302

def (value)
  value[:expect_rr] = @expect_rr unless @expect_rr.nil?
  value[:mode] = @mode if @mode == :extended
  value[:starts] = @starts if @starts.length > 1
  value[:params] = @parser_parameters unless @parser_parameters.empty?
  value[:printers] = @value_printers unless @value_printers.empty?
  value[:tests] = @grammar_tests unless @grammar_tests.empty?
  value[:lexer] = @lexer.to_h if @lexer
end

#append_recovery_metadata(value) ⇒ void

This method returns an undefined value.

RBS:

  • (Hash[Symbol, Object?] value) -> void

Parameters:

  • value (Hash[Symbol, Object?])


313
314
315
316
317
# File 'lib/ibex/ir/grammar_ir.rb', line 313

def (value)
  return if @recovery[:sync_tokens].empty? && @recovery[:on_error_reduce].empty?

  value[:recovery] = @recovery
end

#initialize_current(class_name:, superclass:, start:, expect:, options:, symbols:, productions:, user_code:, conversions:, warnings:, user_code_chunks:, source_provenance:, expect_rr:, parser_parameters:, value_printers:, grammar_tests:, recovery:, lexer:, mode:, starts:, parser_contract:) ⇒ void

This method returns an undefined value.

RBS:

  • (class_name: String, superclass: String?, start: String, expect: Integer, options: grammar_options, symbols: Array[GrammarSymbol], productions: Array[Production], user_code: Hash[String, String], conversions: Hash[String, String], warnings: Array[grammar_warning], user_code_chunks: user_code_chunks?, source_provenance: source_provenance?, expect_rr: Integer?, parser_parameters: Array[parser_parameter], value_printers: Array[value_printer], grammar_tests: Array[grammar_test], recovery: recovery_policy?, lexer: Lexer?, mode: grammar_mode, starts: Array[String]?, parser_contract: ParserContract) -> void

Parameters:

  • class_name: (String)
  • superclass: (String, nil)
  • start: (String)
  • expect: (Integer)
  • options: (grammar_options)
  • symbols: (Array[GrammarSymbol])
  • productions: (Array[Production])
  • user_code: (Hash[String, String])
  • conversions: (Hash[String, String])
  • warnings: (Array[grammar_warning])
  • user_code_chunks: (user_code_chunks, nil)
  • source_provenance: (source_provenance, nil)
  • expect_rr: (Integer, nil)
  • parser_parameters: (Array[parser_parameter])
  • value_printers: (Array[value_printer])
  • grammar_tests: (Array[grammar_test])
  • recovery: (recovery_policy, nil)
  • lexer: (Lexer, nil)
  • mode: (grammar_mode)
  • starts: (Array[String], nil)
  • parser_contract: (ParserContract)


214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/ibex/ir/grammar_ir.rb', line 214

def initialize_current(class_name:, superclass:, start:, expect:, options:, symbols:, productions:, user_code:,
                       conversions:, warnings:, user_code_chunks:, source_provenance:, expect_rr:,
                       parser_parameters:, value_printers:, grammar_tests:, recovery:, lexer:, mode:, starts:,
                       parser_contract:)
  validate_mode(mode)
  normalized_starts = validate_starts(start, starts, mode)
  (parser_contract)

  @class_name = class_name.freeze
  @superclass = superclass&.freeze
  @start = start.freeze
  @starts = normalized_starts.map(&:freeze).freeze
  @mode = mode
  @expect = expect
  @expect_rr = expect_rr
  @parser_parameters = IR.deep_freeze(parser_parameters)
  @value_printers = IR.deep_freeze(value_printers)
  @grammar_tests = IR.deep_freeze(grammar_tests)
  @lexer = lexer
  @recovery = IR.deep_freeze(recovery || { sync_tokens: [], on_error_reduce: [] })
  @options = IR.deep_freeze(options)
  @symbols = symbols.freeze
  @productions = productions.freeze
  @user_code = IR.deep_freeze(user_code)
  @user_code_chunks = IR.deep_freeze(user_code_chunks || {})
  validate_user_code_chunks
  @conversions = IR.deep_freeze(conversions)
  @warnings = IR.deep_freeze(warnings)
  @schema_version = SCHEMA_VERSION
  @source_provenance = IR.deep_freeze(source_provenance)
  @parser_contract = IR.deep_freeze(parser_contract)
  @symbols_by_name = @symbols.to_h { |symbol| [symbol.name, symbol] }.freeze
  @symbols_by_id = @symbols.to_h { |symbol| [symbol.id, symbol] }.freeze
  freeze
end

#nonterminalsArray[GrammarSymbol]

RBS:

  • () -> Array[GrammarSymbol]

Returns:



259
# File 'lib/ibex/ir/grammar_ir.rb', line 259

def nonterminals = @symbols.select(&:nonterminal?)

#symbol(name) ⇒ GrammarSymbol?

RBS:

  • (String name) -> GrammarSymbol?

Parameters:

  • name (String)

Returns:



253
254
# File 'lib/ibex/ir/grammar_ir.rb', line 253

def symbol(name) = @symbols_by_name[name]
# @rbs (Integer? id) -> GrammarSymbol?

#symbol_by_id(id) ⇒ GrammarSymbol?

RBS:

  • (Integer? id) -> GrammarSymbol?

Parameters:

  • id (Integer, nil)

Returns:



255
256
# File 'lib/ibex/ir/grammar_ir.rb', line 255

def symbol_by_id(id) = @symbols_by_id[id]
# @rbs () -> Array[GrammarSymbol]

#terminalsArray[GrammarSymbol]

RBS:

  • () -> Array[GrammarSymbol]

Returns:



257
258
# File 'lib/ibex/ir/grammar_ir.rb', line 257

def terminals = @symbols.select(&:terminal?)
# @rbs () -> Array[GrammarSymbol]

#to_hHash[Symbol, Object?]

RBS:

  • () -> Hash[Symbol, Object?]

Returns:

  • (Hash[Symbol, Object?])


262
263
264
265
266
267
268
269
270
271
# File 'lib/ibex/ir/grammar_ir.rb', line 262

def to_h
  value = { ibex_ir: "grammar", schema_version: @schema_version, class_name: @class_name, superclass: @superclass,
            start: @start, expect: @expect, options: @options,
            symbols: @symbols.map(&:to_h),
            productions: @productions.map(&:to_h),
            user_code: @user_code, conversions: @conversions,
            warnings: @warnings } #: Hash[Symbol, Object?]
  (value)
  value
end

#validate_current_metadata(parser_contract) ⇒ void

This method returns an undefined value.

RBS:

  • (ParserContract parser_contract) -> void

Parameters:



329
330
331
332
333
# File 'lib/ibex/ir/grammar_ir.rb', line 329

def (parser_contract)
  return if parser_contract.is_a?(ParserContract)

  raise ArgumentError, "parser_contract must be a ParserContract"
end

#validate_mode(mode) ⇒ void

This method returns an undefined value.

RBS:

  • (grammar_mode mode) -> void

Parameters:

  • mode (grammar_mode)


276
277
278
# File 'lib/ibex/ir/grammar_ir.rb', line 276

def validate_mode(mode)
  raise ArgumentError, "mode must be :default or :extended" unless %i[default extended].include?(mode)
end

#validate_starts(start, starts, mode) ⇒ Array[String]

RBS:

  • (String start, Array[String]? starts, grammar_mode mode) -> Array[String]

Parameters:

  • start (String)
  • starts (Array[String], nil)
  • mode (grammar_mode)

Returns:

  • (Array[String])


281
282
283
284
285
286
287
288
289
# File 'lib/ibex/ir/grammar_ir.rb', line 281

def validate_starts(start, starts, mode)
  values = starts || [start]
  raise ArgumentError, "starts must contain the primary start symbol" if values.empty?
  raise ArgumentError, "start must be the first entry in starts" unless values.first == start
  raise ArgumentError, "starts must be unique" unless values.uniq.length == values.length
  raise ArgumentError, "multiple start symbols require extended mode" if values.length > 1 && mode != :extended

  values
end

#validate_user_code_chunksvoid

This method returns an undefined value.

RBS:

  • () -> void



320
321
322
323
324
325
326
# File 'lib/ibex/ir/grammar_ir.rb', line 320

def validate_user_code_chunks
  @user_code_chunks.each do |name, chunks|
    next if chunks.map(&:code).join == @user_code.fetch(name, "")

    raise Ibex::Error, "(ir):1:1: user-code chunks do not match the concatenated #{name} section"
  end
end