errors.Error and errors.Position are in two different files
This commit is contained in:
parent
5f6dbf2baf
commit
0d149d6fd7
@ -1,90 +1,6 @@
|
|||||||
package errors
|
package errors
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
import "strings"
|
|
||||||
|
|
||||||
// Position stores the position of something within a file. For memory's sake,
|
|
||||||
// positions in the same file should be created using the same File string, and
|
|
||||||
// positions on the same line should be created using the same Line string.
|
|
||||||
type Position struct {
|
|
||||||
File string
|
|
||||||
Line string
|
|
||||||
|
|
||||||
Row int
|
|
||||||
Start int
|
|
||||||
End int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pos Position) String () string {
|
|
||||||
return fmt.Sprintf("%s:%d:%d", pos.File, pos.Row + 1, pos.Start + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format produces a formatted printout of where the position is in its file.
|
|
||||||
func (pos Position) Format () string {
|
|
||||||
line := formatTabs(pos.Line)
|
|
||||||
output := fmt.Sprintf("%-4d | %s\n ", pos.Row + 1, line)
|
|
||||||
|
|
||||||
start := pos.Start
|
|
||||||
end := pos.End
|
|
||||||
if end <= start { end = start + 1 }
|
|
||||||
start = getXInTabbedString(pos.Line, start)
|
|
||||||
end = getXInTabbedString(pos.Line, end)
|
|
||||||
|
|
||||||
for index := range line {
|
|
||||||
if index >= end { break }
|
|
||||||
if index >= start{
|
|
||||||
output += "^"
|
|
||||||
} else {
|
|
||||||
output += " "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return output
|
|
||||||
}
|
|
||||||
|
|
||||||
func getXInTabbedString (tabbed string, column int) int {
|
|
||||||
var x int
|
|
||||||
for index, ch := range tabbed {
|
|
||||||
if index >= column { return x }
|
|
||||||
if ch == '\t' {
|
|
||||||
nextStop := ((x / 8) + 1) * 8
|
|
||||||
x = nextStop - 1
|
|
||||||
}
|
|
||||||
x ++
|
|
||||||
}
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func formatTabs (tabbed string) string {
|
|
||||||
var result string
|
|
||||||
var x int
|
|
||||||
for _, ch := range tabbed {
|
|
||||||
if ch == '\t' {
|
|
||||||
nextStop := ((x / 8) + 1) * 8
|
|
||||||
result += strings.Repeat(" ", nextStop - x)
|
|
||||||
x = nextStop - 1
|
|
||||||
} else {
|
|
||||||
result += string(ch)
|
|
||||||
}
|
|
||||||
x ++
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Union attempts to return the union of two positions. Since a position cannot
|
|
||||||
// span multiple lines or files, the resulting position will be on the same line
|
|
||||||
// and in the same file as the method reciever.
|
|
||||||
func (pos Position) Union (other Position) Position {
|
|
||||||
switch {
|
|
||||||
case other.File != pos.File:
|
|
||||||
case other.Row < pos.Row: pos.Start = 0
|
|
||||||
case other.Row > pos.Row: pos.End = len(pos.Line)
|
|
||||||
default:
|
|
||||||
if other.Start < pos.Start { pos.Start = other.Start }
|
|
||||||
if other.End > pos.End { pos.End = other.End }
|
|
||||||
}
|
|
||||||
return pos
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error is an error that contains positional information.
|
// Error is an error that contains positional information.
|
||||||
type Error interface {
|
type Error interface {
|
||||||
|
87
errors/position.go
Normal file
87
errors/position.go
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
package errors
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
// Position stores the position of something within a file. For memory's sake,
|
||||||
|
// positions in the same file should be created using the same File string, and
|
||||||
|
// positions on the same line should be created using the same Line string.
|
||||||
|
type Position struct {
|
||||||
|
File string
|
||||||
|
Line string
|
||||||
|
|
||||||
|
Row int
|
||||||
|
Start int
|
||||||
|
End int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pos Position) String () string {
|
||||||
|
return fmt.Sprintf("%s:%d:%d", pos.File, pos.Row + 1, pos.Start + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format produces a formatted printout of where the position is in its file.
|
||||||
|
func (pos Position) Format () string {
|
||||||
|
line := formatTabs(pos.Line)
|
||||||
|
output := fmt.Sprintf("%-4d | %s\n ", pos.Row + 1, line)
|
||||||
|
|
||||||
|
start := pos.Start
|
||||||
|
end := pos.End
|
||||||
|
if end <= start { end = start + 1 }
|
||||||
|
start = getXInTabbedString(pos.Line, start)
|
||||||
|
end = getXInTabbedString(pos.Line, end)
|
||||||
|
|
||||||
|
for index := range line {
|
||||||
|
if index >= end { break }
|
||||||
|
if index >= start{
|
||||||
|
output += "^"
|
||||||
|
} else {
|
||||||
|
output += " "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
func getXInTabbedString (tabbed string, column int) int {
|
||||||
|
var x int
|
||||||
|
for index, ch := range tabbed {
|
||||||
|
if index >= column { return x }
|
||||||
|
if ch == '\t' {
|
||||||
|
nextStop := ((x / 8) + 1) * 8
|
||||||
|
x = nextStop - 1
|
||||||
|
}
|
||||||
|
x ++
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatTabs (tabbed string) string {
|
||||||
|
var result string
|
||||||
|
var x int
|
||||||
|
for _, ch := range tabbed {
|
||||||
|
if ch == '\t' {
|
||||||
|
nextStop := ((x / 8) + 1) * 8
|
||||||
|
result += strings.Repeat(" ", nextStop - x)
|
||||||
|
x = nextStop - 1
|
||||||
|
} else {
|
||||||
|
result += string(ch)
|
||||||
|
}
|
||||||
|
x ++
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Union attempts to return the union of two positions. Since a position cannot
|
||||||
|
// span multiple lines or files, the resulting position will be on the same line
|
||||||
|
// and in the same file as the method reciever.
|
||||||
|
func (pos Position) Union (other Position) Position {
|
||||||
|
switch {
|
||||||
|
case other.File != pos.File:
|
||||||
|
case other.Row < pos.Row: pos.Start = 0
|
||||||
|
case other.Row > pos.Row: pos.End = len(pos.Line)
|
||||||
|
default:
|
||||||
|
if other.Start < pos.Start { pos.Start = other.Start }
|
||||||
|
if other.End > pos.End { pos.End = other.End }
|
||||||
|
}
|
||||||
|
return pos
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user