Class: Ibex::Frontend::GeneratedParserBase

Inherits:
Runtime::Parser
  • Object
show all
Includes:
GeneratedParserIncludes, GeneratedParserMetadata, GeneratedParserParameters, ParserConfigurationSupport
Defined in:
lib/ibex/frontend/generated_parser_base.rb,
sig/ibex/frontend/generated_parser_base.rbs

Overview

Semantic support and token delivery for the generated grammar parser. rubocop:disable Metrics/ClassLength -- generated grammar semantics share one parser support surface.

Direct Known Subclasses

GeneratedParser

Constant Summary

Constants included from ParserConfigurationSupport

ParserConfigurationSupport::PARSER_SETTING_VALUES

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ParserConfigurationSupport

#build_parser_configuration, #build_parser_setting, #validate_root_parser_configuration

Methods included from GeneratedParserParameters

#build_parameterized_reference, #build_rule, #build_rule_parameters, #require_adjacency!

Methods included from GeneratedParserIncludes

#build_fragment, #build_include, #fragment_root_declaration_name, #reject_fragment_root_declarations

Methods included from GeneratedParserMetadata

#build_display_name, #build_semantic_type, #build_symbol_metadata, #decode_metadata_value

Constructor Details

#initialize(tokens, mode: :default) ⇒ GeneratedParserBase

Returns a new instance of GeneratedParserBase.

RBS:

  • (Array[Token] tokens, ?mode: Symbol) -> void

Parameters:

  • tokens (Array[Token])
  • mode: (Symbol) (defaults to: :default)


24
25
26
27
28
29
30
# File 'lib/ibex/frontend/generated_parser_base.rb', line 24

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

  super()
  @adapter = TokenAdapter.new(tokens, extended: mode == :extended)
  @mode = mode
end

Instance Attribute Details

#diagnostic_tokenToken? (readonly)

Signature:

  • Token?

Returns:



18
19
20
# File 'lib/ibex/frontend/generated_parser_base.rb', line 18

def diagnostic_token
  @diagnostic_token
end

Instance Method Details

#append_user_code(blocks, token) ⇒ AST::user_code

RBS:

  • (AST::user_code blocks, Token token) -> AST::user_code

Parameters:

  • blocks (AST::user_code)
  • token (Token)

Returns:

  • (AST::user_code)


355
356
357
358
359
# File 'lib/ibex/frontend/generated_parser_base.rb', line 355

def append_user_code(blocks, token)
  value = token_user_code(token)
  blocks[value[:name]] << AST::UserCode.new(name: value[:name], code: value[:code], loc: token.location)
  blocks
end

#apply_suffixes(item, suffixes) ⇒ AST::item

RBS:

  • (AST::item item, Array[Token] suffixes) -> AST::item

Parameters:

  • item (AST::item)
  • suffixes (Array[Token])

Returns:

  • (AST::item)


342
343
344
345
346
347
348
349
350
351
352
# File 'lib/ibex/frontend/generated_parser_base.rb', line 342

def apply_suffixes(item, suffixes)
  suffixes.reduce(item) do |wrapped, suffix|
    extended_only!(suffix.location, "EBNF suffixes")
    case token_string(suffix)
    when "?" then AST::Optional.new(item: wrapped, loc: suffix.location)
    when "*" then AST::Star.new(item: wrapped, loc: suffix.location)
    when "+" then AST::Plus.new(item: wrapped, loc: suffix.location)
    else raise Ibex::Error, "#{suffix.location}: unknown EBNF suffix #{suffix.value.inspect}"
    end
  end
end

#build_action(token) ⇒ AST::InlineAction

RBS:

  • (Token token) -> AST::InlineAction

Parameters:

Returns:



324
325
326
# File 'lib/ibex/frontend/generated_parser_base.rb', line 324

def build_action(token)
  AST::InlineAction.new(code: token_string(token), loc: token.location)
end

#build_alternative(items, precedence, node_annotation) ⇒ AST::Alternative

RBS:

  • (Array[AST::item] items, Token? precedence, AST::NodeAnnotation? node_annotation) -> AST::Alternative

Parameters:

Returns:



264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/ibex/frontend/generated_parser_base.rb', line 264

def build_alternative(items, precedence, node_annotation)
  last_token = @adapter.last_token
  location = item_start_location(items.first) || precedence&.location || last_token&.location
  raise Ibex::Error, "missing alternative location" unless location

  action = nil #: AST::InlineAction?
  last_item = items.last
  if last_item.is_a?(AST::InlineAction)
    items.pop
    action = last_item
  end
  AST::Alternative.new(
    items: items, action: action, precedence: precedence && token_string(precedence),
    node_annotation: node_annotation, loc: location
  )
end

#build_conversion(name_token, literal_token) ⇒ AST::Conversion

RBS:

  • (Token name_token, Token literal_token) -> AST::Conversion

Parameters:

Returns:



247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/ibex/frontend/generated_parser_base.rb', line 247

def build_conversion(name_token, literal_token)
  unless name_token.location.line == literal_token.location.line
    fail_at(name_token.location, "expected a quoted Ruby conversion expression")
  end

  literal = token_string(literal_token)
  expression = if literal.start_with?('"')
                 literal.undump
               else
                 (literal[1...-1] || "").gsub("\\'", "'").gsub("\\\\", "\\")
               end
  AST::Conversion.new(name: token_string(name_token), expression: expression, loc: name_token.location)
rescue RuntimeError => e
  fail_at(name_token.location, "invalid conversion expression: #{e.message}")
end

#build_convert(keyword, pairs) ⇒ AST::Convert

RBS:

  • (Token keyword, Array[AST::Conversion] pairs) -> AST::Convert

Parameters:

Returns:



242
243
244
# File 'lib/ibex/frontend/generated_parser_base.rb', line 242

def build_convert(keyword, pairs)
  AST::Convert.new(pairs: pairs, loc: keyword.location)
end

#build_empty(token) ⇒ AST::Empty

RBS:

  • (Token token) -> AST::Empty

Parameters:

Returns:



290
291
292
293
# File 'lib/ibex/frontend/generated_parser_base.rb', line 290

def build_empty(token)
  extended_only!(token.location, "%empty")
  AST::Empty.new(loc: token.location)
end

#build_expect(keyword, integer) ⇒ AST::Expect

RBS:

  • (Token keyword, Token integer) -> AST::Expect

Parameters:

Returns:



158
159
160
# File 'lib/ibex/frontend/generated_parser_base.rb', line 158

def build_expect(keyword, integer)
  AST::Expect.new(conflicts: token_integer(integer), loc: keyword.location)
end

#build_expect_rr(keyword, integer) ⇒ AST::ExpectRR

RBS:

  • (Token keyword, Token integer) -> AST::ExpectRR

Parameters:

Returns:



163
164
165
166
# File 'lib/ibex/frontend/generated_parser_base.rb', line 163

def build_expect_rr(keyword, integer)
  extended_only!(keyword.location, "expect-rr declarations")
  AST::ExpectRR.new(conflicts: token_integer(integer), loc: keyword.location)
end

#build_grammar_test(keyword, expectation, source) ⇒ AST::GrammarTest

RBS:

  • (Token keyword, Token expectation, Token source) -> AST::GrammarTest

Parameters:

Returns:



208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/ibex/frontend/generated_parser_base.rb', line 208

def build_grammar_test(keyword, expectation, source)
  extended_only!(keyword.location, "%test")
  expected = token_string(expectation)
  fail_at(expectation.location, "expected accept or reject, got #{expected}") unless
    %w[accept reject].include?(expected)
  literal = token_string(source)
  fail_at(source.location, "%test source must use a double-quoted string") unless literal.start_with?('"')

  AST::GrammarTest.new(expectation: expected.to_sym, source: literal.undump, loc: keyword.location)
rescue RuntimeError => e
  fail_at(source.location, "invalid %test source: #{e.message}")
end

#build_group(opening, alternatives, suffixes) ⇒ AST::item

RBS:

  • (Token opening, Array[Array[AST::item]] alternatives, Array[Token] suffixes) -> AST::item

Parameters:

  • opening (Token)
  • alternatives (Array[Array[AST::item]])
  • suffixes (Array[Token])

Returns:

  • (AST::item)


329
330
331
332
# File 'lib/ibex/frontend/generated_parser_base.rb', line 329

def build_group(opening, alternatives, suffixes)
  extended_only!(opening.location, "EBNF groups")
  apply_suffixes(AST::Group.new(alternatives: alternatives, loc: opening.location), suffixes)
end

#build_lexer(keyword, entries) ⇒ AST::Lexer

RBS:

  • (Token keyword, Array[AST::lexer_entry] entries) -> AST::Lexer

Parameters:

  • keyword (Token)
  • entries (Array[AST::lexer_entry])

Returns:



222
223
224
225
# File 'lib/ibex/frontend/generated_parser_base.rb', line 222

def build_lexer(keyword, entries)
  extended_only!(keyword.location, "lexer declarations")
  AST::Lexer.new(definitions: entries, loc: keyword.location)
end

#build_lexer_rule(kind, name, pattern, action, marker) ⇒ AST::LexerRule

RBS:

  • (Symbol kind, Token? name, Token pattern, Token? action, Token marker) -> AST::LexerRule

Parameters:

Returns:



228
229
230
231
232
233
234
# File 'lib/ibex/frontend/generated_parser_base.rb', line 228

def build_lexer_rule(kind, name, pattern, action, marker)
  fail_at(marker.location, "on lexer rules require an action") if kind == :on && !action
  AST::LexerRule.new(
    kind: kind, token: name && token_string(name), pattern: token_string(pattern),
    pattern_kind: pattern.type, action: action && token_string(action), loc: marker.location
  )
end

#build_lexer_state(marker, name, entries) ⇒ AST::LexerState

RBS:

  • (Token marker, Token name, Array[AST::lexer_entry] entries) -> AST::LexerState

Parameters:

  • marker (Token)
  • name (Token)
  • entries (Array[AST::lexer_entry])

Returns:



237
238
239
# File 'lib/ibex/frontend/generated_parser_base.rb', line 237

def build_lexer_state(marker, name, entries)
  AST::LexerState.new(name: token_string(name), definitions: entries, loc: marker.location)
end

#build_node_annotation(marker, name, fields) ⇒ AST::NodeAnnotation

RBS:

  • (Token marker, Token name, Array[Token] fields) -> AST::NodeAnnotation

Parameters:

Returns:



282
283
284
285
286
287
# File 'lib/ibex/frontend/generated_parser_base.rb', line 282

def build_node_annotation(marker, name, fields)
  extended_only!(marker.location, "@node")
  AST::NodeAnnotation.new(
    name: token_string(name), fields: fields.map { |field| token_string(field) }, loc: marker.location
  )
end

#build_on_error_reduce(keyword, names) ⇒ AST::OnErrorReduce

RBS:

  • (Token keyword, Array[String] names) -> AST::OnErrorReduce

Parameters:

  • keyword (Token)
  • names (Array[String])

Returns:



201
202
203
204
205
# File 'lib/ibex/frontend/generated_parser_base.rb', line 201

def build_on_error_reduce(keyword, names)
  extended_only!(keyword.location, "%on_error_reduce")
  fail_at(keyword.location, "%on_error_reduce requires at least one nonterminal") if names.empty?
  AST::OnErrorReduce.new(names: names, loc: keyword.location)
end

#build_options(keyword, names) ⇒ AST::Options

RBS:

  • (Token keyword, Array[String] names) -> AST::Options

Parameters:

  • keyword (Token)
  • names (Array[String])

Returns:



153
154
155
# File 'lib/ibex/frontend/generated_parser_base.rb', line 153

def build_options(keyword, names)
  AST::Options.new(names: names, loc: keyword.location)
end

#build_parameter(keyword, name, type) ⇒ AST::Parameter

RBS:

  • (Token keyword, Token name, Token? type) -> AST::Parameter

Parameters:

Returns:



169
170
171
172
173
174
175
176
177
# File 'lib/ibex/frontend/generated_parser_base.rb', line 169

def build_parameter(keyword, name, type)
  extended_only!(keyword.location, "%param")
  if type && (keyword.location.line != name.location.line || name.location.line != type.location.line)
    fail_at(keyword.location, "%param declaration must be written on one line")
  end

  semantic_type = type && (type, "%param")
  AST::Parameter.new(name: token_string(name), semantic_type: semantic_type, loc: keyword.location)
end

#build_precedence(keyword, direction, levels) ⇒ AST::Precedence

RBS:

  • (Token keyword, Symbol direction, Array[AST::PrecedenceLevel] levels) -> AST::Precedence

Parameters:

Returns:



139
140
141
# File 'lib/ibex/frontend/generated_parser_base.rb', line 139

def build_precedence(keyword, direction, levels)
  AST::Precedence.new(direction: direction, levels: levels, loc: keyword.location)
end

#build_precedence_level(association, symbols) ⇒ AST::PrecedenceLevel

RBS:

  • (Token association, Array[String] symbols) -> AST::PrecedenceLevel

Parameters:

  • association (Token)
  • symbols (Array[String])

Returns:



144
145
146
147
148
149
150
# File 'lib/ibex/frontend/generated_parser_base.rb', line 144

def build_precedence_level(association, symbols)
  fail_at(association.location, "expected at least one precedence symbol") if symbols.empty?
  extended_only!(association.location, "%precedence") if token_string(association) == "precedence"

  AST::PrecedenceLevel.new(associativity: token_string(association).to_sym, symbols: symbols,
                           loc: association.location)
end

#build_printer(keyword, symbol, action) ⇒ AST::Printer

RBS:

  • (Token keyword, Token symbol, Token action) -> AST::Printer

Parameters:

Returns:



180
181
182
183
# File 'lib/ibex/frontend/generated_parser_base.rb', line 180

def build_printer(keyword, symbol, action)
  extended_only!(keyword.location, "%printer")
  AST::Printer.new(name: token_string(symbol), code: token_string(action), loc: keyword.location)
end

#build_recovery(keyword, kind, sync_tokens) ⇒ AST::Recovery

RBS:

  • (Token keyword, Token kind, Array[String] sync_tokens) -> AST::Recovery

Parameters:

  • keyword (Token)
  • kind (Token)
  • sync_tokens (Array[String])

Returns:



193
194
195
196
197
198
# File 'lib/ibex/frontend/generated_parser_base.rb', line 193

def build_recovery(keyword, kind, sync_tokens)
  extended_only!(keyword.location, "%recover")
  fail_at(kind.location, "expected sync, got #{kind.value}") unless token_string(kind) == "sync"
  fail_at(keyword.location, "%recover sync requires at least one token") if sync_tokens.empty?
  AST::Recovery.new(sync_tokens: sync_tokens, loc: keyword.location)
end

#build_root(class_token, class_parts, superclass, declarations, rules, user_code) ⇒ AST::Root

RBS:

  • (Token class_token, Array[String] class_parts, Array[String]? superclass, Array[AST::declaration] declarations, Array[AST::Rule] rules, AST::user_code user_code) -> AST::Root

Parameters:

  • class_token (Token)
  • class_parts (Array[String])
  • superclass (Array[String], nil)
  • declarations (Array[AST::declaration])
  • rules (Array[AST::Rule])
  • user_code (AST::user_code)

Returns:



108
109
110
111
112
113
114
115
# File 'lib/ibex/frontend/generated_parser_base.rb', line 108

def build_root(class_token, class_parts, superclass, declarations, rules, user_code)
  validate_root_parser_configuration(declarations)
  AST::Root.new(class_name: class_parts.join("::"), superclass: superclass&.join("::"),
                declarations: declarations, rules: rules, user_code: user_code, loc: class_token.location,
                extended: @mode == :extended || @adapter.extended_pragma? || @adapter.cst_pragma?,
                cst: @adapter.cst_pragma?,
                extended_loc: @adapter.extended_pragma_location || @adapter.cst_pragma_location)
end

#build_separated_list(function, item, separator) ⇒ AST::SeparatedList

RBS:

  • (Token function, AST::item item, AST::item separator) -> AST::SeparatedList

Parameters:

  • function (Token)
  • item (AST::item)
  • separator (AST::item)

Returns:



335
336
337
338
339
# File 'lib/ibex/frontend/generated_parser_base.rb', line 335

def build_separated_list(function, item, separator)
  extended_only!(function.location, "separated lists")
  AST::SeparatedList.new(item: item, separator: separator,
                         nonempty: function.value == "separated_nonempty_list", loc: function.location)
end

#build_start(keyword, names) ⇒ AST::Start

RBS:

  • (Token keyword, Array[String] names) -> AST::Start

Parameters:

  • keyword (Token)
  • names (Array[String])

Returns:



186
187
188
189
190
# File 'lib/ibex/frontend/generated_parser_base.rb', line 186

def build_start(keyword, names)
  fail_at(keyword.location, "start declaration requires at least one symbol") if names.empty?
  extended_only!(keyword.location, "multiple start symbols") if names.length > 1
  AST::Start.new(names: names, loc: keyword.location)
end

#build_symbol_reference(token, named_reference, suffixes) ⇒ AST::item

RBS:

  • (Token token, [Token, Token]? named_reference, Array[Token] suffixes) -> AST::item

Parameters:

Returns:

  • (AST::item)


307
308
309
310
311
312
# File 'lib/ibex/frontend/generated_parser_base.rb', line 307

def build_symbol_reference(token, named_reference, suffixes)
  item = AST::SymbolReference.new(
    name: token_string(token), named_reference: named_reference_value(named_reference), loc: token.location
  )
  apply_suffixes(item, suffixes)
end

#build_token_alias(name, value) ⇒ [ String, String ]

RBS:

  • (Token name, Token value) -> [String, String]

Parameters:

Returns:

  • ([ String, String ])


129
130
131
132
133
134
135
136
# File 'lib/ibex/frontend/generated_parser_base.rb', line 129

def build_token_alias(name, value)
  extended_only!(name.location, "token aliases")
  unless name.location.line == value.location.line
    fail_at(name.location, "token alias must be written on one line")
  end

  [token_string(name), (value, "token alias")]
end

#build_token_entry(token) ⇒ [ String, nil ]

RBS:

  • (Token token) -> [String, nil]

Parameters:

Returns:

  • ([ String, nil ])


124
125
126
# File 'lib/ibex/frontend/generated_parser_base.rb', line 124

def build_token_entry(token)
  [token_string(token), nil]
end

#build_tokens(keyword, entries) ⇒ AST::Tokens

RBS:

  • (Token keyword, Array[[String, String?]] entries) -> AST::Tokens

Parameters:

  • keyword (Token)
  • entries (Array[[ String, String? ]])

Returns:



118
119
120
121
# File 'lib/ibex/frontend/generated_parser_base.rb', line 118

def build_tokens(keyword, entries)
  aliases = entries.filter_map { |name, value| [name, value] if value }.to_h
  AST::Tokens.new(names: entries.map(&:first), aliases: aliases.empty? ? nil : aliases, loc: keyword.location)
end

#empty_user_codeAST::user_code

RBS:

  • () -> AST::user_code

Returns:

  • (AST::user_code)


369
370
371
# File 'lib/ibex/frontend/generated_parser_base.rb', line 369

def empty_user_code
  Hash.new { |hash, key| hash[key] = [] } #: AST::user_code
end

#expected_description(token) ⇒ String

RBS:

  • (Token? token) -> String

Parameters:

Returns:

  • (String)


88
89
90
91
92
93
94
# File 'lib/ibex/frontend/generated_parser_base.rb', line 88

def expected_description(token)
  expectation = @adapter.expectation(token)
  return expectation if expectation
  return ")" if %i[separated parameter].include?(@adapter.open_delimiter_kind)

  structural_expectation(token)
end

#extended_only!(location, feature) ⇒ void

This method returns an undefined value.

RBS:

  • (Location location, String feature) -> void

Parameters:



374
375
376
377
378
# File 'lib/ibex/frontend/generated_parser_base.rb', line 374

def extended_only!(location, feature)
  return if @mode == :extended || @adapter.extended_pragma? || @adapter.cst_pragma?

  fail_at(location, "#{feature} require extended mode")
end

#fail_at(location, message) ⇒ bot

RBS:

  • (Location location, String message) -> bot

Parameters:

Returns:

  • (bot)


381
382
383
# File 'lib/ibex/frontend/generated_parser_base.rb', line 381

def fail_at(location, message)
  raise Ibex::Error, "#{location}: #{message}"
end

#item_start_location(item) ⇒ Location?

RBS:

  • (AST::item? item) -> Location?

Parameters:

  • item (AST::item, nil)

Returns:



296
297
298
299
300
301
302
303
304
# File 'lib/ibex/frontend/generated_parser_base.rb', line 296

def item_start_location(item)
  return unless item

  if item.is_a?(AST::Optional) || item.is_a?(AST::Star) || item.is_a?(AST::Plus)
    return item_start_location(item.item)
  end

  item.loc
end

#named_reference_value(named_reference) ⇒ String?

RBS:

  • ([Token, Token]? named_reference) -> String?

Parameters:

Returns:

  • (String, nil)


315
316
317
318
319
320
321
# File 'lib/ibex/frontend/generated_parser_base.rb', line 315

def named_reference_value(named_reference)
  return unless named_reference

  colon, name = named_reference
  extended_only!(colon.location, "named references")
  token_string(name)
end

#next_token[ external_token, Token ], false

RBS:

  • () -> ([external_token, Token] | false)

Returns:

  • ([ external_token, Token ], false)


38
39
40
41
42
43
44
45
# File 'lib/ibex/frontend/generated_parser_base.rb', line 38

def next_token
  delivered = @adapter.next_token
  @diagnostic_token = delivered ? delivered.fetch(1) : @adapter.eof_token
  delivered
rescue Ibex::Error
  @diagnostic_token = @adapter.last_token || @adapter.eof_token
  raise
end

#on_error(_token_id, value, _value_stack) ⇒ bot

RBS:

  • (Integer? _token_id, Token? value, Array[Object?] _value_stack) -> bot

Parameters:

  • _token_id (Integer, nil)
  • value (Token, nil)
  • _value_stack (Array[Object?])

Returns:

  • (bot)


48
49
50
51
52
53
54
55
56
57
# File 'lib/ibex/frontend/generated_parser_base.rb', line 48

def on_error(_token_id, value, _value_stack)
  token = value || @adapter.eof_token
  @diagnostic_token = token
  raise_contextual_error(token)

  received = token&.value || token&.type || :eof
  location = token&.location || Location.new(file: "(grammar)", line: 1, column: 1)
  expected = expected_description(token)
  raise Ibex::Error, "#{location}: expected #{expected}, got #{received}"
end

#parseAST::Root, AST::Fragment

RBS:

  • () -> (AST::Root | AST::Fragment)

Returns:



33
34
35
# File 'lib/ibex/frontend/generated_parser_base.rb', line 33

def parse
  do_parse #: AST::Root | AST::Fragment
end

#prepend_user_code(token, blocks) ⇒ AST::user_code

RBS:

  • (Token token, AST::user_code blocks) -> AST::user_code

Parameters:

  • token (Token)
  • blocks (AST::user_code)

Returns:

  • (AST::user_code)


362
363
364
365
366
# File 'lib/ibex/frontend/generated_parser_base.rb', line 362

def prepend_user_code(token, blocks)
  result = append_user_code(empty_user_code, token)
  blocks.each { |name, chunks| result[name].concat(chunks) }
  result
end

#raise_contextual_error(token) ⇒ void

This method returns an undefined value.

RBS:

  • (Token? token) -> void

Parameters:



62
63
64
65
# File 'lib/ibex/frontend/generated_parser_base.rb', line 62

def raise_contextual_error(token)
  raise_group_contextual_error(token)
  raise_conversion_contextual_error
end

#raise_conversion_contextual_errorvoid

This method returns an undefined value.

RBS:

  • () -> void



79
80
81
82
83
84
85
# File 'lib/ibex/frontend/generated_parser_base.rb', line 79

def raise_conversion_contextual_error
  conversion_name = @adapter.conversion_name
  return unless @adapter.declaration == :convert
  return unless conversion_name

  fail_at(conversion_name.location, "expected a quoted Ruby conversion expression")
end

#raise_group_contextual_error(token) ⇒ void

This method returns an undefined value.

RBS:

  • (Token? token) -> void

Parameters:



68
69
70
71
72
73
74
75
76
# File 'lib/ibex/frontend/generated_parser_base.rb', line 68

def raise_group_contextual_error(token)
  group_opening = @adapter.group_opening
  if group_opening && token && token.type == :action
    fail_at(token.location, "actions inside EBNF groups are not supported")
  end
  group_unterminated = @adapter.open_delimiter_kind == :group &&
                       (token.nil? || token.type == :eof || token.value == "end")
  fail_at(group_opening.location, "unterminated EBNF group") if group_unterminated && group_opening
end

#structural_expectation(token) ⇒ String

RBS:

  • (Token? token) -> String

Parameters:

Returns:

  • (String)


97
98
99
100
101
102
103
104
# File 'lib/ibex/frontend/generated_parser_base.rb', line 97

def structural_expectation(token)
  return "rule" if @adapter.section == :declarations
  return "at least one rule" if @adapter.section == :user_code && token&.value == "end"
  return "eof" if @adapter.section == :user_code
  return "end" if @adapter.section == :rules && @adapter.eof_token

  "grammar syntax"
end

#token_integer(token) ⇒ Integer

RBS:

  • (Token token) -> Integer

Parameters:

Returns:

  • (Integer)


394
395
396
397
398
399
# File 'lib/ibex/frontend/generated_parser_base.rb', line 394

def token_integer(token)
  value = token.value
  return value if value.is_a?(Integer)

  fail_at(token.location, "expected integer token")
end

#token_string(token) ⇒ String

RBS:

  • (Token token) -> String

Parameters:

Returns:

  • (String)


386
387
388
389
390
391
# File 'lib/ibex/frontend/generated_parser_base.rb', line 386

def token_string(token)
  value = token.value
  return value if value.is_a?(String)

  fail_at(token.location, "expected text token")
end

#token_user_code(token) ⇒ user_code_token

RBS:

  • (Token token) -> user_code_token

Parameters:

Returns:

  • (user_code_token)


402
403
404
405
406
407
# File 'lib/ibex/frontend/generated_parser_base.rb', line 402

def token_user_code(token)
  value = token.value
  return value if value.is_a?(Hash)

  fail_at(token.location, "expected user-code token")
end