-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathрускрипт.js
286 lines (248 loc) · 16.4 KB
/
рускрипт.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
class Рускрипт {
ошибки_рускрипта = {
не_существующая_команда: "Указана неизвестная команда: «%команда%».",
нет_содержимого: "В конструкторе класса рускрипт не передан код для компиляции.",
не_существующий_модификатор: "Указан несуществующий модификатор: «%модификатор%».",
пустое_условие: "Указано пустое условие в блоке «Если, то».",
большое_исполнение: "Указано более одной команды в исходе в блоке «Если, то».",
не_поддерживаемое_значение: "Передано не поддерживаемое значение: %значение%. Текущие поддерживаемые значения: %поддерживаемые_значения%"
};
команды_рускрипта = {
переменные: {
объявление: /^Объявить переменную (\S+)(.*)$/ui,
чтение: /^Прочитать значение переменной (\S+)(.*)$/ui
},
ввод: {
чтение: /^Прочитать ввод(.*)$/ui,
примитивы: /^Взять значение ((Да|Нет)|(\d+)|«(.*?)»)(.*)$/ui
},
условие: {
проверка: /^Если \((.*?)\), то \((.*?)\)(, иначе \((.*?)\))?$/ui
}
}
модификаторы_рускрипта = {
записать_в_переменную: /^ ?( и)? записать в переменную (\S+)(.*)$/ui,
вывести_на_экран: /^( и)? вывести на экран(.*)$/ui,
вывести_в_журнал: /^( и)? вывести в журнал(.*)$/ui,
прибавить: /^( и)? прибавить («.*?»|\d+|Да|Нет|значение переменной \S+)((?=( и))(.*))?$/ui,
вычесть: /^( и)? вычесть («.*?»|\d+|Да|Нет|значение переменной \S+)((?=( и))(.*))?$/ui,
умножить: /^( и)? умножить на («.*?»|\d+|Да|Нет|значение переменной \S+)((?=( и))(.*))?$/ui,
поделить: /^( и)? поделить на («.*?»|\d+|Да|Нет|значение переменной \S+)((?=( и))(.*))?$/ui,
остаток_от_деления: /^( и)? определить остаток от деления на («.*?»|\d+|Да|Нет|значение переменной \S+)((?=( и))(.*))?$/ui,
перевести_в_число: /^( и)? перевести в число((?=( и))(.*))?$/ui,
перевести_в_строку: /^( и)? перевести в строку((?=( и))(.*))?$/ui,
вид_переменной: /^( и)? определить вид((?=( и))(.*))?$/ui,
равняется_ли: /^( и)? определить равняется ли (.+?)((?=( и))(.*))?$/ui,
заменить: /^( и)? заменить «?(.+?)»? на «?(.+?)»?((?=( и))(.*))?$/ui
}
примитив_строки_выражение = /^«(.*)»$/ui;
примитив_число_выражение = /^\d+$/;
примитив_логическое_выражение = /^(Да|Нет)$/ui;
примитив_в_переменную = /^значение переменной (\S+)$/ui
_временно = undefined;
_переменные = {};
ввод = [];
ввод_индекс = 0;
вывод = [];
поддерживаемые_значения = "Строка — «Пример», Целое число — 100, Логическое значение — Да — Нет"
игнорировать_вывод_на_экран = false;
constructor(содержимое, ввод = [], игнорировать_вывод_на_экран = false) {
this.ввод = ввод;
this.ввод_индекс = 0;
this.игнорировать_вывод_на_экран = игнорировать_вывод_на_экран;
this.обработать(содержимое);
}
обработать(содержимое) {
if(!содержимое || !содержимое.length) { throw this.ошибки_рускрипта.нет_содержимого; }
содержимое = содержимое.replace(/\n/guim, "");
содержимое = содержимое.replace(/(\/\*(.|[^.])*?\*\/)/guim, "")
let команды = содержимое.split(/((?<!\/)\.\s*)+/guim);
команды = команды.map(команда => команда.replace(/\/\./gium, '.'))
команды = команды.filter(команда => команда !== "");
команды = команды.filter(команда => !/^\.\s*$/gium.test(команда))
if(!команды || !команды.length) { throw this.ошибки_рускрипта.нет_содержимого; }
команды.forEach(команда => {
this.обработать_команду(команда)
this._временно = undefined;
});
}
обработать_команду(команда) {
if(this.команды_рускрипта.ввод.чтение.test(команда)){
let [,модификаторы] = this.команды_рускрипта.ввод.чтение.exec(команда);
let ответ_пользователя = this.прочитать_ввод();
if(ответ_пользователя === null){
ответ_пользователя = ""
}
this._временно = ответ_пользователя
this.обработать_модификаторы(модификаторы)
} else if (this.команды_рускрипта.ввод.примитивы.test(команда)){
let [,значение,,,,модификаторы] = this.команды_рускрипта.ввод.примитивы.exec(команда);
this._временно = this.преобразовать_значение(значение)
this.обработать_модификаторы(модификаторы)
} else if (this.команды_рускрипта.переменные.объявление.test(команда)){
let [,название_переменной,модификаторы] = this.команды_рускрипта.переменные.объявление.exec(команда)
this._переменные[название_переменной] = undefined;
this._временно = undefined;
this.обработать_модификаторы(модификаторы)
} else if (this.команды_рускрипта.переменные.чтение.test(команда)){
let [,название_переменной,модификаторы] = this.команды_рускрипта.переменные.чтение.exec(команда)
this._временно = this._переменные[название_переменной];
this.обработать_модификаторы(модификаторы)
} else if (this.команды_рускрипта.условие.проверка.test(команда)){
let [,условие,то,,иначе] = this.команды_рускрипта.условие.проверка.exec(команда)
if(условие === "" || условие === undefined) {
throw this.ошибки_рускрипта.пустое_условие;
}
this.обработать_команду(условие);
if(this.преобразовать_значение(this._временно)){
if(условие.split(".").length > 1){
throw this.ошибки_рускрипта.большое_исполнение;
}
this.обработать_команду(то)
} else {
if(иначе !== undefined && иначе !== ""){
if(иначе.split(".").length > 1){
throw this.ошибки_рускрипта.большое_исполнение;
}
this.обработать_команду(иначе)
}
}
} else {
throw this.ошибки_рускрипта.не_существующая_команда.replace("%команда%", команда);
}
}
прочитать_ввод(){
let ввод = this.ввод[this.ввод_индекс]
if(ввод === undefined){
return prompt()
}
this.ввод_индекс++;
/* на будущее: не использовать ввод || prompt() из-за evaluating */
return ввод
}
преобразовать_значение(значение, преобразовать_логическое_значение = true){
switch(this.определить_вид(значение)){
case "«Строка»":
return значение.slice(1,-1);
case "«Число»":
return Number(значение)
case "«Логическое значение»":
if(typeof значение == "string" && преобразовать_логическое_значение){
return "да"==значение.toLowerCase()
} else {
return значение
}
}
}
определить_вид(значение){
if(this.примитив_число_выражение.test(значение)){
return "«Число»"
} else if (this.примитив_логическое_выражение.test(значение) || typeof значение === "boolean") {
return "«Логическое значение»"
} else if (typeof значение === "string") {
return "«Строка»"
} else {
throw this.ошибки_рускрипта.не_поддерживаемое_значение.replace("%значение%", значение).replace("%поддерживаемые_значения%", this.поддерживаемые_значения);
}
}
обработать_модификаторы(модификаторы){
if(модификаторы === "" || модификаторы === undefined) { return; }
let модификаторы_рускрипта = Object.keys(this.модификаторы_рускрипта);
let модификатор, выражение_модификатора = null;
for (let i = 0; i < модификаторы_рускрипта.length; i++) {
модификатор = модификаторы_рускрипта[i]
выражение_модификатора = this.модификаторы_рускрипта[модификатор]
if(выражение_модификатора.test(модификаторы)){
break;
} else {
модификатор = null;
выражение_модификатора = null;
}
}
switch(модификатор){
case "вывести_на_экран":
let вывод = this._временно;
if(!this.игнорировать_вывод_на_экран){
this.вывод.push(вывод)
alert(вывод);
}
break;
case "вывести_в_журнал":
let _вывод = this._временно;
this.вывод.push(_вывод)
console.log(_вывод);
break;
case "записать_в_переменную":
var [,,название_переменной] = выражение_модификатора.exec(модификаторы)
this._переменные[название_переменной] = this._временно;
break;
case "прибавить":
var [,,значение,последующие_модификаторы] = выражение_модификатора.exec(модификаторы)
this._временно += this.преобразовать_значение_для_операции(значение)
break;
case "вычесть":
var [,,значение,последующие_модификаторы] = выражение_модификатора.exec(модификаторы)
this._временно -= this.преобразовать_значение_для_операции(значение)
break;
case "умножить":
var [,,значение,последующие_модификаторы] = выражение_модификатора.exec(модификаторы)
this._временно *= this.преобразовать_значение_для_операции(значение)
break;
case "поделить":
var [,,значение,последующие_модификаторы] = выражение_модификатора.exec(модификаторы)
this._временно /= this.преобразовать_значение_для_операции(значение)
break;
case "перевести_в_число":
var [,,последующие_модификаторы] = выражение_модификатора.exec(модификаторы)
let числовое_значение = parseInt(this._временно)
if(!isNaN(числовое_значение)){
this._временно = числовое_значение
}
break;
case "перевести_в_строку":
var [,,последующие_модификаторы] = выражение_модификатора.exec(модификаторы)
this._временно = String(this._временно)
break;
case "вид_переменной":
var [,,последующие_модификаторы] = выражение_модификатора.exec(модификаторы)
this._временно = this.определить_вид(this._временно)
break;
case "равняется_ли":
var [,,предположение,последующие_модификаторы] = выражение_модификатора.exec(модификаторы)
let первое_сравнение = this.преобразовать_значение(this._временно, false);
let второе_сравнение = this.преобразовать_значение(предположение, false);
this._временно = первое_сравнение==второе_сравнение
break;
case "остаток_от_деления":
var [,,делитель,последующие_модификаторы] = выражение_модификатора.exec(модификаторы)
this._временно %= this.преобразовать_значение_для_операции(делитель)
break;
case "заменить":
var [,,что,на_что,последующие_модификаторы] = выражение_модификатора.exec(модификаторы)
что = this.преобразовать_значение_для_операции(что)
на_что = this.преобразовать_значение_для_операции(на_что)
if(typeof this._временно == "string"){
this._временно = this._временно.replace(что,на_что)
}
break;
default:
throw this.ошибки_рускрипта.не_существующий_модификатор.replace("%модификатор%", модификаторы);
break;
}
this.обработать_модификаторы(последующие_модификаторы);
}
преобразовать_значение_для_операции(значение) {
if(this.примитив_в_переменную.test(значение)){
let [,название_переменной] = this.примитив_в_переменную.exec(значение)
return this._переменные[название_переменной]
} else if(this.определить_вид(значение) == "«Число»") {
return Number(значение)
} else if(this.примитив_строки_выражение.test(значение)) {
return this.примитив_строки_выражение.exec(значение)[1];
} else if(this.примитив_логическое_выражение.test(значение)){
return значение.toLowerCase()==="да"
} else {
return значение
}
}
}