parser: display colored lines with error messages
[nit.git] / src / location.nit
index 085e980..0603050 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# This module is used to model Nit source-file and locations in source-file
 package location
 
+# A raw text Nit source file
+class SourceFile
+       # The path of the source
+       var filename: String
+
+       # The content of the source
+       var string: String
+
+       # Create a new sourcefile using a filename and a stream
+       init(filename: String, stream: IStream)
+       do
+               self.filename = filename
+               string = stream.read_all
+               line_starts[0] = 0
+       end
+
+       # Position of each line start
+       var line_starts: Array[Int] = new Array[Int]
+end
+
+# A location inside a source file
 class Location
-special Comparable
+       super Comparable
        redef type OTHER: Location
 
-       readable var _file: String
+       readable var _file: nullable SourceFile
        readable var _line_start: Int
        readable var _line_end: Int
        readable var _column_start: Int
        readable var _column_end: Int
 
-       init(f: String, line_s: Int, line_e: Int, column_s: Int, column_e: Int) do
+       init(f: nullable SourceFile, line_s: Int, line_e: Int, column_s: Int, column_e: Int) do
                _file = f
                _line_start = line_s
                _line_end = line_e
@@ -34,7 +56,7 @@ special Comparable
                _column_end = column_e
        end
 
-       init with_file(f: String) do init(f,0,0,0,0)
+       init with_file(f: SourceFile) do init(f,0,0,0,0)
 
        redef fun ==(other: nullable Object): Bool do
                if other == null then return false
@@ -68,15 +90,31 @@ special Comparable
        end
 
        redef fun to_s: String do
+               var file_part = ""
+               if file != null then
+                       file_part = file.filename
+                       if file.filename.length > 0 then file_part += ":"
+               end
+
                if line_start == line_end then
                        if column_start == column_end then
-                               return "{file}:{line_start},{column_start}"
+                               return "{file_part}{line_start},{column_start}"
                        else
-                               return "{file}:{line_start},{column_start}--{column_end}"
+                               return "{file_part}{line_start},{column_start}--{column_end}"
                        end
                else
-                       return "{file}:{line_start},{column_start}--{line_end}:{column_end}"
+                       return "{file_part}{line_start},{column_start}--{line_end},{column_end}"
+               end
+       end
+
+       fun relative_to(loc: nullable Location): String do
+               var relative: Location
+               if loc != null and loc.file == self.file then
+                       relative = new Location(null, self.line_start, self.line_end, self.column_start, self.column_end)
+               else
+                       relative = new Location(self.file, self.line_start, self.line_end, self.column_start, self.column_end)
                end
+               return relative.to_s
        end
 
        redef fun <(other: OTHER): Bool do