Class: Ibex::Runtime::LexerInput

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

Overview

Incremental String, IO, or Fiber input used by generated lexers.

Constant Summary collapse

DEFAULT_CHUNK_SIZE =

Signature:

  • Integer

Returns:

  • (Integer)
16 * 1024

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source, chunk_size: DEFAULT_CHUNK_SIZE) ⇒ LexerInput

Returns a new instance of LexerInput.

RBS:

  • (String | IO | Fiber source, ?chunk_size: Integer) -> void

Parameters:

  • source (String, IO, Fiber)
  • chunk_size: (Integer) (defaults to: DEFAULT_CHUNK_SIZE)


13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/ibex/runtime/lexer_input.rb', line 13

def initialize(source, chunk_size: DEFAULT_CHUNK_SIZE)
  raise ArgumentError, "lexer chunk_size must be positive" unless chunk_size.positive?
  unless source.is_a?(String) || source.respond_to?(:read) || source.is_a?(Fiber)
    raise ArgumentError, "lexer input must be a String, IO, or Fiber"
  end

  @source = source
  @chunk_size = chunk_size
  @buffer = +""
  @archive = +""
  @eof = false
  return unless source.is_a?(String)

  append(source)
  @eof = true
end

Instance Attribute Details

#bufferString (readonly)

Signature:

  • String

Returns:

  • (String)


10
11
12
# File 'lib/ibex/runtime/lexer_input.rb', line 10

def buffer
  @buffer
end

Instance Method Details

#append(chunk) ⇒ void

This method returns an undefined value.

RBS:

  • (String chunk) -> void

Parameters:

  • chunk (String)


101
102
103
104
# File 'lib/ibex/runtime/lexer_input.rb', line 101

def append(chunk)
  @buffer << chunk
  @archive << chunk
end

#consume(prefix) ⇒ void

This method returns an undefined value.

RBS:

  • (String prefix) -> void

Parameters:

  • prefix (String)


46
47
48
49
50
# File 'lib/ibex/runtime/lexer_input.rb', line 46

def consume(prefix)
  raise ArgumentError, "lexer input prefix does not match the buffer" unless @buffer.start_with?(prefix)

  @buffer.slice!(0, prefix.length)
end

#eof?Boolean

RBS:

  • () -> bool

Returns:

  • (Boolean)


31
# File 'lib/ibex/runtime/lexer_input.rb', line 31

def eof? = @eof

#read_chunkvoid

This method returns an undefined value.

RBS:

  • () -> void



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/ibex/runtime/lexer_input.rb', line 64

def read_chunk
  source = @source
  chunk = if source.is_a?(Fiber)
            resume_fiber(source)
          elsif source.respond_to?(:read)
            source.read(@chunk_size)
          end
  if chunk.nil? || chunk == ""
    @eof = true
    return
  end
  raise TypeError, "lexer input chunks must be Strings" unless chunk.is_a?(String)

  text = chunk #: String
  append(text)
end

#read_more?Boolean

Read until at least one byte is added or EOF is observed.

RBS:

  • () -> bool

Returns:

  • (Boolean)


39
40
41
42
43
# File 'lib/ibex/runtime/lexer_input.rb', line 39

def read_more?
  before = @buffer.bytesize
  read_chunk until @eof || @buffer.bytesize > before
  @buffer.bytesize > before
end

#resume_fiber(source) ⇒ Object

RBS:

  • (Fiber source) -> untyped

Parameters:

  • source (Fiber)

Returns:

  • (Object)


82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/ibex/runtime/lexer_input.rb', line 82

def resume_fiber(source)
  supports_alive = source.respond_to?(:alive?)
  if supports_alive && !source.alive?
    @eof = true
    return
  end

  value = source.resume
  @eof = true if supports_alive && !source.alive?
  value
rescue FiberError => e
  terminated = /\A(?:dead fiber called|attempt to resume a terminated fiber)\z/.match?(e.message)
  raise unless !supports_alive && terminated

  @eof = true
  nil
end

#source_bytesString

Return every source byte read so far, including the unconsumed buffer.

RBS:

  • () -> String

Returns:

  • (String)


35
# File 'lib/ibex/runtime/lexer_input.rb', line 35

def source_bytes = @archive.dup

#source_line(line) ⇒ String

Return one source line, reading ahead only to its line boundary.

RBS:

  • (Integer line) -> String

Parameters:

  • line (Integer)

Returns:

  • (String)


54
55
56
57
58
59
# File 'lib/ibex/runtime/lexer_input.rb', line 54

def source_line(line)
  raise ArgumentError, "source line must be positive" unless line.positive?

  read_more? while !@eof && @archive.count("\n") < line
  (@archive.lines[line - 1] || "").delete_suffix("\n").delete_suffix("\r")
end