r - tokeniser.go
1 package r
2
3 import (
4 "io"
5 "strconv"
6
7 "vimagination.zapto.org/parser"
8 )
9
10 const (
11 whitespace = "\t\v\f \u00a0\ufeff" // Tab, Vertical Tab, Form Feed, Space, No-break space, ZeroWidth No-Break Space, https://262.ecma-international.org/11.0/#table-32
12 lineTerminators = "\n\r\u2028\u2029" // Semi-Colon, Line Feed, Carriage Return, Line Separator, Paragraph Separator, https://262.ecma-international.org/11.0/#table-33
13 octalDigit = "01234567"
14 decimalDigit = "0123456789"
15 hexDigit = "0123456789abcdefABCDEF"
16 identifierStart = "ABCDEFGHIJKLMNOPQRSTUVQXYZabcdefghijklmnopqrstuvwxyz"
17 identifierCont = "_.0123456789ABCDEFGHIJKLMNOPQRSTUVQXYZabcdefghijklmnopqrstuvwxyz"
18 )
19
20 // TokenType IDs
21 const (
22 TokenWhitespace parser.TokenType = iota
23 TokenLineTerminator
24 TokenWhitespaceLineTerminator
25 TokenExpressionTerminator
26 TokenComment
27 TokenStringLiteral
28 TokenNumericLiteral
29 TokenIntegerLiteral
30 TokenComplexLiteral
31 TokenBooleanLiteral
32 TokenNull
33 TokenNA
34 TokenIdentifier
35 TokenKeyword
36 TokenEllipsis
37 TokenOperator
38 TokenSpecialOperator
39 TokenGrouping
40 )
41
42 // SetTokeniser sets the initial tokeniser state of a parser.Tokeniser.
43 //
44 // Used if you want to manually tokeniser R source code.
45 func SetTokeniser(t *parser.Tokeniser) *parser.Tokeniser {
46 t.TokeniserState(new(rTokeniser).expression)
47
48 return t
49 }
50
51 type rTokeniser struct {
52 state []byte
53 }
54
55 func (r *rTokeniser) lastState() byte {
56 if len(r.state) == 0 {
57 return 0
58 }
59
60 d := r.state[len(r.state)-1]
61
62 r.state = r.state[:len(r.state)-1]
63
64 return d
65 }
66
67 func (r *rTokeniser) expression(t *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
68 if t.Peek() == -1 {
69 if len(r.state) != 0 {
70 return t.ReturnError(io.ErrUnexpectedEOF)
71 }
72
73 return t.Done()
74 }
75
76 if t.Accept(whitespace) {
77 t.AcceptRun(whitespace)
78
79 return t.Return(TokenWhitespace, r.expression)
80 }
81
82 if t.Accept(lineTerminators) {
83 if len(r.state) > 0 && r.state[len(r.state)-1] != '}' {
84 return t.Return(TokenWhitespaceLineTerminator, r.expression)
85 }
86
87 return t.Return(TokenLineTerminator, r.expression)
88 }
89
90 if t.Accept("#") {
91 t.ExceptRun(lineTerminators)
92
93 return t.Return(TokenComment, r.expression)
94 }
95
96 if t.Accept(identifierStart) {
97 return r.identifier(t)
98 }
99
100 if c := t.Peek(); c == '"' || c == '\'' {
101 return r.string(t)
102 } else if c == '.' || c >= '0' && c <= '9' {
103 return r.number(t)
104 }
105
106 return r.operator(t)
107 }
108
109 func (r *rTokeniser) string(t *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
110 quote := t.Next()
111
112 chars := string(quote) + "\\"
113
114 for {
115 switch t.ExceptRun(chars) {
116 case quote:
117 t.Next()
118
119 return t.Return(TokenStringLiteral, r.expression)
120 case '\\':
121 t.Next()
122
123 switch t.Peek() {
124 case '\'', '"', 'n', 'r', 't', 'b', 'a', 'f', 'v', '\\':
125 t.Next()
126 case '0', '1', '2', '3', '4', '5', '6', '7':
127 t.Next()
128
129 if !t.Accept(octalDigit) || !t.Accept(octalDigit) {
130 return t.ReturnError(ErrInvalidString)
131 }
132 case 'x':
133 t.Next()
134
135 if !t.Accept(hexDigit) || !t.Accept(hexDigit) {
136 return t.ReturnError(ErrInvalidString)
137 }
138 case 'u':
139 t.Next()
140
141 brace := t.Accept("{")
142
143 if !t.Accept(hexDigit) {
144 return t.ReturnError(ErrInvalidString)
145 }
146
147 if brace {
148 t.Accept(hexDigit)
149 t.Accept(hexDigit)
150 t.Accept(hexDigit)
151
152 if !t.Accept("}") {
153 return t.ReturnError(ErrInvalidString)
154 }
155 } else if !t.Accept(hexDigit) || !t.Accept(hexDigit) || !t.Accept(hexDigit) {
156 return t.ReturnError(ErrInvalidString)
157 }
158 case 'U':
159 t.Next()
160
161 brace := t.Accept("{")
162
163 if !t.Accept(hexDigit) {
164 return t.ReturnError(ErrInvalidString)
165 }
166
167 if brace {
168 t.Accept(hexDigit)
169 t.Accept(hexDigit)
170 t.Accept(hexDigit)
171 t.Accept(hexDigit)
172 t.Accept(hexDigit)
173 t.Accept(hexDigit)
174 t.Accept(hexDigit)
175
176 if !t.Accept("}") {
177 return t.ReturnError(ErrInvalidString)
178 }
179 } else if !t.Accept(hexDigit) || !t.Accept(hexDigit) || !t.Accept(hexDigit) || !t.Accept(hexDigit) || !t.Accept(hexDigit) || !t.Accept(hexDigit) || !t.Accept(hexDigit) {
180 return t.ReturnError(ErrInvalidString)
181 }
182 default:
183 return t.ReturnError(ErrInvalidString)
184 }
185 case -1:
186 return t.ReturnError(ErrInvalidString)
187 }
188 }
189 }
190
191 func (r *rTokeniser) number(t *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
192 if t.Accept(".") {
193 if !t.Accept(decimalDigit) {
194 return r.ellipsisOrIdentifier(t)
195 }
196
197 return r.float(t, decimalDigit)
198 }
199
200 digits := decimalDigit
201
202 if t.Accept("0") {
203 if t.Accept("x") {
204 digits = hexDigit
205
206 if !t.Accept(digits) {
207 return t.ReturnError(ErrInvalidNumber)
208 }
209 }
210 }
211
212 t.AcceptRun(digits)
213
214 if t.Accept("L") {
215 return t.Return(TokenIntegerLiteral, r.expression)
216 } else if t.Accept("i") {
217 return t.Return(TokenComplexLiteral, r.expression)
218 } else if t.Accept(".") {
219 return r.float(t, digits)
220 }
221
222 return r.exponential(t, digits)
223 }
224
225 func (r *rTokeniser) float(t *parser.Tokeniser, digits string) (parser.Token, parser.TokenFunc) {
226 if digits == hexDigit && !t.Accept(digits) {
227 return t.ReturnError(ErrInvalidNumber)
228 }
229
230 t.AcceptRun(digits)
231
232 if t.Accept("L") {
233 return t.Return(TokenIntegerLiteral, r.expression)
234 } else if t.Accept("i") {
235 return t.Return(TokenComplexLiteral, r.expression)
236 }
237
238 return r.exponential(t, digits)
239 }
240
241 func (r *rTokeniser) exponential(t *parser.Tokeniser, digits string) (parser.Token, parser.TokenFunc) {
242 e := "eE"
243
244 if digits == hexDigit {
245 e = "pP"
246 }
247
248 if t.Accept(e) {
249 t.Accept("+-")
250
251 if !t.Accept(digits) {
252 return t.ReturnError(ErrInvalidNumber)
253 }
254
255 t.AcceptRun(digits)
256 }
257
258 if t.Accept("L") {
259 return t.Return(TokenIntegerLiteral, r.expression)
260 } else if t.Accept("i") {
261 return t.Return(TokenComplexLiteral, r.expression)
262 }
263
264 return t.Return(TokenNumericLiteral, r.expression)
265 }
266
267 func (r *rTokeniser) ellipsisOrIdentifier(t *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
268 if t.Accept(".") {
269 if t.Accept(".") {
270 if !t.Accept(identifierCont) {
271 return t.Return(TokenEllipsis, r.expression)
272 }
273 } else if t.Accept(decimalDigit) {
274 t.AcceptRun(decimalDigit)
275
276 if !t.Accept(identifierCont) {
277 return t.Return(TokenEllipsis, r.expression)
278 }
279 }
280 }
281
282 return r.identifier(t)
283 }
284
285 func (r *rTokeniser) identifier(t *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
286 t.AcceptRun(identifierCont)
287
288 tk := parser.Token{Type: TokenIdentifier, Data: t.Get()}
289
290 switch tk.Data {
291 case "NULL":
292 tk.Type = TokenNull
293 case "TRUE", "FALSE":
294 tk.Type = TokenBooleanLiteral
295 case "Inf", "NaN":
296 tk.Type = TokenNumericLiteral
297 case "NA", "NA_character_", "NA_integer_", "NA_real_", "NA_complex_":
298 tk.Type = TokenNA
299 case "if", "else", "repeat", "while", "function", "for", "in", "next", "break":
300 tk.Type = TokenKeyword
301 }
302
303 return tk, r.expression
304 }
305
306 func (r *rTokeniser) operator(t *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
307 if t.Accept(";,") {
308 return t.Return(TokenExpressionTerminator, r.expression)
309 } else if t.Accept("+*/^~$@?") {
310 } else if t.Accept(">=!") {
311 t.Accept("=")
312 } else if t.Accept("-") {
313 t.Accept(">")
314 t.Accept(">")
315 } else if t.Accept("<") {
316 if t.Accept("<") && !t.Accept("-") {
317 return t.ReturnError(ErrInvalidOperator)
318 } else {
319 t.Accept("=-")
320 }
321 } else if t.Accept("%") {
322 for ; t.Peek() != '%' && strconv.IsPrint(t.Peek()); t.Next() {
323 }
324
325 if !t.Accept("%") {
326 return t.ReturnError(ErrInvalidOperator)
327 }
328
329 return t.Return(TokenSpecialOperator, r.expression)
330 } else if t.Accept(":") {
331 t.Accept(":")
332 } else if t.Accept("&") {
333 t.Accept("&")
334 } else if t.Accept("|") {
335 t.Accept("|>")
336 } else if t.Accept("[") {
337 if t.Accept("[") {
338 r.state = append(r.state, '#')
339 } else {
340 r.state = append(r.state, ']')
341 }
342
343 return t.Return(TokenGrouping, r.expression)
344 } else if t.Accept("(") {
345 r.state = append(r.state, ')')
346
347 return t.Return(TokenGrouping, r.expression)
348 } else if t.Accept("{") {
349 r.state = append(r.state, '}')
350
351 return t.Return(TokenGrouping, r.expression)
352 } else if t.Accept("]") {
353 if g := r.lastState(); g == '#' {
354 if !t.Accept("]") {
355 return t.ReturnError(ErrInvalidCharacter)
356 }
357 } else if g != ']' {
358 return t.ReturnError(ErrInvalidCharacter)
359 }
360
361 return t.Return(TokenGrouping, r.expression)
362 } else if t.Accept(")") {
363 if r.lastState() != ')' {
364 return t.ReturnError(ErrInvalidCharacter)
365 }
366
367 return t.Return(TokenGrouping, r.expression)
368 } else if t.Accept("}") {
369 if r.lastState() != '}' {
370 return t.ReturnError(ErrInvalidCharacter)
371 }
372
373 return t.Return(TokenGrouping, r.expression)
374 } else {
375 return t.ReturnError(ErrInvalidCharacter)
376 }
377
378 return t.Return(TokenOperator, r.expression)
379 }
380