Permalink
Browse files

+ Slices return also line and column

They now include a reference to their source, so that line and column
information can be extracted from there.

many effects
but one source
confounded
  • Loading branch information...
1 parent f05e00b commit 8a6d64cbfb245092e1935d4118ed764b0debee2f @kschiess committed Mar 1, 2011
Showing with 51 additions and 11 deletions.
  1. +16 −4 lib/parslet/slice.rb
  2. +1 −1 lib/parslet/source.rb
  3. +34 −6 spec/parslet/slice_spec.rb
View
@@ -16,9 +16,11 @@
class Parslet::Slice
attr_reader :str, :offset
attr_reader :parent
+ attr_reader :source
- def initialize(string, offset, parent=nil)
+ def initialize(string, offset, source=nil, parent=nil)
@str, @offset = string, offset
+ @source = source
@parent = parent
end
@@ -44,7 +46,7 @@ def slice(start, length)
if parent
parent.slice(offset - parent.offset, length)
else
- Parslet::Slice.new(str.slice(start, length), offset+start, self)
+ self.class.new(str.slice(start, length), offset+start, source, self)
end
end
def abs_slice(start, length)
@@ -67,7 +69,7 @@ def +(other)
unless other.respond_to?(:to_slice)
raise Parslet::InvalidSliceOperation,
- "Cannot concat slices that aren't adjacent."+
+ "Cannot join slices that aren't adjacent."+
" (#{self.inspect} + #{other.inspect})" \
if offset+size != other.offset
@@ -78,8 +80,18 @@ def +(other)
return parent.abs_slice(offset, size+other.size)
end
- self.class.new(str + other.str, offset)
+ self.class.new(str + other.str, offset, source)
end
+
+ # Returns a <line, column> tuple referring to the original input.
+ #
+ def line_and_column
+ raise ArgumentError, "No source was given, cannot infer line and column." \
+ unless source
+
+ source.line_and_column(self.offset)
+ end
+
# Conversion operators -----------------------------------------------------
def to_str
View
@@ -95,7 +95,7 @@ def read_slice(needed)
# cache line ends
@line_cache.scan_for_line_endings(start, buf)
- slice = Parslet::Slice.new(buf || '', start)
+ slice = Parslet::Slice.new(buf || '', start, self)
# Don't cache empty slices.
return slice unless buf
View
@@ -43,16 +43,43 @@
it "should return the associated offset" do
slice.offset.should == 40
end
+ it "should fail to return a line and column" do
+ lambda {
+ slice.line_and_column
+ }.should raise_error(ArgumentError)
+ end
+
+ context "when constructed with a source" do
+ before(:each) {
+ flexmock(slice, :source => flexmock(:source).
+ tap { |sm| sm.
+ should_receive(:line_and_column).
+ with(40).
+ and_return([13, 14]) })
+ }
+ it "should return proper line and column" do
+ slice.line_and_column.should == [13, 14]
+ end
+ end
end
describe "slices" do
describe "<- #slice(start, length)" do
- it "should reslice its parent if available" do
- small = slice.slice(1,3)
- small.should == 'oob'
- small.parent.should == slice
+ context "when a common parent is available" do
+ before(:each) {
+ flexmock(slice, :source => :correct_parent)
+ }
+ let(:small) { slice.slice(1,3) }
+
+ it "should copy the parents source" do
+ small.source.should == :correct_parent
+ end
+ it "should reslice its parent if available" do
+ small.should == 'oob'
+ small.parent.should == slice
- flexmock(small.parent).should_receive(:slice).with(1,1).once
- small.slice(0,1)
+ flexmock(small.parent).should_receive(:slice).with(1,1).once
+ small.slice(0,1)
+ end
end
it "should return slices that have a correct offset" do
as = slice.slice(4,1)
@@ -93,6 +120,7 @@
it { should == 6 }
end
describe "<- #+(other)" do
+ it "should check that sources are compatible"
it "should return a slice that represents the extended range" do
other = described_class.new('foobar', 46)
(slice + other).should eq(described_class.new('foobarfoobar', 40))

0 comments on commit 8a6d64c

Please sign in to comment.