Pull to refresh

Ненормальное программирование: макрос-интерпретатор в Notepad++

Reading time 29 min
Views 9.9K

swap


Обмен значений. Исходный текст и текст после 1-го, 2-го и 3-го выполнения макроса. Далее будут примеры посложнее.


Идея приспособить макрос для примитивного программирования появлялась у меня несколько раз. То есть, сделать так, чтобы макрос при запуске "читал" строчку с операцией, интерпретировал ее, что-то делал с данными и переходил к следующей строчке.


На всякий случай напомню: макрос в Notepad++ и в других текстовых редакторах – записанная последовательность действий пользователя над текстом. Макрос можно запускать многократно для быстрого выполнения рутинных операций. Макрос "запоминает" нажатия клавиш и может воспроизводить, например, такие действия:


  • Ввод и удаление символов
  • Перемещение курсора
  • Копирование и вставка
  • Поиск в тексте

Сначала это казалось невозможным, ведь макрос слишком "глуп" и прямолинеен:


  • Нельзя менять последовательность действий во время выполнения макроса.
  • Искомая строка фиксирована — никакой вставки из буфера обмена.
  • Нельзя выполнить действие переменное количество раз, а также пропустить действие в зависимости от какого-либо условия.

Для второго пункта нашлось решение – Search -> Find (Volatile) Next (Ctrl+Alt+F3). Эта операция ищет выделенное. Благодаря ей, можно совершать динамический переход, в зависимости от выделения. А вот первый пункт казалось невозможно обойти. Получалось, что никак не выполнить такой код:


a = 1
if что-то-там...

Макрос не сможет определить, что в первой строке нужно выполнить присваивание, а во второй совершить условный переход. А это значит, что нужно делать все в одной операции. Как-то так:


//Данные
a:0

//Код
a = 1 goto label1
label1: a = 2 goto label2

Чтобы перейти по метке, нужно использовать поиск выделенного. Но появилась такая проблема – как реализовать условный переход. Очевидно, нужно переходить всегда, но по изменяющимся меткам:


[a]:0
a = 1 goto label[a]
label1:

Значение переменной подставляется вместо [a], и получается label1, label2 или label_hello. Так как подстановка должна осуществляться всегда, то для безусловного перехода появилась служебная переменная [] с пустым значением:


[]:
[a]:0
a = 1 goto label1[]
label1: ...

Из-за того что пустое значение нельзя скопировать, пришлось во всех хранилищах переменных добавлять пробел после значения и удалять после подстановки. Неудобно, но не знаю, как сделать лучше. В конечном итоге, строка с операций приобрела следующий вид:


w: w[w]w = w[w[w]w]w   w[w]w

Где w – \w* в регулярном выражении, т. е. состоящее из буквенных и цифровых символов и знаков подчёркивания. Макрос 4 раза осуществляет подстановку переменных, сохраняет значение переменнной и совершает переход.


Принцип работы макроса


Рассмотрим простой пример.


label1: b[index] = [a[]] label2[]
label2:

[]: 
[a]:Hello_world 
[index]:2 
[b2]: 

Считаем, что курсор в начале первой строки. Регуляркой \w*\[\w*\]\w* ищется и выделяется первое вхождение, у нас это b[index]. Оно копируется и вставляется в конец строки после добавления >>>:


label1: b[index] = [a[]] label2[]>>>b[index]

После \[\w*\] добавляется двоеточие, и регуляркой выделяется [index]:. Далее совершается поиск следующего такого вхождения. Если все корректно, то это место со значением переменной. Значение выделяется и копируется. Производится возврат путем поиска >>>. Регуляркой находится [index]:. Вместо этого выражения вставляется значение переменной. Все выражения "оборачивается" в квадратные скобки и к нему добавляется двоеточие для дальнейшего поиска получившегося имени переменной:


label1: b[index] = [a[]] label2[]>>>[b2]:

Дальше аналогично, но для выражения в правой части равенства осуществляется двойная подстановка.


(1) label1: b[index] = [a[]] label2[]>>>[b2]:>>>[a[]]
(2) label1: b[index] = [a[]] label2[]>>>[b2]:>>>[a]
(3) label1: b[index] = [a[]] label2[]>>>[b2]:>>>Hello_world

Запись значения переменной по тому же принципу. И, наконец, осуществляется подстановка для имени метки, и происходит переход по ней.


(1) label1: b[index] = [a[]] label2[]>>>label2[]
(1) label2:

(2) label1: b[index] = [a[]] label2[]>>>label2
(2) label2:

(3) label1: b[index] = [a[]] label2[]>>>label2
(3) >>>label2:

(4) label1: b[index] = [a[]] label2[]
(4) >>>label2:

(5) label1: b[index] = [a[]] label2[]
(5) label2:

Приходится отмечать маркером >>> метку перехода, чтобы удалить "мусор" в конце строки.


Примеры


Hello, world!


Выполнение макроса зацикливается на первой строчке.


label: out[] = Hello_world[[]] label[]

[out]:Hello_world 
[]: 

Обмен значений (swap)


l1: t[]=[a[]] l2[]
l2: a[]=[b[]] l3[]
l3: b[]=[t[]] l1[]

[]: 
[a]:World 
[b]:Hello 
[t]: 

В начале и после трех запусков макроса:


swap


Вызов подпрограммы


Тот же swap, только вынесенный в отдельную подпрограмму. Конструкция [[swap_var0]] позволяет получить значение переменной, имя которой находится в swap_var0.


l1: swap_var0[] = a[[]]  l2[]   //Установка имени 1 переменной
l2: swap_var1[] = b[[]]  l3[]   //Установка имени 2 переменной
l3: swap_ret[]  = l1[[]] swap[] //Установка метки возврата
                                //и переход в подпрограмму

[]: 
[a]:Hello 
[b]:World 

##### Swap
[swap_var0]: 
[swap_var1]: 
[swap_ret]: 

swap:    _swap_temp[] = [[swap_var0]]  _swap_2[]
-- private
_swap_2: [swap_var0]  = [[swap_var1]]  _swap_3[]
_swap_3: [swap_var1]  = [_swap_temp[]] [swap_ret]
[_swap_temp]: 
#####

Одноразрядный десятичный инкремент


l1: inc__var[] = a[[]]  l2[]
l2: inc__ret[] = inc__begin[[]]  inc__begin[]

[]: 
[a]:0 

##### Increment 
[inc__var]:a 
[inc__ret]: 
inc__begin: _inc__val[] = [[inc__var]]  _inc[]

-- private
_inc:  [inc__var] = [_inc__map[_inc__val]]  [inc__ret]

[_inc__val]: 
[_inc__map0]:1 
[_inc__map1]:2 
[_inc__map2]:3 
[_inc__map3]:4 
[_inc__map4]:5 
[_inc__map5]:6 
[_inc__map6]:7 
[_inc__map7]:8 
[_inc__map8]:9 
[_inc__map9]:0 
#####

Трехразрядный десятичный инкремент


При инкрементации для переноса в старший разряд требуется отслеживать переполнение. Поэтому в подпрограмму инкрементации добавлен второй overflow-выход. Да, метки можно разместить в ряд.


l01: inc__var[] = a[[]]  l02[]
l02: inc__ret[] = inc__begin[[]]  l03[]
l03: inc__over_ret[] = l11[[]]  inc__begin[]

l11: inc__var[] = b[[]]  l12[]
l12: inc__ret[] = l01[[]]  l13[]
l13: inc__over_ret[] = l21[[]]  inc__begin[]

l21: inc__var[] = c[[]]  l22[]
l22: inc__ret[] = l01[[]]  l23[]
l23: inc__over_ret[] = l01[[]]  inc__begin[]

[]: 
[c]:0 
[b]:0 
[a]:0 

##### Increment 
[inc__var]: 
[inc__ret]: 
[inc__over_ret]: 
inc__begin: _inc__val[] = [[inc__var]]  _inc[]

-- private
_inc:  [inc__var] = [_inc__map[_inc__val]]  i[_inc__val]
i0:i1:i2:i3:i4:i5:i6:i7:i8: _inc__val[] = [_inc__val[]]  [inc__ret]
i9: _inc__val[] = [_inc__val[]]  [inc__over_ret]

[_inc__val]: 
[_inc__map0]:1 
[_inc__map1]:2 
[_inc__map2]:3 
[_inc__map3]:4 
[_inc__map4]:5 
[_inc__map5]:6 
[_inc__map6]:7 
[_inc__map7]:8 
[_inc__map8]:9 
[_inc__map9]:0 
#####

Пузырьковая сортировка


И размер массива, и его возможные значения ограничены от 0 до 9. Работает долго, но сортирует. Можно запустить макрос многократно и задать 2000 итераций, тогда выполнение займет порядка минуты. Первоначальная реализация сравнения была очень медленной – каждое число декрементировалось до тех пор, пока одно из них не достигнет 0. Сейчас она некрасивая, но относительно быстрая.


Пузырьковыя сортировка
s000: it_remain[] = 8[[]] s010[]
s010: index0[]    = 8[[]] s020[]
s020: index1[]    = 9[[]] s030[]

//Обмен значений, если первое больше
s030: swap_if__var0[] = array[index0[]] s040[]
s040: swap_if__var1[] = array[index1[]] s050[]
s050: swap_if__ret[]  = s060[[]]        swap_if__begin[]

//Декремент 1-го индекса
s060: dec__var[]      = index1[[]] s070[]
s070: dec__ret[]      = s100[[]]   s080[]
s080: dec__zero_ret[] = s100[[]]   dec__begin[]

//Декремент 2-го индекса
s100: dec__var[]      = index0[[]] s110[]
s110: dec__ret[]      = s030[[]]   s120[]
s120: dec__zero_ret[] = s200[[]]   dec__begin[]

//Декремент количества оставшихся прогонов
s200: dec__var[]      = it_remain[[]] s210[]
s210: dec__ret[]      = s010[[]]      s220[]
s220: dec__zero_ret[] = finish[[]]    dec__begin[]

[array0]:5 
[array1]:3 
[array2]:7 
[array3]:3 
[array4]:2 
[array5]:3 
[array6]:1 
[array7]:2 
[array8]:4 
[array9]:1 

[index0]: 
[index1]: 
[it_remain]: 

##### special
[]: 
[stub]:stub 
[finished]:no 
finish: finished[]=yes[[]] finish[]
#####

##### Swap if not less
[swap_if__var0]: 
[swap_if__var1]: 
[swap_if__ret]: 
swap_if__begin: less__val0[] = [[swap_if__var0]] _swap_if1[]

-- private
_swap_if1: less__val1[] = [[swap_if__var1]] _swap_if2[]
_swap_if2: less__ret0[] = [swap_if__ret[]]  _swap_if3[]
_swap_if3: less__ret1[] = _swap_if4[[]]     less__begin[]

_swap_if4: _swap__tmp[]    = [[swap_if__var0]] _swap_if5[]
_swap_if5: [swap_if__var0] = [[swap_if__var1]] _swap_if6[]
_swap_if6: [swap_if__var1] = [_swap__tmp[]]    [swap_if__ret]

[_swap__tmp]: 
#####

##### Less
[less__val0]: 
[less__val1]: 
[less__ret0]: 
[less__ret1]: 
less__begin: stub[] = [stub[]]  _less__[less__val0]

-- private
_less__0: stub[] = [stub[]]  s0[less__val1]
_less__1: stub[] = [stub[]]  s1[less__val1]
_less__2: stub[] = [stub[]]  s2[less__val1]
_less__3: stub[] = [stub[]]  s3[less__val1]
_less__4: stub[] = [stub[]]  s4[less__val1]
_less__5: stub[] = [stub[]]  s5[less__val1]
_less__6: stub[] = [stub[]]  s6[less__val1]
_less__7: stub[] = [stub[]]  s7[less__val1]
_less__8: stub[] = [stub[]]  s8[less__val1]
_less__9: stub[] = [stub[]]  [less__ret1]
s01:s02:s03:s04:s05:s06:s07:s08:s09:s12: stub[] = [stub[]]  [less__ret0]
s13:s14:s15:s16:s17:s18:s19:s23:s24:s25: stub[] = [stub[]]  [less__ret0]
s26:s27:s28:s29:s34:s35:s36:s37:s38:s39: stub[] = [stub[]]  [less__ret0]
s45:s46:s47:s48:s49:s56:s57:s58:s59:s67: stub[] = [stub[]]  [less__ret0]
s68:s69:s78:s79:s89:                     stub[] = [stub[]]  [less__ret0]
s00:s10:s11:s20:s21:s22:s30:s31:s32:s33: stub[] = [stub[]]  [less__ret1]
s40:s41:s42:s43:s44:s50:s51:s52:s53:s54: stub[] = [stub[]]  [less__ret1]
s55:s60:s61:s62:s63:s64:s65:s66:s70:s71: stub[] = [stub[]]  [less__ret1]
s72:s73:s74:s75:s76:s77:s80:s81:s82:s83: stub[] = [stub[]]  [less__ret1]
s84:s85:s86:s87:s88:                     stub[] = [stub[]]  [less__ret1]
#####

##### Decrement
[dec__var]: 
[dec__ret]: 
[dec__zero_ret]: 
dec__begin: _dec__val[] = [[dec__var]]  d[_dec__val]

-- private
d1:d2:d3:d4:d5:d6:d7:d8:d9: [dec__var] = [_dec__map[_dec__val]]  [dec__ret]
d0: [dec__var] = [_dec__map[_dec__val]]  [dec__zero_ret]

[_dec__val]: 
[_dec__map0]:9 
[_dec__map1]:0 
[_dec__map2]:1 
[_dec__map3]:2 
[_dec__map4]:3 
[_dec__map5]:4 
[_dec__map6]:5 
[_dec__map7]:6 
[_dec__map8]:7 
[_dec__map9]:8 
#####

Установка


Если вам вдруг захотелось попробовать, то в элемент <Macros> файла %APPDATA%/Notepad++/shortcuts.xml нужно вставить:


Код макроса
        <Macro name="npplang" Ctrl="yes" Alt="yes" Shift="yes" Key="69">
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="\w*\[\w*\]\w*" />
            <Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="0" message="2178" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2451" wParam="0" lParam="0" sParam="" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="&gt;" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="&gt;" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="&gt;" />
            <Action type="0" message="2179" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]" />
            <Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam=":" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]:" />
            <Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="2" message="0" wParam="43014" lParam="0" sParam="" />
            <Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2452" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2178" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]:" />
            <Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="0" message="2179" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2326" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="[" />
            <Action type="0" message="2451" wParam="0" lParam="0" sParam="" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="]" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam=":" />
            <Action type="0" message="2453" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="\w*\[\w*\[\w*\]\w*\]\w*" />
            <Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="0" message="2178" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2451" wParam="0" lParam="0" sParam="" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="&gt;" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="&gt;" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="&gt;" />
            <Action type="0" message="2179" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]" />
            <Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam=":" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]:" />
            <Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="2" message="0" wParam="43014" lParam="0" sParam="" />
            <Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2452" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2178" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]:" />
            <Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="0" message="2179" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2326" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]" />
            <Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam=":" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]:" />
            <Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="2" message="0" wParam="43014" lParam="0" sParam="" />
            <Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2452" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2178" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]:" />
            <Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="0" message="2179" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2326" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2452" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2178" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]:" />
            <Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="2" message="0" wParam="43014" lParam="0" sParam="" />
            <Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2452" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2179" wParam="0" lParam="0" sParam="" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam=" " />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="0" message="2304" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2452" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2180" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2453" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="\w*\[\w*\]\w*" />
            <Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="\w*\[\w*\]\w*" />
            <Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="\w*\[\w*\]\w*" />
            <Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="0" message="2178" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2451" wParam="0" lParam="0" sParam="" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="&gt;" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="&gt;" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="&gt;" />
            <Action type="0" message="2179" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]" />
            <Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam=":" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]:" />
            <Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="2" message="0" wParam="43014" lParam="0" sParam="" />
            <Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2452" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2178" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]:" />
            <Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="0" message="2179" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2326" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2451" wParam="0" lParam="0" sParam="" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam=":" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2452" wParam="0" lParam="0" sParam="" />
            <Action type="2" message="0" wParam="43014" lParam="0" sParam="" />
            <Action type="0" message="2304" wParam="0" lParam="0" sParam="" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="&gt;" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="&gt;" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="&gt;" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="0" message="2452" wParam="0" lParam="0" sParam="" />
            <Action type="0" message="2180" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
            <Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
            <Action type="0" message="2180" wParam="0" lParam="0" sParam="" />
        </Macro>

Запуск макроса осуществляется нажатием Ctrl+Shift+Alt+E.


Заключение


Была мысль создать стек, чтобы отойти от глобальных переменных. Тогда бы появилась возможность реализации рекурсии, например. Но не вижу особого смысла, ведь тут самым интересным было исследовать возможность такого программирования. И вы не представляете, как я был рад, когда заработали первые простые примеры.

Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
+24
Comments 9
Comments Comments 9

Articles