Module: Ibex::Codegen::RubyLexer

Included in:
Ruby
Defined in:
lib/ibex/codegen/ruby_lexer.rb,
sig/ibex/codegen/ruby_lexer.rbs

Overview

Generated lexer tables and action methods.

Instance Method Summary collapse

Instance Method Details

#append_lexer(lines) ⇒ void

This method returns an undefined value.

RBS:

  • (Array[String] lines) -> void

Parameters:

  • lines (Array[String])


11
12
13
14
15
16
17
18
19
20
# File 'lib/ibex/codegen/ruby_lexer.rb', line 11

def append_lexer(lines)
  # @type self: Ruby
  lexer = @grammar.lexer
  return unless lexer

  lines << "  include Ibex::Runtime::GeneratedLexer"
  lines << "  LEXER_STATES = #{lexer.states.inspect}.freeze"
  append_lexer_rules(lines, lexer)
  append_lexer_actions(lines, lexer)
end

#append_lexer_actions(lines, lexer) ⇒ void

This method returns an undefined value.

RBS:

  • (Array[String] lines, IR::Lexer lexer) -> void

Parameters:



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/ibex/codegen/ruby_lexer.rb', line 50

def append_lexer_actions(lines, lexer)
  # @type self: Ruby
  lexer.rules.each do |rule|
    next unless rule.action

    source = lexer_action_source(rule)
    if @line_convert
      location = rule.location
      lines << "  class_eval(#{source.dump}, #{location[:file].inspect}, #{location[:line]})"
    else
      source.lines.each { |line| lines << "  #{line.rstrip}" }
    end
    lines << ""
  end
end

#append_lexer_rules(lines, lexer) ⇒ void

This method returns an undefined value.

RBS:

  • (Array[String] lines, IR::Lexer lexer) -> void

Parameters:



23
24
25
26
27
28
29
30
31
32
# File 'lib/ibex/codegen/ruby_lexer.rb', line 23

def append_lexer_rules(lines, lexer)
  # @type self: Ruby
  by_state = lexer.states.to_h do |state|
    rules = lexer.rules.select { |rule| rule.state == state }.map { |rule| lexer_rule_literal(rule) }
    [state.to_sym, "[#{rules.join(', ')}].freeze"]
  end
  source = by_state.map { |state, rules| "#{state.inspect} => #{rules}" }.join(", ")
  lines << "  LEXER_RULES_BY_STATE = { #{source} }.freeze"
  lines << ""
end

#lexer_action_source(rule) ⇒ String

RBS:

  • (IR::LexerRule rule) -> String

Parameters:

Returns:

  • (String)


67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/ibex/codegen/ruby_lexer.rb', line 67

def lexer_action_source(rule)
  action = rule.action || ""
  binding = nil #: String?
  if (match = action.match(/\A\s*\|([a-z_][a-zA-Z0-9_]*)\|\s*(.*)\z/m))
    parameter = match[1] || "s"
    binding = "#{parameter} = _ibex_lexeme"
    action = match[2] || ""
  end
  lines = ["private def _ibex_lexer_action_#{rule.id}(_ibex_lexeme)"]
  lines << "  #{binding}" if binding
  lines << "  #{action}"
  lines << "end"
  "#{lines.join("\n")}\n"
end

#lexer_rule_literal(rule) ⇒ String

RBS:

  • (IR::LexerRule rule) -> String

Parameters:

Returns:

  • (String)


35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/ibex/codegen/ruby_lexer.rb', line 35

def lexer_rule_literal(rule)
  # @type self: Ruby
  flags = 0
  flags |= Regexp::IGNORECASE if rule.options.include?("i")
  flags |= Regexp::MULTILINE if rule.options.include?("m")
  flags |= Regexp::EXTENDED if rule.options.include?("x")
  action = rule.action ? ":_ibex_lexer_action_#{rule.id}" : "nil"
  terminal = rule.token && @grammar.symbol(rule.token)
  token = terminal ? external_token_expression(terminal) : "nil"
  regexp = "Regexp.new(#{"\\A(?:#{rule.pattern})".dump}, #{flags}).freeze"
  "{ id: #{rule.id}, kind: #{rule.kind.inspect}, token: #{token}, " \
    "regexp: #{regexp}, action: #{action} }.freeze"
end