]> git.wincent.com - walrat.git/blob - lib/walrat/location_tracking.rb
Initial import (extraction from Walrus repo, commit 0c9d44c)
[walrat.git] / lib / walrat / location_tracking.rb
1 # Copyright 2007-2010 Wincent Colaiuta. All rights reserved.
2 # Redistribution and use in source and binary forms, with or without
3 # modification, are permitted provided that the following conditions are met:
4 #
5 # 1. Redistributions of source code must retain the above copyright notice,
6 #    this list of conditions and the following disclaimer.
7 # 2. Redistributions in binary form must reproduce the above copyright notice,
8 #    this list of conditions and the following disclaimer in the documentation
9 #    and/or other materials provided with the distribution.
10 #
11 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
12 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
15 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
16 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
17 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
18 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
19 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
20 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
21 # POSSIBILITY OF SUCH DAMAGE.
22
23 require 'walrat'
24
25 module Walrat
26   # Methods for embedding location information in objects returned (or
27   # exceptions raised) from parse methods.
28   module LocationTracking
29     attr_reader :source_text
30
31     # For occasions where a single item must serve as a carrier for array-like
32     # information (that is, its own start, end and source_text, as well as the
33     # "outer" equivalents). This can happen where a single node appears in a
34     # list context surrounded only by skipped content.
35     attr_accessor :outer_start, :outer_end, :outer_source_text
36
37     def source_text=(string)
38       @source_text = string.to_s.clone
39     end
40
41     # Sets @column_start to col.
42     # Sets @column_start to 0 if passed nil (for ease of use, users of classes
43     # that mix-in this module don't have to worry about special casing nil
44     # values).
45     def column_start=(column_start)
46       @column_start = column_start.to_i
47     end
48
49     # Returns 0 if @column_start is nil (for ease of use, users of classes that
50     # mix-in this module don't have to worry about special casing nil values).
51     def column_start
52       @column_start || 0
53     end
54
55     # Sets @line_start to line.
56     # Sets @line_start to 0 if passed nil (for ease of use, users of classes
57     # that mix-in this module don't have to worry about special casing nil
58     # values).
59     def line_start=(line_start)
60       @line_start = line_start.to_i
61     end
62
63     # Returns 0 if @line_start is nil (for ease of use, users of classes that
64     # mix-in this module don't have to worry about special casing nil values).
65     def line_start
66       @line_start || 0
67     end
68
69     # Convenience method for getting both line_start and column_start at once.
70     def start
71       [self.line_start, self.column_start]
72     end
73
74     # Convenience method for setting both line_start and column_start at once.
75     def start=(array)
76       raise ArgumentError if array.nil?
77       raise ArgumentError if array.length != 2
78       self.line_start    = array[0]
79       self.column_start  = array[1]
80     end
81
82     def line_end=(line_end)
83       @line_end = line_end.to_i
84     end
85
86     def line_end
87       @line_end || 0
88     end
89
90     def column_end=(column_end)
91       @column_end = column_end.to_i
92     end
93
94     def column_end
95       @column_end || 0
96     end
97
98     # Convenience method for getting both line_end and column_end at once.
99     def end
100       [self.line_end, self.column_end]
101     end
102
103     # Convenience method for setting both line_end and column_end at once.
104     def end=(array)
105       raise ArgumentError if array.nil?
106       raise ArgumentError if array.length != 2
107       self.line_end   = array[0]
108       self.column_end = array[1]
109     end
110
111     # Given another object that responds to column_end and line_end, returns
112     # true if the receiver is rightmost or equal.
113     # If the other object is farther to the right returns false.
114     def rightmost? other
115       if self.line_end > other.line_end
116         true
117       elsif other.line_end > self.line_end
118         false
119       elsif self.column_end >= other.column_end
120         true
121       else
122         false
123       end
124     end
125   end # module LocationTracking
126 end # module Walrat