errors.Error and errors.Position are in two different files

This commit is contained in:
Sasha Koshka 2024-02-08 16:24:46 -05:00
parent 29012110f8
commit d2a4d785f6
2 changed files with 87 additions and 84 deletions

View File

@ -1,90 +1,6 @@
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
}
// Error is an error that contains positional information.
type Error interface {

87
errors/position.go Normal file
View 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
}