// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package scanner

import (
	
	
	
	
)

// In an [ErrorList], an error is represented by an *Error.
// The position Pos, if valid, points to the beginning of
// the offending token, and the error condition is described
// by Msg.
type Error struct {
	Pos token.Position
	Msg string
}

// Error implements the error interface.
func ( Error) () string {
	if .Pos.Filename != "" || .Pos.IsValid() {
		// don't print "<unknown position>"
		// TODO(gri) reconsider the semantics of Position.IsValid
		return .Pos.String() + ": " + .Msg
	}
	return .Msg
}

// ErrorList is a list of *Errors.
// The zero value for an ErrorList is an empty ErrorList ready to use.
type ErrorList []*Error

// Add adds an [Error] with given position and error message to an [ErrorList].
func ( *ErrorList) ( token.Position,  string) {
	* = append(*, &Error{, })
}

// Reset resets an [ErrorList] to no errors.
func ( *ErrorList) () { * = (*)[0:0] }

// [ErrorList] implements the sort Interface.
func ( ErrorList) () int      { return len() }
func ( ErrorList) (,  int) { [], [] = [], [] }

func ( ErrorList) (,  int) bool {
	 := &[].Pos
	 := &[].Pos
	// Note that it is not sufficient to simply compare file offsets because
	// the offsets do not reflect modified line information (through //line
	// comments).
	if .Filename != .Filename {
		return .Filename < .Filename
	}
	if .Line != .Line {
		return .Line < .Line
	}
	if .Column != .Column {
		return .Column < .Column
	}
	return [].Msg < [].Msg
}

// Sort sorts an [ErrorList]. *[Error] entries are sorted by position,
// other errors are sorted by error message, and before any *[Error]
// entry.
func ( ErrorList) () {
	sort.Sort()
}

// RemoveMultiples sorts an [ErrorList] and removes all but the first error per line.
func ( *ErrorList) () {
	sort.Sort()
	var  token.Position // initial last.Line is != any legal error line
	 := 0
	for ,  := range * {
		if .Pos.Filename != .Filename || .Pos.Line != .Line {
			 = .Pos
			(*)[] = 
			++
		}
	}
	* = (*)[0:]
}

// An [ErrorList] implements the error interface.
func ( ErrorList) () string {
	switch len() {
	case 0:
		return "no errors"
	case 1:
		return [0].Error()
	}
	return fmt.Sprintf("%s (and %d more errors)", [0], len()-1)
}

// Err returns an error equivalent to this error list.
// If the list is empty, Err returns nil.
func ( ErrorList) () error {
	if len() == 0 {
		return nil
	}
	return 
}

// PrintError is a utility function that prints a list of errors to w,
// one error per line, if the err parameter is an [ErrorList]. Otherwise
// it prints the err string.
func ( io.Writer,  error) {
	if ,  := .(ErrorList);  {
		for ,  := range  {
			fmt.Fprintf(, "%s\n", )
		}
	} else if  != nil {
		fmt.Fprintf(, "%s\n", )
	}
}