Class: Ibex::Frontend::SourceDocument

Inherits:
Object
  • Object
show all
Defined in:
lib/ibex/frontend/source_document.rb

Overview

Lossless grammar source plus its semantic parse and lexical concrete syntax tree.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source:, file:, tokens:, cst:, ast: nil) ⇒ SourceDocument

Returns a new instance of SourceDocument.



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

def initialize(source:, file:, tokens:, cst:, ast: nil)
  @source = SourceEncoding.validated_utf8(source, file)
  @file = file.dup.freeze
  @tokens = tokens.dup.freeze
  @cst = cst
  @ast = ast
  @line_starts = build_line_starts.freeze #: Array[Integer]
  validate_render
  freeze
end

Instance Attribute Details

#astObject (readonly)

: AST::Root | AST::Fragment | nil



102
103
104
# File 'lib/ibex/frontend/source_document.rb', line 102

def ast
  @ast
end

#cstObject (readonly)

: CST::Document



101
102
103
# File 'lib/ibex/frontend/source_document.rb', line 101

def cst
  @cst
end

#fileObject (readonly)

: String



99
100
101
# File 'lib/ibex/frontend/source_document.rb', line 99

def file
  @file
end

#sourceObject (readonly)

: String



98
99
100
# File 'lib/ibex/frontend/source_document.rb', line 98

def source
  @source
end

#tokensObject (readonly)

: Array



100
101
102
# File 'lib/ibex/frontend/source_document.rb', line 100

def tokens
  @tokens
end

Instance Method Details

#byte_offset_at(line, column) ⇒ Object

Raises:

  • (ArgumentError)


141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/ibex/frontend/source_document.rb', line 141

def byte_offset_at(line, column)
  raise ArgumentError, "line and column must be positive" unless line.positive? && column.positive?

  line_start = @line_starts[line - 1]
  raise ArgumentError, "line is outside the source" unless line_start

  line_end = @line_starts[line] || source.bytesize
  line_text = source.byteslice(line_start, line_end - line_start) || ""
  line_text = line_text.delete_suffix("\n")
  character_count = column - 1
  raise ArgumentError, "column is outside the source line" if character_count > line_text.length

  line_start + line_text.each_char.take(character_count).join.bytesize
end

#position_at(byte_offset) ⇒ Object

Raises:

  • (ArgumentError)


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

def position_at(byte_offset)
  validate_byte_offset(byte_offset)
  prefix = source.byteslice(0, byte_offset) || ""
  raise ArgumentError, "byte offset must be on a UTF-8 character boundary" unless prefix.valid_encoding?

  line_index = (@line_starts.bsearch_index { |start| start > byte_offset } || @line_starts.length) - 1
  line_start = @line_starts.fetch(line_index)
  line_prefix = source.byteslice(line_start, byte_offset - line_start) || ""
  SourcePosition.new(byte_offset: byte_offset, line: line_index + 1, column: line_prefix.length + 1)
end

#renderObject



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

def render
  cst.render
end

#slice(span) ⇒ Object



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

def slice(span)
  validate_span(span)
  source.byteslice(span.start_byte, span.length) || ""
end

#span(start_byte, end_byte) ⇒ Object



157
158
159
# File 'lib/ibex/frontend/source_document.rb', line 157

def span(start_byte, end_byte)
  SourceSpan.new(file: file, start: position_at(start_byte), finish: position_at(end_byte))
end

#token_for(segment) ⇒ Object



162
163
164
165
# File 'lib/ibex/frontend/source_document.rb', line 162

def token_for(segment)
  index = segment.token_index
  index && tokens[index]
end

#with_ast(ast) ⇒ Object



168
169
170
# File 'lib/ibex/frontend/source_document.rb', line 168

def with_ast(ast)
  self.class.new(source: source, file: file, tokens: tokens, cst: cst, ast: ast)
end