...
1 package parser
2
3 import (
4 "fmt"
5 "sort"
6
7 "github.com/dop251/goja/file"
8 "github.com/dop251/goja/token"
9 )
10
11 const (
12 err_UnexpectedToken = "Unexpected token %v"
13 err_UnexpectedEndOfInput = "Unexpected end of input"
14 err_UnexpectedEscape = "Unexpected escape"
15 )
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 type Error struct {
53 Position file.Position
54 Message string
55 }
56
57
58
59 func (self Error) Error() string {
60 filename := self.Position.Filename
61 if filename == "" {
62 filename = "(anonymous)"
63 }
64 return fmt.Sprintf("%s: Line %d:%d %s",
65 filename,
66 self.Position.Line,
67 self.Position.Column,
68 self.Message,
69 )
70 }
71
72 func (self *_parser) error(place interface{}, msg string, msgValues ...interface{}) *Error {
73 idx := file.Idx(0)
74 switch place := place.(type) {
75 case int:
76 idx = self.idxOf(place)
77 case file.Idx:
78 if place == 0 {
79 idx = self.idxOf(self.chrOffset)
80 } else {
81 idx = place
82 }
83 default:
84 panic(fmt.Errorf("error(%T, ...)", place))
85 }
86
87 position := self.position(idx)
88 msg = fmt.Sprintf(msg, msgValues...)
89 self.errors.Add(position, msg)
90 return self.errors[len(self.errors)-1]
91 }
92
93 func (self *_parser) errorUnexpected(idx file.Idx, chr rune) error {
94 if chr == -1 {
95 return self.error(idx, err_UnexpectedEndOfInput)
96 }
97 return self.error(idx, err_UnexpectedToken, token.ILLEGAL)
98 }
99
100 func (self *_parser) errorUnexpectedToken(tkn token.Token) error {
101 switch tkn {
102 case token.EOF:
103 return self.error(file.Idx(0), err_UnexpectedEndOfInput)
104 }
105 value := tkn.String()
106 switch tkn {
107 case token.BOOLEAN, token.NULL:
108 value = self.literal
109 case token.IDENTIFIER:
110 return self.error(self.idx, "Unexpected identifier")
111 case token.KEYWORD:
112
113 return self.error(self.idx, "Unexpected reserved word")
114 case token.ESCAPED_RESERVED_WORD:
115 return self.error(self.idx, "Keyword must not contain escaped characters")
116 case token.NUMBER:
117 return self.error(self.idx, "Unexpected number")
118 case token.STRING:
119 return self.error(self.idx, "Unexpected string")
120 }
121 return self.error(self.idx, err_UnexpectedToken, value)
122 }
123
124
125 type ErrorList []*Error
126
127
128 func (self *ErrorList) Add(position file.Position, msg string) {
129 *self = append(*self, &Error{position, msg})
130 }
131
132
133 func (self *ErrorList) Reset() { *self = (*self)[0:0] }
134
135 func (self ErrorList) Len() int { return len(self) }
136 func (self ErrorList) Swap(i, j int) { self[i], self[j] = self[j], self[i] }
137 func (self ErrorList) Less(i, j int) bool {
138 x := &self[i].Position
139 y := &self[j].Position
140 if x.Filename < y.Filename {
141 return true
142 }
143 if x.Filename == y.Filename {
144 if x.Line < y.Line {
145 return true
146 }
147 if x.Line == y.Line {
148 return x.Column < y.Column
149 }
150 }
151 return false
152 }
153
154 func (self ErrorList) Sort() {
155 sort.Sort(self)
156 }
157
158
159 func (self ErrorList) Error() string {
160 switch len(self) {
161 case 0:
162 return "no errors"
163 case 1:
164 return self[0].Error()
165 }
166 return fmt.Sprintf("%s (and %d more errors)", self[0].Error(), len(self)-1)
167 }
168
169
170
171 func (self ErrorList) Err() error {
172 if len(self) == 0 {
173 return nil
174 }
175 return self
176 }
177
View as plain text