// 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 (
	"container/vector";
	"fmt";
	"go/token";
	"io";
	"os";
	"sort";
)


// An implementation of an ErrorHandler may be provided to the Scanner.
// If a syntax error is encountered and a handler was installed, Error
// is called with a position and an error message. The position points
// to the beginning of the offending token.
//
type ErrorHandler interface {
	Error(pos token.Position, msg string);
}


// ErrorVector implements the ErrorHandler interface. It must be
// initialized with Init(). It maintains a list of errors which can
// be retrieved with GetErrorList and GetError.
//
// A common usage pattern is to embed an ErrorVector alongside a
// scanner in a data structure that uses the scanner. By passing a
// reference to an ErrorVector to the scanner's Init call, default
// error handling is obtained.
//
type ErrorVector struct {
	errors vector.Vector;
}


// Init initializes an ErrorVector.
func (h *ErrorVector) Init()	{ h.errors.Init(0) }


// NewErrorVector creates a new ErrorVector.
func NewErrorVector() *ErrorVector {
	h := new(ErrorVector);
	h.Init();
	return h;
}


// ErrorCount returns the number of errors collected.
func (h *ErrorVector) ErrorCount() int	{ return h.errors.Len() }


// Within ErrorVector, an error is represented by an Error node. 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;
}


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


// An ErrorList is a (possibly sorted) list of Errors.
type ErrorList []*Error


// ErrorList implements the sort Interface.
func (p ErrorList) Len() int		{ return len(p) }
func (p ErrorList) Swap(i, j int)	{ p[i], p[j] = p[j], p[i] }


func (p ErrorList) Less(i, j int) bool {
	e := &p[i].Pos;
	f := &p[j].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 e.Filename < f.Filename {
		return true
	}
	if e.Filename == f.Filename {
		if e.Line < f.Line {
			return true
		}
		if e.Line == f.Line {
			return e.Column < f.Column
		}
	}
	return false;
}


func (p ErrorList) String() string {
	switch len(p) {
	case 0:
		return "unspecified error"
	case 1:
		return p[0].String()
	}
	return fmt.Sprintf("%s (and %d more errors)", p[0].String(), len(p)-1);
}


// These constants control the construction of the ErrorList
// returned by GetErrors.
//
const (
	Raw		= iota;	// leave error list unchanged
	Sorted;		// sort error list by file, line, and column number
	NoMultiples;	// sort error list and leave only the first error per line
)


// GetErrorList returns the list of errors collected by an ErrorVector.
// The construction of the ErrorList returned is controlled by the mode
// parameter. If there are no errors, the result is nil.
//
func (h *ErrorVector) GetErrorList(mode int) ErrorList {
	if h.errors.Len() == 0 {
		return nil
	}

	list := make(ErrorList, h.errors.Len());
	for i := 0; i < h.errors.Len(); i++ {
		list[i] = h.errors.At(i).(*Error)
	}

	if mode >= Sorted {
		sort.Sort(list)
	}

	if mode >= NoMultiples {
		var last token.Position;	// initial last.Line is != any legal error line
		i := 0;
		for _, e := range list {
			if e.Pos.Filename != last.Filename || e.Pos.Line != last.Line {
				last = e.Pos;
				list[i] = e;
				i++;
			}
		}
		list = list[0:i];
	}

	return list;
}


// GetError is like GetErrorList, but it returns an os.Error instead
// so that a nil result can be assigned to an os.Error variable and
// remains nil.
//
func (h *ErrorVector) GetError(mode int) os.Error {
	if h.errors.Len() == 0 {
		return nil
	}

	return h.GetErrorList(mode);
}


// ErrorVector implements the ErrorHandler interface.
func (h *ErrorVector) Error(pos token.Position, msg string) {
	h.errors.Push(&Error{pos, msg})
}


// 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 PrintError(w io.Writer, err os.Error) {
	if list, ok := err.(ErrorList); ok {
		for _, e := range list {
			fmt.Fprintf(w, "%s\n", e)
		}
	} else {
		fmt.Fprintf(w, "%s\n", err)
	}
}
