package file import "os" import "fmt" type ErrorKind int const ( ErrorKindError ErrorKind = iota ErrorKindWarn ) type Error struct { Location width int message string kind ErrorKind } // NewError creates a new error at the specified location. func NewError ( location Location, width int, message string, kind ErrorKind, ) ( err *Error, ) { return &Error { Location: location, width: width, message: message, kind: kind, } } // Error returns a formatted error message as a string. func (err Error) Error () (formattedMessage string) { switch err.kind { case ErrorKindError: formattedMessage += "ERR" case ErrorKindWarn: formattedMessage += "!!!" } // print information about the location of the mistake if err.width > 0 { formattedMessage += fmt.Sprint ( " ", err.Location.row + 1, ":", err.Location.column + 1) } formattedMessage += " in " + err.Location.file.path + "\n" if err.width > 0 { // print erroneous line formattedMessage += err.Location.file.lines[err.Location.row] + "\n" // print an arrow with a tail spanning the width of the mistake columnCountdown := err.Location.column for columnCountdown > 0 { formattedMessage += " " columnCountdown -- } for err.width > 1 { formattedMessage += "-" } formattedMessage += "-\n" } formattedMessage += err.message + "-\n" return } // Print formats the error and prints it to stderr. func (err Error) Print () { os.Stderr.Write([]byte(err.Error())) }