OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [go/] [scanner/] [errors.go] - Rev 747

Compare with Previous | Blame | View Log

// 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 (
        "fmt"
        "go/token"
        "io"
        "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 maintains a list
// of errors which can be retrieved with GetErrorList and GetError. The
// zero value for an ErrorVector is an empty ErrorVector ready to use.
//
// 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 []*Error
}

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

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

// 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) Error() 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) Error() string {
        switch len(p) {
        case 0:
                return "unspecified error"
        case 1:
                return p[0].Error()
        }
        return fmt.Sprintf("%s (and %d more errors)", p[0], 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 len(h.errors) == 0 {
                return nil
        }

        list := make(ErrorList, len(h.errors))
        copy(list, h.errors)

        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 error instead
// so that a nil result can be assigned to an error variable and
// remains nil.
//
func (h *ErrorVector) GetError(mode int) error {
        if len(h.errors) == 0 {
                return nil
        }

        return h.GetErrorList(mode)
}

// ErrorVector implements the ErrorHandler interface.
func (h *ErrorVector) Error(pos token.Position, msg string) {
        h.errors = append(h.errors, &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 error) {
        if list, ok := err.(ErrorList); ok {
                for _, e := range list {
                        fmt.Fprintf(w, "%s\n", e)
                }
        } else {
                fmt.Fprintf(w, "%s\n", err)
        }
}

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.