ether-code 0.4.5 → 0.4.7

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.
package/cli/ether.js CHANGED
@@ -6,7 +6,7 @@ const http = require('http')
6
6
  const { EtherCompiler } = require('./compiler')
7
7
  const { Watcher } = require('./watcher')
8
8
 
9
- const VERSION = '0.4.5'
9
+ const VERSION = '0.4.7'
10
10
 
11
11
  const COLORS = {
12
12
  reset: '\x1b[0m',
package/ether-parser.js CHANGED
@@ -11,6 +11,206 @@ class EtherParser {
11
11
  this.targetLang = options.targetLang || 'auto'
12
12
 
13
13
  this.loadAllI18n(options.i18nDir || './i18n')
14
+ this.initCompoundTerms()
15
+ }
16
+
17
+ initCompoundTerms() {
18
+ this.compoundOperators = {
19
+ 'strictement egal': '===',
20
+ 'strictement égal': '===',
21
+ 'strictement different': '!==',
22
+ 'strictement différent': '!==',
23
+ 'superieur ou egal': '>=',
24
+ 'supérieur ou égal': '>=',
25
+ 'inferieur ou egal': '<=',
26
+ 'inférieur ou égal': '<=',
27
+ 'coalescence nulle': '??',
28
+ 'chainage optionnel': '?.',
29
+ 'chaînage optionnel': '?.'
30
+ }
31
+
32
+ this.compoundKeywords = {
33
+ 'sinon si': 'else if',
34
+ 'tant que': 'while',
35
+ 'pour chaque': 'forEach',
36
+ 'fonction asynchrone': 'async function',
37
+ 'fonction async': 'async function',
38
+ 'fonction generatrice': 'function*',
39
+ 'fonction génératrice': 'function*',
40
+ 'variable globale': 'var'
41
+ }
42
+
43
+ this.jsTranslations = {
44
+ 'variable': 'let',
45
+ 'constante': 'const',
46
+ 'fonction': 'function',
47
+ 'retourner': 'return',
48
+ 'si': 'if',
49
+ 'sinon': 'else',
50
+ 'pour': 'for',
51
+ 'de': 'of',
52
+ 'dans': 'in',
53
+ 'selon': 'switch',
54
+ 'cas': 'case',
55
+ 'defaut': 'default',
56
+ 'sortir': 'break',
57
+ 'continuer': 'continue',
58
+ 'essayer': 'try',
59
+ 'attraper': 'catch',
60
+ 'finalement': 'finally',
61
+ 'lancer': 'throw',
62
+ 'nouveau': 'new',
63
+ 'supprimer': 'delete',
64
+ 'vrai': 'true',
65
+ 'faux': 'false',
66
+ 'nul': 'null',
67
+ 'indefini': 'undefined',
68
+ 'ceci': 'this',
69
+ 'classe': 'class',
70
+ 'etendre': 'extends',
71
+ 'super': 'super',
72
+ 'constructeur': 'constructor',
73
+ 'statique': 'static',
74
+ 'obtenir': 'get',
75
+ 'definir': 'set',
76
+ 'asynchrone': 'async',
77
+ 'attendre': 'await',
78
+ 'importer': 'import',
79
+ 'exporter': 'export',
80
+ 'depuis': 'from',
81
+ 'comme': 'as',
82
+ 'addition': '+',
83
+ 'soustraction': '-',
84
+ 'multiplication': '*',
85
+ 'division': '/',
86
+ 'modulo': '%',
87
+ 'puissance': '**',
88
+ 'increment': '++',
89
+ 'decrement': '--',
90
+ 'egal': '==',
91
+ 'different': '!=',
92
+ 'superieur': '>',
93
+ 'inferieur': '<',
94
+ 'et': '&&',
95
+ 'ou': '||',
96
+ 'non': '!',
97
+ 'document': 'document',
98
+ 'fenetre': 'window',
99
+ 'console': 'console',
100
+ 'journal': 'console.log',
101
+ 'erreur': 'console.error',
102
+ 'avertir': 'console.warn',
103
+ 'info': 'console.info',
104
+ 'promesse': 'Promise',
105
+ 'resoudre': 'resolve',
106
+ 'rejeter': 'reject',
107
+ 'alors': 'then',
108
+ 'tout': 'all',
109
+ 'course': 'race',
110
+ 'json': 'JSON',
111
+ 'serialiser': 'stringify',
112
+ 'analyser': 'parse',
113
+ 'math': 'Math',
114
+ 'aleatoire': 'random',
115
+ 'arrondir': 'round',
116
+ 'plancher': 'floor',
117
+ 'plafond': 'ceil',
118
+ 'absolu': 'abs',
119
+ 'maximum': 'max',
120
+ 'minimum': 'min',
121
+ 'date': 'Date',
122
+ 'maintenant': 'now',
123
+ 'carte': 'Map',
124
+ 'ensemble': 'Set',
125
+ 'symbole': 'Symbol',
126
+ 'objet': 'Object',
127
+ 'selecteur': 'querySelector',
128
+ 'sur': 'addEventListener',
129
+ 'longueur': 'length',
130
+ 'taille': 'size',
131
+ 'recuperer': 'fetch',
132
+ 'transformer': 'map',
133
+ 'filtrer': 'filter',
134
+ 'reduire': 'reduce',
135
+ 'trouver': 'find',
136
+ 'certains': 'some',
137
+ 'tous': 'every',
138
+ 'inclut': 'includes',
139
+ 'joindre': 'join',
140
+ 'inverser': 'reverse',
141
+ 'trier': 'sort',
142
+ 'decouper': 'slice',
143
+ 'concatener': 'concat',
144
+ 'ajouter': 'push',
145
+ 'retirer': 'pop',
146
+ 'diviser': 'split',
147
+ 'remplacer': 'replace',
148
+ 'rogner': 'trim',
149
+ 'repeter': 'repeat'
150
+ }
151
+ }
152
+
153
+ normalizeAccents(str) {
154
+ return str.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '')
155
+ }
156
+
157
+ tryMatchCompoundOperator() {
158
+ const current = this.current()
159
+ if (!current || current.type !== TokenType.IDENTIFIER) return null
160
+
161
+ const val1 = this.normalizeAccents(String(current.value))
162
+ const next = this.peek(1)
163
+ const next2 = this.peek(2)
164
+
165
+ if (next && next.type === TokenType.IDENTIFIER) {
166
+ const val2 = this.normalizeAccents(String(next.value))
167
+
168
+ if (next2 && next2.type === TokenType.IDENTIFIER) {
169
+ const val3 = this.normalizeAccents(String(next2.value))
170
+ const compound3 = `${val1} ${val2} ${val3}`
171
+ if (this.compoundOperators[compound3]) {
172
+ this.advance()
173
+ this.advance()
174
+ this.advance()
175
+ return this.compoundOperators[compound3]
176
+ }
177
+ }
178
+
179
+ const compound2 = `${val1} ${val2}`
180
+ if (this.compoundOperators[compound2]) {
181
+ this.advance()
182
+ this.advance()
183
+ return this.compoundOperators[compound2]
184
+ }
185
+ }
186
+
187
+ return null
188
+ }
189
+
190
+ tryMatchCompoundKeyword() {
191
+ const current = this.current()
192
+ if (!current || current.type !== TokenType.IDENTIFIER) return null
193
+
194
+ const val1 = this.normalizeAccents(String(current.value))
195
+ const next = this.peek(1)
196
+
197
+ if (next && next.type === TokenType.IDENTIFIER) {
198
+ const val2 = this.normalizeAccents(String(next.value))
199
+ const compound2 = `${val1} ${val2}`
200
+ if (this.compoundKeywords[compound2]) {
201
+ this.advance()
202
+ this.advance()
203
+ return this.compoundKeywords[compound2]
204
+ }
205
+ }
206
+
207
+ return null
208
+ }
209
+
210
+ translateJSIdentifier(word) {
211
+ if (!word) return word
212
+ const lower = this.normalizeAccents(String(word))
213
+ return this.jsTranslations[lower] || word
14
214
  }
15
215
 
16
216
  loadAllI18n(dir) {
@@ -1153,7 +1353,14 @@ class EtherParser {
1153
1353
  return this.parseExport(lang)
1154
1354
  }
1155
1355
 
1156
- return this.parseExpression(lang)
1356
+ const expr = this.parseExpression(lang)
1357
+ if (expr) {
1358
+ return {
1359
+ type: 'ExpressionStatement',
1360
+ expression: expr
1361
+ }
1362
+ }
1363
+ return null
1157
1364
  }
1158
1365
 
1159
1366
  isVariableDeclaration(value) {
@@ -1717,6 +1924,13 @@ class EtherParser {
1717
1924
  let left = this.parseComparison(lang)
1718
1925
 
1719
1926
  while (true) {
1927
+ const compoundOp = this.tryMatchCompoundOperator()
1928
+ if (compoundOp === '===' || compoundOp === '!==') {
1929
+ const right = this.parseComparison(lang)
1930
+ left = { type: 'BinaryExpression', operator: compoundOp, left, right }
1931
+ continue
1932
+ }
1933
+
1720
1934
  if (this.match(TokenType.DOUBLE_EQUALS) || this.matchValue('egal') || this.matchValue('egale')) {
1721
1935
  const right = this.parseComparison(lang)
1722
1936
  left = { type: 'BinaryExpression', operator: '===', left, right }
@@ -1735,16 +1949,23 @@ class EtherParser {
1735
1949
  let left = this.parseAdditive(lang)
1736
1950
 
1737
1951
  while (true) {
1952
+ const compoundOp = this.tryMatchCompoundOperator()
1953
+ if (compoundOp === '>=' || compoundOp === '<=') {
1954
+ const right = this.parseAdditive(lang)
1955
+ left = { type: 'BinaryExpression', operator: compoundOp, left, right }
1956
+ continue
1957
+ }
1958
+
1738
1959
  if (this.match(TokenType.LT) || this.matchValue('inferieur')) {
1739
1960
  const right = this.parseAdditive(lang)
1740
1961
  left = { type: 'BinaryExpression', operator: '<', left, right }
1741
1962
  } else if (this.match(TokenType.GT) || this.matchValue('superieur')) {
1742
1963
  const right = this.parseAdditive(lang)
1743
1964
  left = { type: 'BinaryExpression', operator: '>', left, right }
1744
- } else if (this.match(TokenType.LTE) || this.matchValue('inferieur ou egal')) {
1965
+ } else if (this.match(TokenType.LTE)) {
1745
1966
  const right = this.parseAdditive(lang)
1746
1967
  left = { type: 'BinaryExpression', operator: '<=', left, right }
1747
- } else if (this.match(TokenType.GTE) || this.matchValue('superieur ou egal')) {
1968
+ } else if (this.match(TokenType.GTE)) {
1748
1969
  const right = this.parseAdditive(lang)
1749
1970
  left = { type: 'BinaryExpression', operator: '>=', left, right }
1750
1971
  } else {
@@ -1759,10 +1980,10 @@ class EtherParser {
1759
1980
  let left = this.parseMultiplicative(lang)
1760
1981
 
1761
1982
  while (true) {
1762
- if (this.match(TokenType.PLUS) || this.matchValue('plus')) {
1983
+ if (this.match(TokenType.PLUS) || this.matchValue('plus') || this.matchValue('addition')) {
1763
1984
  const right = this.parseMultiplicative(lang)
1764
1985
  left = { type: 'BinaryExpression', operator: '+', left, right }
1765
- } else if (this.match(TokenType.MINUS) || this.matchValue('moins')) {
1986
+ } else if (this.match(TokenType.MINUS) || this.matchValue('moins') || this.matchValue('soustraction')) {
1766
1987
  const right = this.parseMultiplicative(lang)
1767
1988
  left = { type: 'BinaryExpression', operator: '-', left, right }
1768
1989
  } else {
@@ -1777,10 +1998,10 @@ class EtherParser {
1777
1998
  let left = this.parseUnary(lang)
1778
1999
 
1779
2000
  while (true) {
1780
- if (this.match(TokenType.STAR) || this.matchValue('fois') || this.matchValue('multiplie')) {
2001
+ if (this.match(TokenType.STAR) || this.matchValue('fois') || this.matchValue('multiplie') || this.matchValue('multiplication')) {
1781
2002
  const right = this.parseUnary(lang)
1782
2003
  left = { type: 'BinaryExpression', operator: '*', left, right }
1783
- } else if (this.match(TokenType.SLASH) || this.matchValue('divise')) {
2004
+ } else if (this.match(TokenType.SLASH) || this.matchValue('divise') || this.matchValue('division')) {
1784
2005
  const right = this.parseUnary(lang)
1785
2006
  left = { type: 'BinaryExpression', operator: '/', left, right }
1786
2007
  } else if (this.match(TokenType.PERCENT) || this.matchValue('modulo')) {
@@ -1823,7 +2044,7 @@ class EtherParser {
1823
2044
  const property = this.current()
1824
2045
  if (property && property.type === TokenType.IDENTIFIER) {
1825
2046
  this.advance()
1826
- expr = { type: 'MemberExpression', object: expr, property: property.value }
2047
+ expr = { type: 'MemberExpression', object: expr, property: { type: 'Identifier', name: property.value } }
1827
2048
  }
1828
2049
  } else if (this.match(TokenType.LBRACKET)) {
1829
2050
  const index = this.parseExpression(lang)
@@ -1877,8 +2098,19 @@ class EtherParser {
1877
2098
  return { type: 'Literal', value: undefined }
1878
2099
  }
1879
2100
 
2101
+ const translated = this.translateJSIdentifier(token.value)
1880
2102
  this.advance()
1881
- return { type: 'Identifier', name: token.value }
2103
+
2104
+ if (translated && translated.includes('.')) {
2105
+ const parts = translated.split('.')
2106
+ let expr = { type: 'Identifier', name: parts[0] }
2107
+ for (let i = 1; i < parts.length; i++) {
2108
+ expr = { type: 'MemberExpression', object: expr, property: { type: 'Identifier', name: parts[i] } }
2109
+ }
2110
+ return expr
2111
+ }
2112
+
2113
+ return { type: 'Identifier', name: translated || token.value }
1882
2114
  }
1883
2115
 
1884
2116
  if (token.type === TokenType.LBRACKET) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ether-code",
3
- "version": "0.4.5",
3
+ "version": "0.4.7",
4
4
  "description": "Ether - Le langage intentionnel",
5
5
  "main": "cli/compiler.js",
6
6
  "bin": {