ITcl/Tk base elements
ОСНОВНЫЕ ПОНЯТИЯ И ЭЛЕМЕНТЫ ЯЗЫКА TCL
- Общая характеристика языка Tcl/Tk
- Типы данных Tcl
- Основы синтаксиса команд
- Комментарии
- Группирование аргументов с помощью двойных кавычек
- Группирование аргументов с помощью фигурных скобок
- Подстановка команд со скобками
- Подстановка переменных с '$'
- Разделение команд точкой с запятой
- Подстановки с обратным слешем
- Выражения
- Списки
- Регулярные выражения
- Результаты команд
- Процедуры
- Переменные: скалярные и массивы
- Встроенные команды
- Встроенные переменные
Общая характеристика языка Tcl/Tk
Язык Tcl/Tk обладает многими свойствами обычных процедурных языков и имеет следующие основные особенности:
- это язык высокого уровня, что выражается в значительно меньшем количестве непосредственного программирования для решения задачи;
- это интерпретируемый язык: программы на Tcl готовы к выполнению без компилирования и компоновки, хотя существует и компилятор Tcl;
- это расширяемый язык: в него легко добавляются команды пользователя, написанные на С или Tcl;
- его можно встраивать в создаваемые приложения ≈ ИНТЕРПРЕТАТОР Tcl представляет собой просто набор функций С, которые можно вызывать из кода приложения. В результате Tcl может служить языком приложения, подобно макроязыку электронных таблиц;
- Tcl работает на многих распространенных платформах;
Tcl предоставляет возможность автоматической загрузки пользовательских библиотек Tcl. Также возможна автоматическая загрузка по мере надобности динамических библиотек DLL, если ОС поддерживает такую загрузку.
Способ интерпретации строки Tcl зависит от конкретного интерпретатора, однако существует три общих формы строк: команды, выражения и списки. Ниже эти формы раскрыты более полно.
Синтаксически язык Tcl похож одновременно на оболочки Unix и lisp. Тем не менее, интерпретация (вариант: смысл) команд в Tcl отличается от обоих систем. Команда Tcl состоит из одной или нескольких команд, разделенных символами новой строки или точками с запятой. Каждая команда состоит из набора полей, разделенных пустым промежутком (пробелами или табуляцией). Первое поле должно быть именем команды, а необязательные остальные поля ≈ суть аргументы, передаваемые этой команде. Например, команда
При изображении первого символа команды, кроме пробела, в виде "#", все последующие символы в этой строке до символа новой строки включительно считаются комментарием и игнорируются. Когда комментарии встроены во вложенных командах (например, поля, заключенные в фигурные скобки), они должны иметь парные фигурные скобки. Это необходимо потому, что когда Tcl анализирует команду верхнего уровня, он еще не знает, что вложенное поле будет использовано как команда, и поэтому не может обработать вложенный символ комментария как символ комментария.
с помощью двойных кавычек
Обычно каждое поле аргумента заканчивается последующим пробелом, однако двойные кавычки можно использовать для задания аргументов с пробелами внутри. Если поле аргумента начинается с двойных кавычек, то этот аргумент не будет заканчиваться пробелом (включая символы новой строки) или точкой с запятой (использование точек с запятой описано ниже). Такой аргумент будет заканчиваться только следующим символом двойных кавычек. Символы двойных кавычек не будут входить в значение аргумента. Например, команда
с помощью фигурных скобок
Для группирования аргументов можно также использовать фигурные скобки. Их действие похоже на двойные кавычки, за исключением двух отличий. Во-первых, они позволяют вложение, поэтому их проще использовать для таких усложненных аргументов, как вложенные командные строки Tcl. Во-вторых, нижеописанные подстановки для команд, переменных и обратных слешей внутри фигурных скобок не выполняются. Поэтому фигурные скобки можно использовать для избежания ненужных подстановок. Если поле аргумента начинается с открывающей фигурной скобки, то этот аргумент заканчивается соответствующей ей закрывающей фигурной скобкой. Tcl отбросит наружную пару фигурных скобок и передаст команде информацию внутри скобок без какой-либо последующей модификации. Например, в команде
set b 33
При появлении в поле команды открывающей квадратной скобки выполняется подстановка команды. Все символы внутри скобок считаются командой, и она исполняется немедленно. Затем результат этого исполнения подставляется вместо текста в скобках. Например, рассмотрим команду
expr $b+2]x
Символ доллара "$" можно использовать в качестве краткой формы для подстановки переменных. Если у аргумента, не заключенного в фигурные скобки, имеется символ "$", то выполняется подстановка переменной. Символы после "$" вплоть до первого символа, не являющегося цифрой, буквой или подчеркиванием, считаются именем переменной, и строковое значение этой переменной подставляется вместо ее имени. Например, если переменная foo имеет значение "test", то команда
Вторая специальная форма для переменных имеет место тогда, когда после символа доллара следует открывающая фигурная скобка. В этом случае имя переменной состоит из всех символов, заключенных между фигурными скобками. Ссылки на массив в таком случае невозможны: предполагается, что такое имя есть имя скалярной переменной. Например, если переменная foo имеет значение "test", то команда
Аббревиатура с символом доллара
есть просто сокращенная форма: "$a" полностью эквивалентна "[set
a]" и используется только для удобного сокращения количества печатаемых
символов.
Обычно каждая команда занимает
одну строчку (команда заканчивается символом новой строки). Символ точки
с запятой также считается разделителем команд: можно поместить несколько
команд в одной строке, разделив их точками с запятой. Точки с запятой не
считаются разделителями команд, если они находятся внутри фигурных скобок
или двойных кавычек.
\b | ≈ | сдвиг на одну позицию влево (0х8); |
\f | ≈ | прогон листа (0хс); |
\n | ≈ | новая строка, newline(0ха); |
\r | ≈ | возврат каретки (0хd); |
\t | ≈ | табуляция (0х9); |
\v | вертикальная табуляция (0xb); | |
\{ | ≈ | открывающая фигурная скобка ("{"); |
\} | ≈ | закрывающая фигурная скобка ("}"); |
\[ | ≈ | открывающая квадратная скобка ("["); |
\] | ≈ | закрывающая квадратная скобка ("]"); |
\$ | ≈ | символ доллара ("$"); |
\sp | ≈ | пробел (" "), аргумент не прерывается; |
\; | ≈ | точка с запятой, аргумент не прерывается; |
\" | ≈ | двойные кавычки; |
\nl | ≈ | ничего: обратный слеш с последующей новой строкой соединяет две строки в одну. Эта подстановка уникальна тем, что она действует даже внутри фигурных скобок; |
\<newline>пробел | ≈ | одиночный пробел заменяет обратный слеш, символ новой строки и все пробелы и табуляции после этого символа новой строки. Данная последовательность уникальна в том смысле, что она замещается в отдельном суб-проходе перед тем, как начинается непосредственно анализ команды. Поэтому эта последовательность будет замещена, даже если она стоит между фигурными скобками и результирующий пробел будет интерпретироваться как разделитель слов, кроме того случая, когда он стоит между фигурными скобками или кавычками; |
\\ | ≈ | обратный слеш ("\"); |
\ddd | ≈ | цифры ddd (одна, две или все три) дают восьмеричное значение символа. Нулевой символ нельзя вставить в поле команды: если ddd есть ноль, то последовательность с обратным слешем игнорируется (т.е., преобразовывается в нулевую строку). |
Если следом за обратным слешем стоит какой-либо иной символ, кроме перечисленных выше, то обратный слеш передается в поле аргумента без специальной обработки, и сканер строки Tcl продолжает нормальную работу со следующим символом.
- Например, в команде
Данный механизм обратного слеша недостаточен для создания аргумента абсолютно любой структуры; он только обеспечивает наиболее общие случаи. Для создания особенно сложного аргумента, возможно, самым простым вариантом будет использование команду format совместно с подстановкой команды.
Вторая смысловая форма строк в Tcl ≈ это выражения. Несколько команд, таких как expr, for и if, считают один или несколько своих аргументов выражениями и для вычисления их значения вызывают процессоры выражений Tcl (Tcl_ExprLong, Tcl_ExprBoolean, и т.д.). Разрешенные в Tcl выражениях операторы составляют подмножество операторов, разрешенных в выражениях С, и они имеют такой же смысл и приоритет выполнения, как и соответствующие им операторы С. Почти всегда значением выражения является число (целое или с плавающей запятой). Например, выражение
8.2 + 6
Операнды могут быть заданы одним из следующих способов:
- числовым значением ≈ целым или с плавающей запятой;
- переменной Tcl, используя обычную нотацию со знаком $. В качестве операнда будет использовано значение переменной;
- строкой символов, заключенной в двойные кавычки. Анализатор выражения выполнит подстановки переменных, команд и с обратным слешем; полученное значение будет использовано в качестве операнда;
- строкой, заключенной в фигурные скобки. Все символы между открывающей и закрывающей скобками будут считаться операндом без каких-либо подстановок;
Еще один способ задания операндов назван в разделе "Встроенные команды Tcl".
Если в выражении имели место подстановки (например, внутри двойных кавычек), то они будут обработаны процессором выражения. Хотя анализатор команд тоже может выполнить свою часть подстановок (дополнительную серию подстановок) до вызова процессора выражения. Поэтому обычно, во избежание выполнения анализатором команд подстановок в содержимое выражения, лучше всего заключать выражение в фигурные скобки.
В качестве примеров рассмотрим простые выражения, в которых переменная a имеет значение "3", а значение переменной b есть "6". Тогда выражение в левой части каждой строки даст значение в ее правой части:
Третьей основной смысловой формой строк в Tcl являются списки. Список ≈ это обычная строка с подобной списку структурой, состоящей из полей, разделенных промежутками. Например, строка "Al Sue Anne John" есть список, имеющий четыре элемента (поля). Основная структура списков аналогична структуре командных строк, за исключением того, что символ новой строки служит таким же разделителем, как и пробел с табуляцией. Для списков действуют такие же правила в отношении фигурных скобок, двойных кавычек и обратных слешей, как и для команд. Например, строка- a
b\ c {d e {f g h}}
Команды Tcl concat,
foreach,
lappend,
lindex,
linsert,
list,
llength,
lrange,
lreplace,
lsearch
и
lsort
позволяют составлять списки, извлекать из них элементы, просматривать содержимое
и выполнять прочие относящиеся к спискам функции.
Tcl предоставляет две команды для сравнения строк регулярных выражений в стиле egrep: regexp и regsub.
Регулярное выражение состоит из ни одной или более ветвей (branch), разделенных символом "|". Оно совпадает с любым выражением, которое совпадает с одной из ветвей.
Ветвь состоит из одного или более кусков (piece), соединенных друг с другом. Она совпадает с выражением, которое состоит из тождества для первого куска, следом за которым идет тождество для второго куска, и т. д.
Кусок состоит из атома со
следующим за ним необязательным символом "*", "+" или "?". Атом с последующим
символом "*' совпадает с последовательностью из одного или более тождества
для этого атома. Атом с символом "+" после него совпадает с последовательностью
из одного или более тождества для этого атома. Атом с символом "?" после
него совпадает с последовательностью из одного тождества для этого атома
или пустой строкой.
Атом может быть регулярным выражением в скобках (в этом случае оно совпадает с тождеством для этого регулярного выражения), интервалом (об этом рассказано ниже), символом "." (совпадающим с одним любым символом), "^" (совпадающим с нулевой строкой в начале вводимой строки), "$" (совпадающим с нулевой строкой в конце вводимой строки), "\" с последующим одним символом (совпадающим с этим символом), или одним символом без какого-либо иного смысла (совпадающим с этим символом).
Интервал есть последовательность символов, заключенная в квадратные скобки. Он обычно совпадает с любым символом из этого интервала. Если последовательность начинается с символа "^", то она совпадает с любым символом не из числа остальных символов. Если два символа в последовательности разделены символом "-", то это краткая форма для обозначения всех символов между этими двумя (например, "[0-9]" совпадает с любой десятичной цифрой). Для того, чтобы включить в последовательность символ "]", следует поставить его на место первого в последовательности (следом за возможным символом "^"). Для включения в последовательность символа "-" следует сделать его первым или последним символом.
Если регулярное выражение совпадает с двумя разными частями строки, она будет совпадать с той, которая раньше начинается. Если обе начинаются в одном и том же месте, то это неопределенный (тяжелый) случай. Его можно объяснить следующим образом.
В общем, возможные исходы в списке ветвей рассматриваются слева направо. Исходы для "*", "+" и "?" рассматриваются в порядке убывания длины. Вложенные конструкции рассматриваются извне вовнутрь (from the outermost in), и составленные (concatenated) конструкции рассматриваются слева направо. Будет выбрано то из тождеств, которое будет отвечать самому раннему из исходов в первом выборе. Если предстоит несколько выборов, то следующее сравнение будет сделано таким же образом (самый ранний из исходов), в зависимости от решения при первом выборе, и так далее.
Например, "(ab|f)b*c" может совпадать с "abc" одним из двух способов. Первый выбор делается между "ab" и "a"; поскольку "ab" стоит раньше и ведет к успешному совпадению, то оно будет выбрано. Поскольку "b" уже закрыто, то "b*" должно совпасть со своим крайним исходом ≈ пустой строкой, чтобы не конфликтовать с предыдущим выбором.
В частном случае, когда нет ни одного разделителя ветвей "|" и присутствует только один символ "*", "+" или "?", общий результат будет следующим: будет выбрано самое длинное тождество из всех возможных. Таким образом, сравнение "ab*" с "xabbbby" даст результат "abbbb". Зато если "ab*" будет сравниваться с "xabyabbbz", то результатом будет считаться "ab", находящееся сразу за "x", в соответствии с правилом первого совпадения из всех возможных. В действительности, решение о том, откуда начинать сравнивать, есть первый выбор, который надо сделать. Этому выбору должны подчиняться последующие шаги, даже они ведут к менее предпочтительному результату.
Каждая команда возвращает два результата: код и строку. Код служит для индикации того, успешно или нет закончилась команда, а строка предоставляет дополнительную информацию. Действующие значения кодов определены в файле tcl.h, в виде следующего списка:
Обычно программистам на Tcl не нужно задумываться о кодах возврата, поскольку почти всегда возвращается TCL_OK. Если команда возвратила что-либо иное, то Интерпретатор Tcl немедленно останавливает обработку команд и возвращается к вызвавшему его событию. Если в некоторый момент имеется несколько вложенных вызовов интерпретатора Tcl, то обычно каждая из вложенных команд вернет ошибку вызывающему ее субъекту, и таким образом сообщение об ошибке достигнет самого верхнего уровня в приложении. После этого приложение выведет пользователю сообщение об ошибке.
В некоторых случаях отдельные
команды обрабатывают ошибочные ситуации сами и не сообщают о них наверх.
Например, команда for проверяет наличие
кода возврата TCL_BREAK
и если находит его, то прекращает выполнение тела цикла и возвращает код
TCL_OK
вызвавшему субъекту. Также команда forобрабатывает
коды TCL_CONTINUE,
а Интерпретатор процедур обрабатывает коды TCL_RETURN.
Команда catch позволяет программам
Tcl перехватывать ошибки и обрабатывать их без последующего прекращения
интерпретации команд.
Tcl позволяет расширить командный
интерфейс за счет определения процедур. Процедуру Tcl можно вызвать для
исполнения так же, как и любую другую команду Tcl (у нее есть имя и она
получает один или более аргументов). Единственным отличием является то,
что она не состоит из кода С, скомпонованного внутрь программы: это строка,
содержащая одну или более команд Tcl. Подробнее об определении и вызове
процедур рассказано в разделе "Встроенные комнды Tcl" (proc).
set a(3,6) 2
Библиотека Tcl предоставляет
набор встроенных команд. Эти команды будут доступны в любом приложении,
использующем Tcl. Дополнительно к этим командам приложения могут определять
свои собственные команды, а также команды, определенные в виде процедур
Tcl. Полный аннотированный список встроенных команд приведен в разделе
"Встроенные команды Tcl".
. В нем слова, выделенные
полужирным шрифтом, представляют собой имена команд и прочие слова, которые
следует передавать интерпретатору без изменения. Слова, выделенные курсивом,
представляют собой метасимволы, они обозначают собой некоторое возможное
значение, допустимое для ввода. Многоточие указывает на возможность подстановки
произвольного количества дополнительных аргументов или групп аргументов,
в том же формате, что и предшествующий аргумент или группа.
Библиотека Tcl автоматически создает и управляет следующими глобальными переменными. Во всех случаях, кроме специально оговоренных, эти переменные должны использоваться приложениями и пользователями в режиме только для чтения.env errorCode errorInfo
- Эта переменная задается
Tcl в виде массива, элементами которого являются переменные окружения процесса.
Чтение элемента даст значение соответствующей переменной окружения. Присвоение
значения элементу массива присвоит новое значение переменной окружения
или создаст ее, если она не была определена. Отмена (удаление) элемента
массива env удалит соответствующую
переменную окружения. Изменения в массиве будут влиять на окружение, переданное
дочерним процессам такими командами, как
exec.
Если будет удален весь массив env,
то Tcl перестанет отслеживать обращения к env
и перестанет обновлять значения переменных окружения.
- После возникновения ошибки
данная переменная будет определена для содержания дополнительной информации
об ошибке в форме, удобной для обработки программами. Переменная состоит
из списка Tcl с одним или более элементами. Первый элемент списка идентифицирует
общий класс ошибок и определяет формат остальной части списка. Ядро Tcl
использует следующие ниже форматы errorCode,
отдельные приложения могут задавать свои собственные форматы.
- идентификатор процесса (десятичное число);
- символическое имя сигнала, вызвавшего приостановку процесса;
- короткое сообщение пользователю, описывающее сигнал, например: Фоновое TTY чтение.
Для задания переменной errorCode приложения должны использовать такие библиотечные процедуры, как Tcl_SetErrorCode и Tcl_UnixError, или использовать команду error. Если ни один из этих способов не был использован, то после следующей ошибки ИНТЕРПРЕТАТОР Tcl установит переменную на NONE.
- После возникновения ошибки
эта строковая переменная будет содержать одну или более строк, идентифицирующих
команды и процедуры Tcl, исполнявшиеся в момент возникновения самой последней
ошибки. Ее содержимое принимает форму образа стека, со всеми вложенными
командами Tcl, которые в момент возникновения ошибки не были закончены.