1
33 package parser
34
35 import (
36 "bytes"
37 "errors"
38 "io"
39 "os"
40
41 "github.com/dop251/goja/ast"
42 "github.com/dop251/goja/file"
43 "github.com/dop251/goja/token"
44 "github.com/dop251/goja/unistring"
45 )
46
47
48 type Mode uint
49
50 const (
51 IgnoreRegExpErrors Mode = 1 << iota
52 )
53
54 type options struct {
55 disableSourceMaps bool
56 sourceMapLoader func(path string) ([]byte, error)
57 }
58
59
60
61 type Option func(*options)
62
63
64
65 func WithDisableSourceMaps(opts *options) {
66 opts.disableSourceMaps = true
67 }
68
69
70
71
72
73
74 func WithSourceMapLoader(loader func(path string) ([]byte, error)) Option {
75 return func(opts *options) {
76 opts.sourceMapLoader = loader
77 }
78 }
79
80 type _parser struct {
81 str string
82 length int
83 base int
84
85 chr rune
86 chrOffset int
87 offset int
88
89 idx file.Idx
90 token token.Token
91 literal string
92 parsedLiteral unistring.String
93
94 scope *_scope
95 insertSemicolon bool
96 implicitSemicolon bool
97
98 errors ErrorList
99
100 recover struct {
101
102 idx file.Idx
103 count int
104 }
105
106 mode Mode
107 opts options
108
109 file *file.File
110 }
111
112 func _newParser(filename, src string, base int, opts ...Option) *_parser {
113 p := &_parser{
114 chr: ' ',
115 str: src,
116 length: len(src),
117 base: base,
118 file: file.NewFile(filename, src, base),
119 }
120 for _, opt := range opts {
121 opt(&p.opts)
122 }
123 return p
124 }
125
126 func newParser(filename, src string) *_parser {
127 return _newParser(filename, src, 1)
128 }
129
130 func ReadSource(filename string, src interface{}) ([]byte, error) {
131 if src != nil {
132 switch src := src.(type) {
133 case string:
134 return []byte(src), nil
135 case []byte:
136 return src, nil
137 case *bytes.Buffer:
138 if src != nil {
139 return src.Bytes(), nil
140 }
141 case io.Reader:
142 var bfr bytes.Buffer
143 if _, err := io.Copy(&bfr, src); err != nil {
144 return nil, err
145 }
146 return bfr.Bytes(), nil
147 }
148 return nil, errors.New("invalid source")
149 }
150 return os.ReadFile(filename)
151 }
152
153
154
155
156
157
158
159
160
161
162
163
164
165 func ParseFile(fileSet *file.FileSet, filename string, src interface{}, mode Mode, options ...Option) (*ast.Program, error) {
166 str, err := ReadSource(filename, src)
167 if err != nil {
168 return nil, err
169 }
170 {
171 str := string(str)
172
173 base := 1
174 if fileSet != nil {
175 base = fileSet.AddFile(filename, str)
176 }
177
178 parser := _newParser(filename, str, base, options...)
179 parser.mode = mode
180 return parser.parse()
181 }
182 }
183
184
185
186
187
188 func ParseFunction(parameterList, body string, options ...Option) (*ast.FunctionLiteral, error) {
189
190 src := "(function(" + parameterList + ") {\n" + body + "\n})"
191
192 parser := _newParser("", src, 1, options...)
193 program, err := parser.parse()
194 if err != nil {
195 return nil, err
196 }
197
198 return program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral), nil
199 }
200
201 func (self *_parser) slice(idx0, idx1 file.Idx) string {
202 from := int(idx0) - self.base
203 to := int(idx1) - self.base
204 if from >= 0 && to <= len(self.str) {
205 return self.str[from:to]
206 }
207
208 return ""
209 }
210
211 func (self *_parser) parse() (*ast.Program, error) {
212 self.openScope()
213 defer self.closeScope()
214 self.next()
215 program := self.parseProgram()
216 if false {
217 self.errors.Sort()
218 }
219 return program, self.errors.Err()
220 }
221
222 func (self *_parser) next() {
223 self.token, self.literal, self.parsedLiteral, self.idx = self.scan()
224 }
225
226 func (self *_parser) optionalSemicolon() {
227 if self.token == token.SEMICOLON {
228 self.next()
229 return
230 }
231
232 if self.implicitSemicolon {
233 self.implicitSemicolon = false
234 return
235 }
236
237 if self.token != token.EOF && self.token != token.RIGHT_BRACE {
238 self.expect(token.SEMICOLON)
239 }
240 }
241
242 func (self *_parser) semicolon() {
243 if self.token != token.RIGHT_PARENTHESIS && self.token != token.RIGHT_BRACE {
244 if self.implicitSemicolon {
245 self.implicitSemicolon = false
246 return
247 }
248
249 self.expect(token.SEMICOLON)
250 }
251 }
252
253 func (self *_parser) idxOf(offset int) file.Idx {
254 return file.Idx(self.base + offset)
255 }
256
257 func (self *_parser) expect(value token.Token) file.Idx {
258 idx := self.idx
259 if self.token != value {
260 self.errorUnexpectedToken(self.token)
261 }
262 self.next()
263 return idx
264 }
265
266 func (self *_parser) position(idx file.Idx) file.Position {
267 return self.file.Position(int(idx) - self.base)
268 }
269
View as plain text