ether-code 0.1.8 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,869 +0,0 @@
1
- class Token {
2
- constructor(type, value, line, column, indent = 0) {
3
- this.type = type
4
- this.value = value
5
- this.line = line
6
- this.column = column
7
- this.indent = indent
8
- }
9
-
10
- toString() {
11
- return `Token(${this.type}, ${JSON.stringify(this.value)}, L${this.line}:${this.column})`
12
- }
13
- }
14
-
15
- const TokenType = {
16
- IDENTIFIER: 'IDENTIFIER',
17
- STRING: 'STRING',
18
- BLOCK_STRING: 'BLOCK_STRING',
19
- NUMBER: 'NUMBER',
20
- INTEGER: 'INTEGER',
21
- FLOAT: 'FLOAT',
22
- HEX: 'HEX',
23
-
24
- COLON: 'COLON',
25
- DOUBLE_COLON: 'DOUBLE_COLON',
26
- EQUALS: 'EQUALS',
27
- DOUBLE_EQUALS: 'DOUBLE_EQUALS',
28
- NOT_EQUALS: 'NOT_EQUALS',
29
- COMMA: 'COMMA',
30
- DOT: 'DOT',
31
- SPREAD: 'SPREAD',
32
- ARROW: 'ARROW',
33
- FAT_ARROW: 'FAT_ARROW',
34
-
35
- PLUS: 'PLUS',
36
- MINUS: 'MINUS',
37
- STAR: 'STAR',
38
- DOUBLE_STAR: 'DOUBLE_STAR',
39
- SLASH: 'SLASH',
40
- DOUBLE_SLASH: 'DOUBLE_SLASH',
41
- PERCENT: 'PERCENT',
42
-
43
- BANG: 'BANG',
44
- QUESTION: 'QUESTION',
45
- AMPERSAND: 'AMPERSAND',
46
- DOUBLE_AMPERSAND: 'DOUBLE_AMPERSAND',
47
- PIPE: 'PIPE',
48
- DOUBLE_PIPE: 'DOUBLE_PIPE',
49
- CARET: 'CARET',
50
- TILDE: 'TILDE',
51
-
52
- LT: 'LT',
53
- GT: 'GT',
54
- LTE: 'LTE',
55
- GTE: 'GTE',
56
- SPACESHIP: 'SPACESHIP',
57
-
58
- AT: 'AT',
59
- HASH: 'HASH',
60
- UNDERSCORE: 'UNDERSCORE',
61
- BACKSLASH: 'BACKSLASH',
62
-
63
- LPAREN: 'LPAREN',
64
- RPAREN: 'RPAREN',
65
- LBRACKET: 'LBRACKET',
66
- RBRACKET: 'RBRACKET',
67
- LBRACE: 'LBRACE',
68
- RBRACE: 'RBRACE',
69
-
70
- NEWLINE: 'NEWLINE',
71
- INDENT: 'INDENT',
72
- DEDENT: 'DEDENT',
73
-
74
- LANG_BLOCK: 'LANG_BLOCK',
75
-
76
- COMMENT: 'COMMENT',
77
- BLOCK_COMMENT: 'BLOCK_COMMENT',
78
-
79
- EOF: 'EOF',
80
- ERROR: 'ERROR'
81
- }
82
-
83
- const LANG_BLOCKS = [
84
- 'html', 'css', 'style', 'script', 'js', 'javascript',
85
- 'php', 'python', 'py', 'ruby', 'rb',
86
- 'sql', 'graphql', 'gql',
87
- 'node', 'nodejs', 'ts', 'typescript',
88
- 'react', 'jsx', 'tsx',
89
- 'json', 'xml', 'yaml', 'markdown', 'md'
90
- ]
91
-
92
- class EtherLexer {
93
- constructor(source, options = {}) {
94
- this.source = source
95
- this.pos = 0
96
- this.line = 1
97
- this.column = 1
98
- this.tokens = []
99
- this.indentStack = [0]
100
- this.currentIndent = 0
101
- this.atLineStart = true
102
-
103
- this.options = {
104
- trackComments: options.trackComments || false,
105
- allowUnicode: options.allowUnicode !== false,
106
- tabSize: options.tabSize || 2
107
- }
108
- }
109
-
110
- peek(offset = 0) {
111
- const idx = this.pos + offset
112
- return idx < this.source.length ? this.source[idx] : null
113
- }
114
-
115
- advance() {
116
- const char = this.source[this.pos]
117
- this.pos++
118
- if (char === '\n') {
119
- this.line++
120
- this.column = 1
121
- this.atLineStart = true
122
- } else {
123
- this.column++
124
- }
125
- return char
126
- }
127
-
128
- match(expected) {
129
- if (this.peek() === expected) {
130
- this.advance()
131
- return true
132
- }
133
- return false
134
- }
135
-
136
- matchSequence(seq) {
137
- for (let i = 0; i < seq.length; i++) {
138
- if (this.peek(i) !== seq[i]) return false
139
- }
140
- for (let i = 0; i < seq.length; i++) {
141
- this.advance()
142
- }
143
- return true
144
- }
145
-
146
- isAtEnd() {
147
- return this.pos >= this.source.length
148
- }
149
-
150
- isDigit(char) {
151
- if (!char) return false
152
- return char >= '0' && char <= '9'
153
- }
154
-
155
- isHexDigit(char) {
156
- if (!char) return false
157
- return this.isDigit(char) || (char >= 'a' && char <= 'f') || (char >= 'A' && char <= 'F')
158
- }
159
-
160
- isAlpha(char) {
161
- if (!char) return false
162
- const code = char.charCodeAt(0)
163
- if ((code >= 65 && code <= 90) || (code >= 97 && code <= 122)) return true
164
- if (char === '_') return true
165
- if (this.options.allowUnicode) {
166
- if (code >= 0x00C0 && code <= 0x024F) return true
167
- if (code >= 0x0400 && code <= 0x04FF) return true
168
- if (code >= 0x4E00 && code <= 0x9FFF) return true
169
- if (code >= 0x3040 && code <= 0x30FF) return true
170
- if (code >= 0x0600 && code <= 0x06FF) return true
171
- if (code >= 0x0370 && code <= 0x03FF) return true
172
- }
173
- return false
174
- }
175
-
176
- isAlphaNumeric(char) {
177
- return this.isAlpha(char) || this.isDigit(char)
178
- }
179
-
180
- isWhitespace(char) {
181
- if (!char) return false
182
- return char === ' ' || char === '\t' || char === '\r'
183
- }
184
-
185
- addToken(type, value, startColumn = null) {
186
- const col = startColumn !== null ? startColumn : this.column
187
- this.tokens.push(new Token(type, value, this.line, col, this.currentIndent))
188
- }
189
-
190
- tokenize() {
191
- while (!this.isAtEnd()) {
192
- this.scanToken()
193
- }
194
-
195
- while (this.indentStack.length > 1) {
196
- this.indentStack.pop()
197
- this.tokens.push(new Token(TokenType.DEDENT, '', this.line, this.column, 0))
198
- }
199
-
200
- this.tokens.push(new Token(TokenType.EOF, '', this.line, this.column, 0))
201
- return this.tokens
202
- }
203
-
204
- scanToken() {
205
- if (this.atLineStart) {
206
- this.handleIndentation()
207
- if (this.isAtEnd()) return
208
- }
209
-
210
- const char = this.peek()
211
-
212
- if (char === '\n') {
213
- this.advance()
214
- this.addToken(TokenType.NEWLINE, '\n')
215
- return
216
- }
217
-
218
- if (this.isWhitespace(char)) {
219
- this.advance()
220
- return
221
- }
222
-
223
- if (char === '#') {
224
- this.scanComment()
225
- return
226
- }
227
-
228
- if (char === '/' && this.peek(1) === '/') {
229
- this.scanComment()
230
- return
231
- }
232
-
233
- if (char === '/' && this.peek(1) === '*') {
234
- this.scanBlockComment()
235
- return
236
- }
237
-
238
- if (char === '"' || char === "'") {
239
- this.scanString(char)
240
- return
241
- }
242
-
243
- if (char === '`') {
244
- this.scanTemplateString()
245
- return
246
- }
247
-
248
- if (this.isDigit(char) || (char === '-' && this.isDigit(this.peek(1)))) {
249
- this.scanNumber()
250
- return
251
- }
252
-
253
- if (this.isAlpha(char)) {
254
- this.scanIdentifier()
255
- return
256
- }
257
-
258
- this.scanOperator()
259
- }
260
-
261
- handleIndentation() {
262
- let indent = 0
263
- while (!this.isAtEnd() && (this.peek() === ' ' || this.peek() === '\t')) {
264
- if (this.peek() === '\t') {
265
- indent += this.options.tabSize
266
- } else {
267
- indent++
268
- }
269
- this.advance()
270
- }
271
-
272
- if (this.isAtEnd() || this.peek() === '\n' || this.peek() === '#') {
273
- this.atLineStart = false
274
- return
275
- }
276
-
277
- if (this.peek() === '/' && this.peek(1) === '/') {
278
- this.atLineStart = false
279
- return
280
- }
281
-
282
- this.currentIndent = indent
283
- this.atLineStart = false
284
-
285
- const currentLevel = this.indentStack[this.indentStack.length - 1]
286
-
287
- if (indent > currentLevel) {
288
- this.indentStack.push(indent)
289
- this.tokens.push(new Token(TokenType.INDENT, indent, this.line, 1, indent))
290
- } else if (indent < currentLevel) {
291
- while (this.indentStack.length > 1 && this.indentStack[this.indentStack.length - 1] > indent) {
292
- this.indentStack.pop()
293
- this.tokens.push(new Token(TokenType.DEDENT, '', this.line, 1, indent))
294
- }
295
- if (this.indentStack[this.indentStack.length - 1] !== indent) {
296
- this.tokens.push(new Token(TokenType.ERROR, 'Indentation incohérente', this.line, 1, indent))
297
- }
298
- }
299
- }
300
-
301
- scanComment() {
302
- const startLine = this.line
303
- const startCol = this.column
304
- let comment = ''
305
-
306
- if (this.peek() === '#') {
307
- this.advance()
308
- } else {
309
- this.advance()
310
- this.advance()
311
- }
312
-
313
- while (!this.isAtEnd() && this.peek() !== '\n') {
314
- comment += this.advance()
315
- }
316
-
317
- if (this.options.trackComments) {
318
- this.tokens.push(new Token(TokenType.COMMENT, comment.trim(), startLine, startCol, this.currentIndent))
319
- }
320
- }
321
-
322
- scanBlockComment() {
323
- const startLine = this.line
324
- const startCol = this.column
325
- let comment = ''
326
-
327
- this.advance()
328
- this.advance()
329
-
330
- while (!this.isAtEnd()) {
331
- if (this.peek() === '*' && this.peek(1) === '/') {
332
- this.advance()
333
- this.advance()
334
- break
335
- }
336
- comment += this.advance()
337
- }
338
-
339
- if (this.options.trackComments) {
340
- this.tokens.push(new Token(TokenType.BLOCK_COMMENT, comment.trim(), startLine, startCol, this.currentIndent))
341
- }
342
- }
343
-
344
- scanString(quote) {
345
- const startLine = this.line
346
- const startCol = this.column
347
- let value = ''
348
- let isBlock = false
349
-
350
- this.advance()
351
-
352
- if (this.peek() === quote && this.peek(1) === quote) {
353
- this.advance()
354
- this.advance()
355
- isBlock = true
356
- }
357
-
358
- while (!this.isAtEnd()) {
359
- if (isBlock) {
360
- if (this.peek() === quote && this.peek(1) === quote && this.peek(2) === quote) {
361
- this.advance()
362
- this.advance()
363
- this.advance()
364
- break
365
- }
366
- } else {
367
- if (this.peek() === quote) {
368
- this.advance()
369
- break
370
- }
371
- if (this.peek() === '\n') {
372
- this.tokens.push(new Token(TokenType.ERROR, 'Chaîne non terminée', startLine, startCol, this.currentIndent))
373
- return
374
- }
375
- }
376
-
377
- if (this.peek() === '\\' && !isBlock) {
378
- this.advance()
379
- const escaped = this.advance()
380
- switch (escaped) {
381
- case 'n': value += '\n'; break
382
- case 't': value += '\t'; break
383
- case 'r': value += '\r'; break
384
- case '\\': value += '\\'; break
385
- case "'": value += "'"; break
386
- case '"': value += '"'; break
387
- case '0': value += '\0'; break
388
- case 'x':
389
- let hex = ''
390
- for (let i = 0; i < 2 && this.isHexDigit(this.peek()); i++) {
391
- hex += this.advance()
392
- }
393
- value += String.fromCharCode(parseInt(hex, 16))
394
- break
395
- case 'u':
396
- let unicode = ''
397
- if (this.peek() === '{') {
398
- this.advance()
399
- while (this.isHexDigit(this.peek())) {
400
- unicode += this.advance()
401
- }
402
- if (this.peek() === '}') this.advance()
403
- } else {
404
- for (let i = 0; i < 4 && this.isHexDigit(this.peek()); i++) {
405
- unicode += this.advance()
406
- }
407
- }
408
- value += String.fromCodePoint(parseInt(unicode, 16))
409
- break
410
- default:
411
- value += escaped
412
- }
413
- } else {
414
- value += this.advance()
415
- }
416
- }
417
-
418
- this.tokens.push(new Token(
419
- isBlock ? TokenType.BLOCK_STRING : TokenType.STRING,
420
- value,
421
- startLine,
422
- startCol,
423
- this.currentIndent
424
- ))
425
- }
426
-
427
- scanTemplateString() {
428
- const startLine = this.line
429
- const startCol = this.column
430
- let value = ''
431
-
432
- this.advance()
433
-
434
- while (!this.isAtEnd() && this.peek() !== '`') {
435
- if (this.peek() === '\\') {
436
- this.advance()
437
- value += this.advance()
438
- } else {
439
- value += this.advance()
440
- }
441
- }
442
-
443
- if (this.peek() === '`') {
444
- this.advance()
445
- }
446
-
447
- this.tokens.push(new Token(TokenType.BLOCK_STRING, value, startLine, startCol, this.currentIndent))
448
- }
449
-
450
- scanNumber() {
451
- const startLine = this.line
452
- const startCol = this.column
453
- let value = ''
454
- let type = TokenType.INTEGER
455
-
456
- if (this.peek() === '-') {
457
- value += this.advance()
458
- }
459
-
460
- if (this.peek() === '0' && (this.peek(1) === 'x' || this.peek(1) === 'X')) {
461
- value += this.advance()
462
- value += this.advance()
463
- while (this.isHexDigit(this.peek())) {
464
- value += this.advance()
465
- }
466
- this.tokens.push(new Token(TokenType.HEX, value, startLine, startCol, this.currentIndent))
467
- return
468
- }
469
-
470
- if (this.peek() === '0' && (this.peek(1) === 'b' || this.peek(1) === 'B')) {
471
- this.advance()
472
- this.advance()
473
- let binValue = ''
474
- while (this.peek() === '0' || this.peek() === '1') {
475
- binValue += this.advance()
476
- }
477
- this.tokens.push(new Token(TokenType.INTEGER, parseInt(binValue, 2), startLine, startCol, this.currentIndent))
478
- return
479
- }
480
-
481
- if (this.peek() === '0' && (this.peek(1) === 'o' || this.peek(1) === 'O')) {
482
- this.advance()
483
- this.advance()
484
- let octValue = ''
485
- while (this.peek() >= '0' && this.peek() <= '7') {
486
- octValue += this.advance()
487
- }
488
- this.tokens.push(new Token(TokenType.INTEGER, parseInt(octValue, 8), startLine, startCol, this.currentIndent))
489
- return
490
- }
491
-
492
- while (this.isDigit(this.peek()) || this.peek() === '_') {
493
- if (this.peek() !== '_') {
494
- value += this.advance()
495
- } else {
496
- this.advance()
497
- }
498
- }
499
-
500
- if (this.peek() === '.' && this.isDigit(this.peek(1))) {
501
- type = TokenType.FLOAT
502
- value += this.advance()
503
- while (this.isDigit(this.peek()) || this.peek() === '_') {
504
- if (this.peek() !== '_') {
505
- value += this.advance()
506
- } else {
507
- this.advance()
508
- }
509
- }
510
- }
511
-
512
- if (this.peek() === 'e' || this.peek() === 'E') {
513
- type = TokenType.FLOAT
514
- value += this.advance()
515
- if (this.peek() === '+' || this.peek() === '-') {
516
- value += this.advance()
517
- }
518
- while (this.isDigit(this.peek())) {
519
- value += this.advance()
520
- }
521
- }
522
-
523
- if (type === TokenType.FLOAT) {
524
- this.tokens.push(new Token(type, parseFloat(value), startLine, startCol, this.currentIndent))
525
- } else {
526
- this.tokens.push(new Token(type, parseInt(value, 10), startLine, startCol, this.currentIndent))
527
- }
528
- }
529
-
530
- scanIdentifier() {
531
- const startLine = this.line
532
- const startCol = this.column
533
- let value = ''
534
-
535
- while (this.isAlphaNumeric(this.peek()) || this.peek() === '-' || this.peek() === '_') {
536
- value += this.advance()
537
- }
538
-
539
- let keepLooking = true
540
- while (keepLooking && this.peek() === ' ') {
541
- const savedPos = this.pos
542
- const savedLine = this.line
543
- const savedCol = this.column
544
-
545
- this.advance()
546
-
547
- let nextWord = ''
548
- while (this.isAlphaNumeric(this.peek()) || this.peek() === '-' || this.peek() === '_') {
549
- nextWord += this.advance()
550
- }
551
-
552
- if (nextWord) {
553
- const combined = value + ' ' + nextWord
554
- if (this.isCompoundKeyword(combined) || this.couldBeCompoundStart(combined)) {
555
- value = combined
556
- } else {
557
- this.pos = savedPos
558
- this.line = savedLine
559
- this.column = savedCol
560
- keepLooking = false
561
- }
562
- } else {
563
- this.pos = savedPos
564
- this.line = savedLine
565
- this.column = savedCol
566
- keepLooking = false
567
- }
568
- }
569
-
570
- const lowerValue = value.toLowerCase()
571
- if (this.peek() === ':' && LANG_BLOCKS.includes(lowerValue)) {
572
- this.advance()
573
- this.tokens.push(new Token(TokenType.LANG_BLOCK, lowerValue, startLine, startCol, this.currentIndent))
574
- return
575
- }
576
-
577
- this.tokens.push(new Token(TokenType.IDENTIFIER, value, startLine, startCol, this.currentIndent))
578
- }
579
-
580
- couldBeCompoundStart(partial) {
581
- const normalized = this.normalizeAccents(partial)
582
- const compounds = [
583
- 'retour a la ligne', 'a la soumission', 'a la reinitialisation',
584
- 'inferieur ou egal', 'superieur ou egal',
585
- 'gauche a droite', 'droite a gauche',
586
- 'mettre a jour', 'case a cocher'
587
- ]
588
- return compounds.some(c => c.startsWith(normalized + ' '))
589
- }
590
-
591
- normalizeAccents(str) {
592
- const accentsMap = {
593
- 'à': 'a', 'â': 'a', 'ä': 'a', 'á': 'a',
594
- 'è': 'e', 'ê': 'e', 'ë': 'e', 'é': 'e',
595
- 'ì': 'i', 'î': 'i', 'ï': 'i', 'í': 'i',
596
- 'ò': 'o', 'ô': 'o', 'ö': 'o', 'ó': 'o',
597
- 'ù': 'u', 'û': 'u', 'ü': 'u', 'ú': 'u',
598
- 'ç': 'c', 'ñ': 'n'
599
- }
600
- return str.toLowerCase().split('').map(c => accentsMap[c] || c).join('')
601
- }
602
-
603
- isCompoundKeyword(phrase) {
604
- const normalized = this.normalizeAccents(phrase)
605
- const compounds = [
606
- 'en ligne', 'hors ligne', 'au survol', 'au clic', 'au focus',
607
- 'au double clic', 'au changement', 'a la soumission',
608
- 'retour a la ligne', 'lecture seule', 'zone texte',
609
- 'case a cocher', 'bouton radio', 'premiere lettre',
610
- 'premiere ligne', 'inferieur ou egal',
611
- 'superieur ou egal',
612
- 'espace de noms', 'element liste', 'racine carree',
613
- 'nouvelle fenetre', 'gauche a droite',
614
- 'droite a gauche',
615
- 'definir defaut', 'mettre a jour',
616
- 'cle primaire', 'cle etrangere',
617
- 'non nul', 'par defaut',
618
- 'au focus dans', 'pointeur bas', 'pointeur haut',
619
- 'obtenir contenu', 'erreur type', 'erreur syntaxe',
620
- 'nettoyer gauche', 'nettoyer droite', 'vers date',
621
- 'si null', 'creer role',
622
- 'a la reinitialisation'
623
- ]
624
- return compounds.includes(normalized)
625
- }
626
-
627
- scanOperator() {
628
- const startLine = this.line
629
- const startCol = this.column
630
- const char = this.advance()
631
-
632
- switch (char) {
633
- case ':':
634
- if (this.match(':')) {
635
- this.tokens.push(new Token(TokenType.DOUBLE_COLON, '::', startLine, startCol, this.currentIndent))
636
- } else {
637
- this.tokens.push(new Token(TokenType.COLON, ':', startLine, startCol, this.currentIndent))
638
- }
639
- break
640
-
641
- case '=':
642
- if (this.match('=')) {
643
- if (this.match('=')) {
644
- this.tokens.push(new Token(TokenType.DOUBLE_EQUALS, '===', startLine, startCol, this.currentIndent))
645
- } else {
646
- this.tokens.push(new Token(TokenType.DOUBLE_EQUALS, '==', startLine, startCol, this.currentIndent))
647
- }
648
- } else if (this.match('>')) {
649
- this.tokens.push(new Token(TokenType.FAT_ARROW, '=>', startLine, startCol, this.currentIndent))
650
- } else {
651
- this.tokens.push(new Token(TokenType.EQUALS, '=', startLine, startCol, this.currentIndent))
652
- }
653
- break
654
-
655
- case '!':
656
- if (this.match('=')) {
657
- if (this.match('=')) {
658
- this.tokens.push(new Token(TokenType.NOT_EQUALS, '!==', startLine, startCol, this.currentIndent))
659
- } else {
660
- this.tokens.push(new Token(TokenType.NOT_EQUALS, '!=', startLine, startCol, this.currentIndent))
661
- }
662
- } else {
663
- this.tokens.push(new Token(TokenType.BANG, '!', startLine, startCol, this.currentIndent))
664
- }
665
- break
666
-
667
- case ',':
668
- this.tokens.push(new Token(TokenType.COMMA, ',', startLine, startCol, this.currentIndent))
669
- break
670
-
671
- case '.':
672
- if (this.match('.')) {
673
- if (this.match('.')) {
674
- this.tokens.push(new Token(TokenType.SPREAD, '...', startLine, startCol, this.currentIndent))
675
- } else {
676
- this.tokens.push(new Token(TokenType.DOT, '.', startLine, startCol, this.currentIndent))
677
- this.tokens.push(new Token(TokenType.DOT, '.', startLine, startCol + 1, this.currentIndent))
678
- }
679
- } else {
680
- this.tokens.push(new Token(TokenType.DOT, '.', startLine, startCol, this.currentIndent))
681
- }
682
- break
683
-
684
- case '+':
685
- if (this.match('+')) {
686
- this.tokens.push(new Token(TokenType.PLUS, '++', startLine, startCol, this.currentIndent))
687
- } else if (this.match('=')) {
688
- this.tokens.push(new Token(TokenType.PLUS, '+=', startLine, startCol, this.currentIndent))
689
- } else {
690
- this.tokens.push(new Token(TokenType.PLUS, '+', startLine, startCol, this.currentIndent))
691
- }
692
- break
693
-
694
- case '-':
695
- if (this.match('-')) {
696
- this.tokens.push(new Token(TokenType.MINUS, '--', startLine, startCol, this.currentIndent))
697
- } else if (this.match('>')) {
698
- this.tokens.push(new Token(TokenType.ARROW, '->', startLine, startCol, this.currentIndent))
699
- } else if (this.match('=')) {
700
- this.tokens.push(new Token(TokenType.MINUS, '-=', startLine, startCol, this.currentIndent))
701
- } else {
702
- this.tokens.push(new Token(TokenType.MINUS, '-', startLine, startCol, this.currentIndent))
703
- }
704
- break
705
-
706
- case '*':
707
- if (this.match('*')) {
708
- if (this.match('=')) {
709
- this.tokens.push(new Token(TokenType.DOUBLE_STAR, '**=', startLine, startCol, this.currentIndent))
710
- } else {
711
- this.tokens.push(new Token(TokenType.DOUBLE_STAR, '**', startLine, startCol, this.currentIndent))
712
- }
713
- } else if (this.match('=')) {
714
- this.tokens.push(new Token(TokenType.STAR, '*=', startLine, startCol, this.currentIndent))
715
- } else {
716
- this.tokens.push(new Token(TokenType.STAR, '*', startLine, startCol, this.currentIndent))
717
- }
718
- break
719
-
720
- case '/':
721
- if (this.match('=')) {
722
- this.tokens.push(new Token(TokenType.SLASH, '/=', startLine, startCol, this.currentIndent))
723
- } else if (this.match('/')) {
724
- this.tokens.push(new Token(TokenType.DOUBLE_SLASH, '//', startLine, startCol, this.currentIndent))
725
- } else {
726
- this.tokens.push(new Token(TokenType.SLASH, '/', startLine, startCol, this.currentIndent))
727
- }
728
- break
729
-
730
- case '%':
731
- if (this.match('=')) {
732
- this.tokens.push(new Token(TokenType.PERCENT, '%=', startLine, startCol, this.currentIndent))
733
- } else {
734
- this.tokens.push(new Token(TokenType.PERCENT, '%', startLine, startCol, this.currentIndent))
735
- }
736
- break
737
-
738
- case '<':
739
- if (this.match('=')) {
740
- if (this.match('>')) {
741
- this.tokens.push(new Token(TokenType.SPACESHIP, '<=>', startLine, startCol, this.currentIndent))
742
- } else {
743
- this.tokens.push(new Token(TokenType.LTE, '<=', startLine, startCol, this.currentIndent))
744
- }
745
- } else if (this.match('<')) {
746
- this.tokens.push(new Token(TokenType.LT, '<<', startLine, startCol, this.currentIndent))
747
- } else {
748
- this.tokens.push(new Token(TokenType.LT, '<', startLine, startCol, this.currentIndent))
749
- }
750
- break
751
-
752
- case '>':
753
- if (this.match('=')) {
754
- this.tokens.push(new Token(TokenType.GTE, '>=', startLine, startCol, this.currentIndent))
755
- } else if (this.match('>')) {
756
- if (this.match('>')) {
757
- this.tokens.push(new Token(TokenType.GT, '>>>', startLine, startCol, this.currentIndent))
758
- } else {
759
- this.tokens.push(new Token(TokenType.GT, '>>', startLine, startCol, this.currentIndent))
760
- }
761
- } else {
762
- this.tokens.push(new Token(TokenType.GT, '>', startLine, startCol, this.currentIndent))
763
- }
764
- break
765
-
766
- case '&':
767
- if (this.match('&')) {
768
- this.tokens.push(new Token(TokenType.DOUBLE_AMPERSAND, '&&', startLine, startCol, this.currentIndent))
769
- } else if (this.match('=')) {
770
- this.tokens.push(new Token(TokenType.AMPERSAND, '&=', startLine, startCol, this.currentIndent))
771
- } else {
772
- this.tokens.push(new Token(TokenType.AMPERSAND, '&', startLine, startCol, this.currentIndent))
773
- }
774
- break
775
-
776
- case '|':
777
- if (this.match('|')) {
778
- this.tokens.push(new Token(TokenType.DOUBLE_PIPE, '||', startLine, startCol, this.currentIndent))
779
- } else if (this.match('=')) {
780
- this.tokens.push(new Token(TokenType.PIPE, '|=', startLine, startCol, this.currentIndent))
781
- } else if (this.match('>')) {
782
- this.tokens.push(new Token(TokenType.PIPE, '|>', startLine, startCol, this.currentIndent))
783
- } else {
784
- this.tokens.push(new Token(TokenType.PIPE, '|', startLine, startCol, this.currentIndent))
785
- }
786
- break
787
-
788
- case '^':
789
- if (this.match('=')) {
790
- this.tokens.push(new Token(TokenType.CARET, '^=', startLine, startCol, this.currentIndent))
791
- } else {
792
- this.tokens.push(new Token(TokenType.CARET, '^', startLine, startCol, this.currentIndent))
793
- }
794
- break
795
-
796
- case '~':
797
- this.tokens.push(new Token(TokenType.TILDE, '~', startLine, startCol, this.currentIndent))
798
- break
799
-
800
- case '?':
801
- if (this.match('?')) {
802
- if (this.match('=')) {
803
- this.tokens.push(new Token(TokenType.QUESTION, '??=', startLine, startCol, this.currentIndent))
804
- } else {
805
- this.tokens.push(new Token(TokenType.QUESTION, '??', startLine, startCol, this.currentIndent))
806
- }
807
- } else if (this.match('.')) {
808
- this.tokens.push(new Token(TokenType.QUESTION, '?.', startLine, startCol, this.currentIndent))
809
- } else {
810
- this.tokens.push(new Token(TokenType.QUESTION, '?', startLine, startCol, this.currentIndent))
811
- }
812
- break
813
-
814
- case '@':
815
- this.tokens.push(new Token(TokenType.AT, '@', startLine, startCol, this.currentIndent))
816
- break
817
-
818
- case '#':
819
- this.tokens.push(new Token(TokenType.HASH, '#', startLine, startCol, this.currentIndent))
820
- break
821
-
822
- case '\\':
823
- this.tokens.push(new Token(TokenType.BACKSLASH, '\\', startLine, startCol, this.currentIndent))
824
- break
825
-
826
- case '(':
827
- this.tokens.push(new Token(TokenType.LPAREN, '(', startLine, startCol, this.currentIndent))
828
- break
829
-
830
- case ')':
831
- this.tokens.push(new Token(TokenType.RPAREN, ')', startLine, startCol, this.currentIndent))
832
- break
833
-
834
- case '[':
835
- this.tokens.push(new Token(TokenType.LBRACKET, '[', startLine, startCol, this.currentIndent))
836
- break
837
-
838
- case ']':
839
- this.tokens.push(new Token(TokenType.RBRACKET, ']', startLine, startCol, this.currentIndent))
840
- break
841
-
842
- case '{':
843
- this.tokens.push(new Token(TokenType.LBRACE, '{', startLine, startCol, this.currentIndent))
844
- break
845
-
846
- case '}':
847
- this.tokens.push(new Token(TokenType.RBRACE, '}', startLine, startCol, this.currentIndent))
848
- break
849
-
850
- case ';':
851
- break
852
-
853
- default:
854
- this.tokens.push(new Token(TokenType.ERROR, `Caractère inattendu: ${char}`, startLine, startCol, this.currentIndent))
855
- }
856
- }
857
-
858
- static tokenize(source, options = {}) {
859
- const lexer = new EtherLexer(source, options)
860
- return lexer.tokenize()
861
- }
862
- }
863
-
864
- module.exports = {
865
- EtherLexer,
866
- Token,
867
- TokenType,
868
- LANG_BLOCKS
869
- }