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 tokenDepth []byte
53 }
54
55 func (r *rTokeniser) lastDepth() byte {
56 if len(r.tokenDepth) == 0 {
57 return 0
58 }
59
60 d := r.tokenDepth[len(r.tokenDepth)-1]
61
62 r.tokenDepth = r.tokenDepth[:len(r.tokenDepth)-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.tokenDepth) != 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.tokenDepth) > 0 && r.tokenDepth[len(r.tokenDepth)-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
149 t.Accept(hexDigit)
150 t.Accept(hexDigit)
151 t.Accept(hexDigit)
152
153 if !t.Accept("}") {
154 return t.ReturnError(ErrInvalidString)
155 }
156 } else if !t.Accept(hexDigit) || !t.Accept(hexDigit) || !t.Accept(hexDigit) {
157 return t.ReturnError(ErrInvalidString)
158 }
159 case 'U':
160 t.Next()
161
162 brace := t.Accept("{")
163
164 if !t.Accept(hexDigit) {
165 return t.ReturnError(ErrInvalidString)
166 }
167
168 if brace {
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 t.Accept(hexDigit)
176
177 if !t.Accept("}") {
178 return t.ReturnError(ErrInvalidString)
179 }
180 } else if !t.Accept(hexDigit) || !t.Accept(hexDigit) || !t.Accept(hexDigit) || !t.Accept(hexDigit) || !t.Accept(hexDigit) || !t.Accept(hexDigit) || !t.Accept(hexDigit) {
181 return t.ReturnError(ErrInvalidString)
182 }
183 default:
184 return t.ReturnError(ErrInvalidString)
185 }
186 case -1:
187 return t.ReturnError(ErrInvalidString)
188 }
189 }
190 }
191
192 func (r *rTokeniser) number(t *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
193 if t.Accept(".") {
194 if !t.Accept(decimalDigit) {
195 return r.ellipsisOrIdentifier(t)
196 }
197
198 return r.float(t, decimalDigit)
199 }
200
201 digits := decimalDigit
202
203 if t.Accept("0") {
204 if t.Accept("x") {
205 digits = hexDigit
206
207 if !t.Accept(digits) {
208 return t.ReturnError(ErrInvalidNumber)
209 }
210 }
211 }
212
213 t.AcceptRun(digits)
214
215 if t.Accept("L") {
216 return t.Return(TokenIntegerLiteral, r.expression)
217 } else if t.Accept("i") {
218 return t.Return(TokenComplexLiteral, r.expression)
219 } else if t.Accept(".") {
220 return r.float(t, digits)
221 }
222
223 return r.exponential(t, digits)
224 }
225
226 func (r *rTokeniser) float(t *parser.Tokeniser, digits string) (parser.Token, parser.TokenFunc) {
227 if digits == hexDigit && !t.Accept(digits) {
228 return t.ReturnError(ErrInvalidNumber)
229 }
230
231 t.AcceptRun(digits)
232
233 if t.Accept("L") {
234 return t.Return(TokenIntegerLiteral, r.expression)
235 } else if t.Accept("i") {
236 return t.Return(TokenComplexLiteral, r.expression)
237 }
238
239 return r.exponential(t, digits)
240 }
241
242 func (r *rTokeniser) exponential(t *parser.Tokeniser, digits string) (parser.Token, parser.TokenFunc) {
243 e := "eE"
244
245 if digits == hexDigit {
246 e = "pP"
247 }
248
249 if t.Accept(e) {
250 t.Accept("+-")
251
252 if !t.Accept(digits) {
253 return t.ReturnError(ErrInvalidNumber)
254 }
255
256 t.AcceptRun(digits)
257 }
258
259 if t.Accept("L") {
260 return t.Return(TokenIntegerLiteral, r.expression)
261 } else if t.Accept("i") {
262 return t.Return(TokenComplexLiteral, r.expression)
263 }
264
265 return t.Return(TokenNumericLiteral, r.expression)
266 }
267
268 func (r *rTokeniser) ellipsisOrIdentifier(t *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
269 if t.Accept(".") {
270 if t.Accept(".") {
271 if !t.Accept(identifierCont) {
272 return t.Return(TokenEllipsis, r.expression)
273 }
274 } else if t.Accept(decimalDigit) {
275 t.AcceptRun(decimalDigit)
276
277 if !t.Accept(identifierCont) {
278 return t.Return(TokenEllipsis, r.expression)
279 }
280 }
281 }
282
283 return r.identifier(t)
284 }
285
286 func (r *rTokeniser) identifier(t *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
287 t.AcceptRun(identifierCont)
288
289 tk := parser.Token{Type: TokenIdentifier, Data: t.Get()}
290
291 switch tk.Data {
292 case "NULL":
293 tk.Type = TokenNull
294 case "TRUE", "FALSE":
295 tk.Type = TokenBooleanLiteral
296 case "Inf", "NaN":
297 tk.Type = TokenNumericLiteral
298 case "NA", "NA_character_", "NA_integer_", "NA_real_", "NA_complex_":
299 tk.Type = TokenNA
300 case "if", "else", "repeat", "while", "function", "for", "in", "next", "break":
301 tk.Type = TokenKeyword
302 }
303
304 return tk, r.expression
305 }
306
307 func (r *rTokeniser) operator(t *parser.Tokeniser) (parser.Token, parser.TokenFunc) {
308 if t.Accept(";,") {
309 return t.Return(TokenExpressionTerminator, r.expression)
310 } else if t.Accept("+*/^~$@?") {
311 } else if t.Accept(">=!") {
312 t.Accept("=")
313 } else if t.Accept("-") {
314 t.Accept(">")
315 t.Accept(">")
316 } else if t.Accept("<") {
317 if t.Accept("<") && !t.Accept("-") {
318 return t.ReturnError(ErrInvalidOperator)
319 } else {
320 t.Accept("=-")
321 }
322 } else if t.Accept("%") {
323 for ; t.Peek() != '%' && strconv.IsPrint(t.Peek()); t.Next() {
324 }
325
326 if !t.Accept("%") {
327 return t.ReturnError(ErrInvalidOperator)
328 }
329
330 return t.Return(TokenSpecialOperator, r.expression)
331 } else if t.Accept(":") {
332 t.Accept(":")
333 } else if t.Accept("&") {
334 t.Accept("&")
335 } else if t.Accept("|") {
336 t.Accept("|>")
337 } else if t.Accept("[") {
338 if t.Accept("[") {
339 r.tokenDepth = append(r.tokenDepth, '#')
340 } else {
341 r.tokenDepth = append(r.tokenDepth, ']')
342 }
343
344 return t.Return(TokenGrouping, r.expression)
345 } else if t.Accept("(") {
346 r.tokenDepth = append(r.tokenDepth, ')')
347
348 return t.Return(TokenGrouping, r.expression)
349 } else if t.Accept("{") {
350 r.tokenDepth = append(r.tokenDepth, '}')
351
352 return t.Return(TokenGrouping, r.expression)
353 } else if t.Accept("]") {
354 if g := r.lastDepth(); g == '#' {
355 if !t.Accept("]") {
356 return t.ReturnError(ErrInvalidCharacter)
357 }
358 } else if g != ']' {
359 return t.ReturnError(ErrInvalidCharacter)
360 }
361
362 return t.Return(TokenGrouping, r.expression)
363 } else if t.Accept(")") {
364 if r.lastDepth() != ')' {
365 return t.ReturnError(ErrInvalidCharacter)
366 }
367
368 return t.Return(TokenGrouping, r.expression)
369 } else if t.Accept("}") {
370 if r.lastDepth() != '}' {
371 return t.ReturnError(ErrInvalidCharacter)
372 }
373
374 return t.Return(TokenGrouping, r.expression)
375 } else {
376 return t.ReturnError(ErrInvalidCharacter)
377 }
378
379 return t.Return(TokenOperator, r.expression)
380 }
381