| Предыдущая глава |
↓ Содержание ↓
↑ Свернуть ↑
| Следующая глава |
автоматически очищается. Чтобы предотвратить, пришлось добавить в псевдоним
буковку N.
* * *
Третий подход к снаряду: форматные выражения в операторе Write %выражение
плюс оператор Modify с присваиванием, который теперь можно бы назвать Move ибо
перемещает строчки между группами. Ну да нам без разницы: всё равно значима
одна только первая буква ключевого слова. Остальные — игнорируются.
Вот оператор Modify номер_строки_или_группы; мы как-то выпустили из
виду. Да, в такой форме он всего лишь скромненько позволяет редактировать
хранящиеся в памяти программные строки, запуская для каждой из них редактор
командной строки. Но позволяет редактировать не только сам текст, но и номер,
в результате чего строка в итоге может оказаться в другом месте. (Ибо удаляет
и вставляет заново.)
А что он будет делать, если его аргумент не число (номер строки) а текст?
А то же самое, что и интерфейсная часть интерпретатора! То есть либо поместит
этот свой аргумент в память, либо попытается выполнить. Понадобилось это в
комплект к пошаговому режиму, где была сделана возможность ввести и выполнить
"прямую" строку — дабы можно было посмотреть значения переменных, или даже
заглянуть в хелп... Но исправлением и дополнением программы пусть таки
занимается тот, кому это положено — вот оператор Modify.
А за одно это резкое упрощение самомодификации: всётаки описанная выше
технология с формированием строк во внешнем файле и остановкой программы
страдает рядом недостатков... (А из А2: Mod !; — оно как-то получше.)
Следующий шаг модернизации: Mov N = A; перемещение программной строки,
в том числе с добавлением к ней: Mov N = A, B, C... где если первые из A, B,
C... — числа то это номера программных строк; а если очередной элемент — "..."
или ! (то есть строчного типа), то следующие числа рассматриваются как коды
символов. Слева от знака = (равно) в качестве N может быть как число (новый
номер строки), так и ! (восклицательный знак), и тогда результат помещается в
А2.
Таким образом появилась возможность использовать програмные строки как
переменные для хранения строчных значений. Пока что возможность — ограниченная:
хранимые там строки не должны включать символа с кодом ноль. Но это — вопрос
реализации...
А преобразование строк... Уж коли Write их копирует, то пусть сам "на
лету" что-то с ними и делает. Хотя бы по минимуму: типа вставить фрагмент
строки и/или удалить. Ну и найти, куда вставлять и что удалять, тем паче
"маркер" для этого у нас уже есть — всё тот же указатель, разделяющий уже якобы
использованную часть строки и еще нет. Но пришлось придать ему еще и
размер — чтобы указывал что нашли, а не только начало этого...
Буковки мы прибережем для грядущих встроенных форматов, а под операции
задействуем символы, которые не буква и не цифра — ровно по одной штуке на
операцию. Но некоторым нужны уточнения: например для = # ("сохранить" и
"применить") — куда именно сохранять и что применять. Так что получается уже
два символа. Выполняются операции строго слева направо, без какого либо
старшинства, пока выражение не закончится, или до первой ошибки, когда например
попытались переместить маркер за пределы строки, или не нашли что искали.
(После чего содержимое А2 выдаётся в канал вывода, а на его место читается
новая строка из канала ввода. Если конешно вот эта была не последняя.) Да,
всё форматное выражение — "одно слово", начинающееся с символа % (процент).
И у него внутри не может быть пробела, запятой и тем более точки с запятой,
разделяющих слова, части оператора и сами операторы. В роли пробела символ _
(подчеркивание) обозначающий пустую операцию.
Основных операций — две: * / вставка и удаление. Способов перемещения
маркера тоже два — собственно перемещение на указанное числом количество
позиций, и поиск указанного строкой фрагмента. В первом случае размер маркера
становится нулевой, а во втором устанавливается по размеру найденного. А в
самом начале, когда строка еще только прочитана — маркер ставится в начало и
включает её всю. (Потому как решено, что встроенные форматы, когда они наконец
появятся, будут действовать не на всё подряд, а только на то, что под маркером.)
Два префикса + и — указывают направление перемещения. А операции ^ и $
предписывают поставить маркер в начало и в конец строки. Так: $-10*"Вася"
предписывает поставить маркер в конец, отступить на десять позиций и вставить
там слово "Вася". Если строка короче десяти символов, то операцию сдвига "-10"
выполнить не удастся и слово не будет вставлено.
При перемещении, размер маркера обнуляется, но может быть установлен
принудительно операцией ~ которой нужен либо правый операнд — число, либо еще
какое либо уточнение. Например ~$ (до конца строки) ~^ (до её начала) ~. (до
метки). Эта самая "метка" — удобная штука: с помощью =. запоминает текущую
позицию маркера, а с помощью #. меняется с ним местами.
Префиксы + и — сами по себе предписывающие перемещение вперёд и назад на
одну позицию, действуют не только на следующее за ними число, но и на многие
операции. Маркер делит строку на три части, условно: A B C — до, под маркером
и после маркера (некоторые из которых могут иметь нулевой размер). Ну так
-*"ххх" вставит ххх между A и B, +*"ххх" — между B и C, а просто *"ххх" -
вместо B. (При нулевом размере фрагмента B это без разницы.) А вот операция /
без причитающегося ей числового операнда, который бы и указал, сколько
символов удалять, для -/ / и +/ удалит части A, B и C соответственно.
Таким образом операции * причитается строчный операнд, / числовой, ~ тоже
числовой, а операциям ^ и $ — не причитаются. И префиксы на них тоже не
действуют. (Не придумал пока, что бы это значило. Хотя есть идеи...)
Разумеется операнд может быть не только константой (это было бы слишком
грустно и не универсально), но и значением переменной: #Х (где Х — буква или
цифра), и результатом вычисления выражения: {...} и даже #{...}.
(Противоположные операции =Х и ={...} тоже очень даже имеют смысл!)
Число берется из фокаловской переменной со специфическим именем #Х, которая,
впрочем, от других переменных ничем кроме имени не отличается. А вот строка
(если Х — цифра, так что лучше писать как #N =N) — из "регистра" форматного
механизма. Которых получилось ровно десять штук. И операцией =N туда же
помещается: для -=N =N +=N берутся части строки A B и C соответственно.
Одновременно в фокаловскую переменную с именем #N пишется размер этого
фрагмента. Для -=Х =Х +=Х (где Х — буква) — только размер.
Числовое выражение в {...} отличается от обычного только тем, что там не
должно быть лишних пробелов, и надо по-аккуратней с как раз и заменяющим
пробел символом _ (подчеркивание). А строчное отличается от него тем, что
начинается со строчной константы ("..." ! :N) и единственная операция -
сцепление входящих туда компонентов ("конкатенация"), которая, впрочем, никак
не обозначается — просто перечень компонентов, может быть разделенных
подчеркиваниями (чисто для красоты и наглядности). Понадобилась например на
случай, когда нам нужны все три кавычки: "'` (там это будет {'"'_"'"_"`"}).
Числовые значения, если встретятся, обозначают коды символов. Еще внутри {...}
допускается конструкция =Х — присваивание, но не до, как например в операторе
Set, а ПОСЛЕ того как вычислено то, что хотим присвоить.
#{...} и ={...} — форматные преобразования. (Еще более форматные, чем само
форматное выражение, компонентом которого являются, хотя казалось бы что
форматней уже некуда.) Формат там внутри — позаимствованный у Си-шных функций
printf() и scanf(), да и сами эти конструкции являются их аналогами. (Вот
только о преобразовании в код как-то не...)
И теперь, когда у нас появились регистры форматного механизма, везде, где
по смыслу допустимо "..." может быть не только ! указывающий на А2 но и :цифра
указывающая на один из этих регистров. (Но опять же кроме операторов Ask, Type
и функции FCHr которые и без того со всем этим работают.)
Write Reg; выдаёт содержимое аккумулятора А2 и регистров форматного
механизма, а Eraze Reg; очищает их. (Но вроде бы только со второй очереди?)
Это была первая очередь форматного механизма оператора Write %
Она включает так же префикс повторения @ для организации циклов и круглые
скобки для группировки операций: префикс повторения действует только на один
элемент — как отдельную операцию, так и вот такую группу. Например:
Write %@(+"Васисуалий"*"Вася").... здесь все найденные вхождения слова
"Васисуалий" будут заменены на слово "Вася", но остаток форматного выражения,
обозначенный здесь как .... выполнен не будет, потому что очереднной поиск
слова "Васисуалий" завершится неуспешно и на этом закончится не только цикл,
но и выполнение всего форматного выражения.
На этот случай есть постфиксы условного выполнения: & ? выполняющие (или
пропускающие) следующую после них операцию для случаев успешности выполнения
предыдущей, неуспешности, а так же ? предусматривающий оба варианта. То есть
например, если в: Write %+"Вася"(^*"###").... фрагмент "Вася" не найден то
выполнение форматного выражения (остаток которого обозначен как ....) всё равно
продолжится, но дополнительно в начало строки будет вставлено "###". Если
подобного нам не надо — после можно поставить ничего не делающую "пустую"
операцию _ (подчеркивание).
Префикс повторения может иметь как числовой операнд, просто указывающий
количество повторений, так и заключенный в {} заголовок, аналогичный заголовку
оператора For. Префикс повторения с загловком но без тела цикла вместе с
постфиксом составляет условное выражение.
Кроме того, в первой очереди предусмотрена операция ! для немедленного
прекращения выполнения форматного выражения и одновременно подавления вывода
строки из А2. (В том числе с префиксами + и — "со скандалом": прекращением
работы оператора Write в т.ч. и с ошибкой 3.6 или какой указано), и
противоположная к ней операция . (точка) предписывающая немедленный вывод
строки из А2 (с префиксами — одной из частей строки). Есть даже обращение к
подпрограмме: %Цифра (где цифра указывает один из регистров). Но нету ни
одного встроенного формата, для которых и приберегаются буковки, ни "шаблонов"
(они же "регулярные выражения") в виде конструкции <...> (Вернее шаблоны-то
как раз сперва были, но потом отправились на реконструкцию.)
С появлением операции ! устройство NUL более не надобно: Write %! "метка"
* * *
Шаблоны и некоторые встроенные форматы (те самые, для которых мы и
приберегали буковки), в том числе преобразования из одной кодировки в другую,
можно считать "второй очередью".
Шаблон (он же "регулярное выражение") — конструкция вида <....> так же как
и "....", нужен для поиска фрагмента строки (это — "анализирующий" шаблон),
ну и конешно как правый операнд операции вставки * (звёздочка), указывающий что
именно ей вставлять ("генерирующий"). Шаблон <....> отличается от текстовой
константы "...." тем, что в ней каждый символ изображает самого себя (кроме
ограничивающих конструкцию кавычек, разумеется), а в шаблоне некоторые из
символов имеют специальный смысл. Например . (точка) изображает вовсе не точку
а заменяет собою абсолютно любой символ; ^ и $ — изображают начало и конец
строки в аккумуляторе, а ! (восклицательный знак) — СИМВОЛ конца строки, что
совсем не тоже самое! Да, такой символ УКАЗЫВАЕТ на конец строки; оператор Ask
читая из А2 очередную строку, определяет где у неё конец вот по такому символу.
.. А состоит он как правило из ДВУХ символов, известных как "перевод строки"
(ПС, он же 'n' в языке Си) и "возврат каретки" (ВК, 'r') с кодами 10 и 13.
Именно с этой парой (в любом порядке) ! и сопоставляется. Но так же если один
из них (тоже любой) — в гордом одиночестве. Соответственно, в конце строки
такой "символ" как правило и присутствует. Но совсем не обязательно...
Да и вставить его можно посередь строки, разрывая её надвое...
Так что <.$.> или <.^.> — заведомо ни с чем не сопоставятся. Потому
что ни до начала строки ни после её конца никаких символов быть не может
просто по определению, а вот <.!.> — очень даже может.
А главный баламут всея Фокала символ % (процент) отбирает у таких вот
специальных символов их специальный смысл, заставляя изображать самоё себя.
Но и придаёт некоторым "обычным" символам специальный смысл "встроенного
шаблона", изображающего собою группу символов. Например: %c — любая цифра,
%b — любая буква, %r — любая русская, %l — любая латинская, а вот %л и %Л
только заглавная и только строчная. Аналогично для русских букв %р %Р и для
букв вообще %б %Б. И кроме того %Г %г %G %g — любой символ псевдографики;
%С %с %S %s — строка в кавычках; %П %п %P %p пробел и "слепые" символы (с
кодом меньше чем у пробела). При чем для %П %п — плюс знаки препинания,
способные завершать слова . , : ; ! ? и конец строки. При чем %П и %P
сопоставляются с одним, а %п и %p — с нулём таких символов, то есть просто
обнаруживают конец слова.
Однако, сила и мощь регулярных выражений — в * ? ("повторение")...
Регулярные выражения встречаются... ну не то что бы сплошь и рядом, но
по-моему достаточно известны — используются при поиске. Чего либо. Например
файлов в каталоге командой операционной системы: DIR имя_файла где вместо
имени конкретного файла может быть и вот такой шаблон. Где * (звёздочка),
которая в именах файлов не встречается, заменяет собою любое количество любых
символов, в том числе и ни одного, а ? (вопросительный знак) — ровно один
символ, но тоже любой. (В именах файлов ? разумеется тоже не встречается.)
Например под шаблон "*ася" подойдёт и "Вася" и "вася" и "мася" и "ася" и
"ЫЫЫася", а под "?ася" только три первые.
Следует заметить, что и в ДОС`е и в винде механизм этот сделан крайне
халтурно. И как он себя поведёт, когда в шаблоне две звёздочки — одному Аллаху
известно.
А вот в UNIX`овском ls — всё по честному. И есть еще один элемент: [...]
заменяющие собой тоже один символ, но не любой, а один из внутри перечисленных.
Или его негативный вариант [~...] — любой из внутри не встречающихся. Внутри
могут быть как сами эти символы, так и "диапазон": чтобы не перечислять все с
подряд идущими кодами. Например: [a-zA-Z] это все латинские буквы. С русскими
| Предыдущая глава |
↓ Содержание ↓
↑ Свернуть ↑
| Следующая глава |