Class: Parser::Source::Buffer
- Inherits:
-
Object
- Object
- Parser::Source::Buffer
- Defined in:
- lib/parser/source/buffer.rb
Instance Attribute Summary collapse
-
#first_line ⇒ Object
readonly
Returns the value of attribute first_line.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
Class Method Summary collapse
- .recognize_encoding(string) ⇒ Object
-
.reencode_string(string) ⇒ Object
Lexer expects UTF-8 input.
Instance Method Summary collapse
- #decompose_position(position) ⇒ Object
-
#initialize(name, first_line = 1) ⇒ Buffer
constructor
A new instance of Buffer.
- #line_begins ⇒ Object private
- #line_for(position) ⇒ Object private
- #read ⇒ Object
- #source ⇒ Object
- #source=(source) ⇒ Object
- #source_line(line) ⇒ Object
Constructor Details
#initialize(name, first_line = 1) ⇒ Buffer
Returns a new instance of Buffer.
52 53 54 55 56 57 58 59 |
# File 'lib/parser/source/buffer.rb', line 52 def initialize(name, first_line = 1) @name = name @source = nil @first_line = first_line @lines = nil @line_begins = nil end |
Instance Attribute Details
#first_line ⇒ Object (readonly)
Returns the value of attribute first_line.
7 8 9 |
# File 'lib/parser/source/buffer.rb', line 7 def first_line @first_line end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
7 8 9 |
# File 'lib/parser/source/buffer.rb', line 7 def name @name end |
Class Method Details
.recognize_encoding(string) ⇒ Object
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/parser/source/buffer.rb', line 9 def self.recognize_encoding(string) if string.empty? return Encoding::BINARY end # TODO: Make this more efficient. first_line, second_line = string.lines.first(2) [first_line, second_line].each do |line| line.force_encoding(Encoding::ASCII_8BIT) if line end if first_line =~ /\A\xef\xbb\xbf/ # BOM return Encoding::UTF_8 elsif first_line[0, 2] == '#!' encoding_line = second_line else encoding_line = first_line end if encoding_line =~ /^#.*coding[:=]\s*([a-z0-9_-]+)/ Encoding.find($1) else string.encoding end end |
.reencode_string(string) ⇒ Object
Lexer expects UTF-8 input. This method processes the input in an arbitrary valid Ruby encoding and returns an UTF-8 encoded string.
40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/parser/source/buffer.rb', line 40 def self.reencode_string(string) encoding = recognize_encoding(string) unless encoding.ascii_compatible? raise RuntimeError, "Encoding #{encoding} is not ASCII-compatible" end string. force_encoding(encoding). encode(Encoding::UTF_8) end |
Instance Method Details
#decompose_position(position) ⇒ Object
90 91 92 93 94 |
# File 'lib/parser/source/buffer.rb', line 90 def decompose_position(position) line_no, line_begin = line_for(position) [ @first_line + line_no, position - line_begin ] end |
#line_begins ⇒ Object (private)
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/parser/source/buffer.rb', line 114 def line_begins unless @line_begins @line_begins, index = [ [ 0, 0 ] ], 1 @source.each_char do |char| if char == "\n" @line_begins << [ @line_begins.length, index ] end index += 1 end @line_begins = @line_begins.reverse end @line_begins end |
#line_for(position) ⇒ Object (private)
132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/parser/source/buffer.rb', line 132 def line_for(position) if line_begins.respond_to? :bsearch line_begins.bsearch do |line, line_begin| line_begin <= position end else # Slower variant for <= Ruby 2.0. line_begins.find do |line, line_begin| line_begin <= position end end end |
#read ⇒ Object
61 62 63 64 65 66 67 |
# File 'lib/parser/source/buffer.rb', line 61 def read File.open(@name, 'rb') do |io| self.source = io.read end self end |
#source ⇒ Object
69 70 71 72 73 74 75 |
# File 'lib/parser/source/buffer.rb', line 69 def source if @source.nil? raise RuntimeError, 'Cannot extract source from uninitialized Source::Buffer' end @source end |
#source=(source) ⇒ Object
77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/parser/source/buffer.rb', line 77 def source=(source) if @source raise ArgumentError, "Source::Buffer is immutable" end if source.respond_to? :encoding source = source.dup if source.frozen? source = self.class.reencode_string(source) end @source = source.freeze end |
#source_line(line) ⇒ Object
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/parser/source/buffer.rb', line 96 def source_line(line) unless @lines @lines = @source.lines.map do |source_line| # Line endings will be commonly present for all lines # except the last one. It does not make sense to keep them. if source_line.end_with? "\n" source_line.chomp else source_line end end end @lines[line - @first_line].dup end |