1
2
3
4
5 package scanner
6
7 import (
8 "fmt"
9 "go/token"
10 "io"
11 "os"
12 "sort"
13 )
14
15
16
17
18
19
20 type ErrorHandler interface {
21 Error(pos token.Position, msg string)
22 }
23
24
25
26
27
28
29
30
31
32
33 type ErrorVector struct {
34 errors []*Error
35 }
36
37
38 func (h *ErrorVector) Reset() { h.errors = h.errors[:0] }
39
40
41 func (h *ErrorVector) ErrorCount() int { return len(h.errors) }
42
43
44
45
46
47 type Error struct {
48 Pos token.Position
49 Msg string
50 }
51
52 func (e *Error) String() string {
53 if e.Pos.Filename != "" || e.Pos.IsValid() {
54
55
56 return e.Pos.String() + ": " + e.Msg
57 }
58 return e.Msg
59 }
60
61
62 type ErrorList []*Error
63
64
65 func (p ErrorList) Len() int { return len(p) }
66 func (p ErrorList) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
67
68 func (p ErrorList) Less(i, j int) bool {
69 e := &p[i].Pos
70 f := &p[j].Pos
71
72
73
74 if e.Filename < f.Filename {
75 return true
76 }
77 if e.Filename == f.Filename {
78 if e.Line < f.Line {
79 return true
80 }
81 if e.Line == f.Line {
82 return e.Column < f.Column
83 }
84 }
85 return false
86 }
87
88 func (p ErrorList) String() string {
89 switch len(p) {
90 case 0:
91 return "unspecified error"
92 case 1:
93 return p[0].String()
94 }
95 return fmt.Sprintf("%s (and %d more errors)", p[0].String(), len(p)-1)
96 }
97
98
99
100
101 const (
102 Raw = iota
103 Sorted
104 NoMultiples
105 )
106
107
108
109
110
111 func (h *ErrorVector) GetErrorList(mode int) ErrorList {
112 if len(h.errors) == 0 {
113 return nil
114 }
115
116 list := make(ErrorList, len(h.errors))
117 copy(list, h.errors)
118
119 if mode >= Sorted {
120 sort.Sort(list)
121 }
122
123 if mode >= NoMultiples {
124 var last token.Position
125 i := 0
126 for _, e := range list {
127 if e.Pos.Filename != last.Filename || e.Pos.Line != last.Line {
128 last = e.Pos
129 list[i] = e
130 i++
131 }
132 }
133 list = list[0:i]
134 }
135
136 return list
137 }
138
139
140
141
142
143 func (h *ErrorVector) GetError(mode int) os.Error {
144 if len(h.errors) == 0 {
145 return nil
146 }
147
148 return h.GetErrorList(mode)
149 }
150
151
152 func (h *ErrorVector) Error(pos token.Position, msg string) {
153 h.errors = append(h.errors, &Error{pos, msg})
154 }
155
156
157
158
159
160 func PrintError(w io.Writer, err os.Error) {
161 if list, ok := err.(ErrorList); ok {
162 for _, e := range list {
163 fmt.Fprintf(w, "%s\n", e)
164 }
165 } else {
166 fmt.Fprintf(w, "%s\n", err)
167 }
168 }