ОСНОВНЫЕ  ПОНЯТИЯ И  ЭЛЕМЕНТЫ ЯЗЫКА TCL

Общая характеристика языка Tcl/Tk

Язык Tcl/Tk обладает многими свойствами обычных процедурных языков и имеет следующие основные особенности:

Типы данных Tcl

Tcl поддерживает только один тип данных: строки. Все команды, все аргументы команд, результаты их выполнения и значения переменных суть строки. В тех случаях, когда командам требуются числовые аргументы или они возвращают числовые результаты, аргументы и результаты передаются в виде строк. Многие команды предполагают соответствие их аргументов определенным форматам, но это суть индивидуальные особенности команд. Например, часто аргументы содержат командные строки, которые могут быть обработаны в качестве частей команды. Самый простой путь для понимания интерпретатора Tcl ≈ это помнить, что все в нем представляет собой операции над строками. Во многих случаях конструкции Tcl будут выглядеть подобно более структурированным конструкциям из других языков. Однако конструкции Tcl не являются структурированными вообще: они являются лишь строками символов, и поэтому они ведут себя иначе, чем те конструкции, на которые они могут быть похожи.

Способ интерпретации строки Tcl зависит от конкретного интерпретатора, однако существует три общих формы строк: команды, выражения и списки. Ниже эти формы раскрыты более полно.

Основы синтаксиса команд

Синтаксически язык Tcl похож одновременно на оболочки Unix и lisp. Тем не менее, интерпретация (вариант: смысл) команд в Tcl отличается от обоих систем. Команда Tcl состоит из одной или нескольких команд, разделенных символами новой строки или точками с запятой. Каждая команда состоит из набора полей, разделенных пустым промежутком (пробелами или табуляцией). Первое поле должно быть именем команды, а необязательные остальные поля ≈ суть аргументы, передаваемые этой команде. Например, команда

имеет три поля: первое, set, есть имя команды, а остальные два, a и 22, будут переданы в качестве аргументов команде set. Имя команды должно быть именем встроенной команды Tcl, дополнительной команды, созданной для данного приложения процедурой Tcl_CreateCommand, или командной процедурой, определенной с помощью встроенной команды proc.

Аргументы передаются текстовыми строками в буквальном смысле. Команды пользуются этими строками так, как им требуется. Например, команда set считает свой первый аргумент именем переменной, а второй ≈ строковым значением для присвоения этой переменной. Другие команды могут считать свои аргументы целыми числами, списками, именами файлов или командами Tcl.

Обычно имена команд должны быть напечатаны полностью, без сокращений. В тех случаях, когда интерпретатор Tcl не может узнать имя команды, он вызовет специальную команду по имен    и unknown, которая попытается найти или создать указанную команду. Например, во многих случаях команда unknown будет искать команду в каталогах библиотек и если найдет, то создаст ее в виде процедуры Tcl. Часто команда unknown обеспечивает выполнение команд, заданных сокращенным именем, но обычно только тех, которые поданы в интерактивном режиме работы. Даже если выполнение такой команды обеспечивается, использование сокращенной формы имен команд в командных скриптах и других вещах, которые будут в использовании спустя время, не рекомендуется: изменения в наборах команд последующих версий языка могут привести к неоднозначной интерпретации и вызванными этим ошибками в работе скриптов.

Комментарии

При изображении первого символа команды, кроме пробела, в виде ▒#▓, все последующие символы в этой строке до символа новой строки включительно считаются комментарием и игнорируются. Когда комментарии встроены во вложенных командах (например, поля, заключенные в фигурные скобки), они должны иметь парные фигурные скобки. Это необходимо потому, что когда Tcl анализирует команду верхнего уровня, он еще не знает, что вложенное поле будет использовано как команда, и поэтому не может обработать вложенный символ комментария как символ комментария.

Группирование аргументов с помощью двойных кавычек

Обычно каждое поле аргумента заканчивается последующим пробелом, однако двойные кавычки можно использовать для задания аргументов с пробелами внутри. Если поле аргумента начинается с двойных кавычек, то этот аргумент не будет заканчиваться пробелом (включая символы новой строки) или точкой с запятой (использование точек с запятой описано ниже). Такой аргумент будет заканчиваться только следующим символом двойных кавычек. Символы двойных кавычек не будут входить в значение аргумента. Например, команда

set a " This is a single argument" передаст команде set  два аргумента: a и ▒This is a single argument▓. Выполнение подстановок команд, подстановок переменных и подстановок с обратным слешем внутри двойных кавычек будет сохранено. Если первый символ в поле команды не двойные кавычки, тогда при анализе этого поля двойные кавычки не имеют специальной интерпретации.

Группирование аргументов с помощью фигурных скобок

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

set a {xyz a {b c d}} команда  set  получит два аргумента: a и ▒xyz a {b c d}▓. Когда действуют двойные кавычки или фигурные скобки, парная закрывающая скобка или кавычки не должны обязательно быть на той же строке, что и ее открывающая. В этом случае символ новой строки будет включен в поле аргумента вместе со всеми остальными символами до закрывающей скобки или кавычек. Например, команда eval использует один аргумент, представляющий собой строку команды: eval  вызывает ИНТЕРПРЕТАТОР Tcl для выполнения командной строки. Команда
eval { set a 22
set b 33
}
присвоит значение ▒22▓ переменной a и значение ▒33▓ ≈ переменной ▒b▓. Если первый символ поля команды ≈ не открывающая фигурная скобка, то ни открывающая, ни закрывающая фигурные скобки в этом поле не будут интерпретироваться специальным образом (кроме случая подстановки переменной, об этом рассказано ниже).

Подстановка команд со скобками

При появлении в поле команды открывающей квадратной скобки выполняется подстановка команды. Все символы внутри скобок считаются командой, и она исполняется немедленно. Затем результат этого исполнения подставляется вместо текста в скобках. Например, рассмотрим команду

set a [set b] Когда у команды set задан только один аргумент, тогда это есть имя переменной, и set возвращает значение этой переменной. В этом случае, если переменная b имеет значение ▒foo▓, то предыдущая команда эквивалентна команде
set a foo Квадратные скобки можно использовать более сложными способами. Например, если переменная b имеет значение ▒foo▓, а переменная c имеет значение ▒gorp▓, то команда
set a xyz[set b].[set c] эквивалентна команде set a xyzfoo.gorp Команда в квадратных скобках может содержать несколько команд, разделенных обычным образом ≈ строками или точками с запятой. В этом случае для подстановки используется значение последней команды. Например, последовательность команд
set a x[set b 22
expr $b+2]x
эквивалентна команде set a x24x Если поле заключено в фигурные скобки, то квадратные скобки и символы между ними не интерпретируются специальным образом, а передаются в аргумент без изменения.

Подстановка переменных с $

Символ доллара ▒$▓ можно использовать в качестве краткой формы для подстановки переменных. Если у аргумента, не заключенного в фигурные скобки, имеется символ ▒$▓, то выполняется подстановка переменной. Символы после ▒$▓ вплоть до первого символа, не являющегося цифрой, буквой или подчеркиванием, считаются именем переменной, и строковое значение этой переменной подставляется вместо ее имени. Например, если переменная foo имеет значение ▒test▓, то команда

set a $foo.c эквивалентна команде set a test.c Существует две специальные формы для подстановки переменных. Если следующим после имени переменной является открывающая скобка, то переменная считается именем массива, и все символы между открывающей скобкой и следующей закрывающей скобкой считаются индексом внутри этого массива. Команды и переменные, используемые в качестве индекса, обрабатывается перед операцией извлечения элемента массива. Например, если переменная x есть массив и один его элемент по имени first имеет значение ▒87▓, а второй по имени 14 ≈ значение ▒more▓, то команда
set a xyz$x(first)zyx эквивалентна команде set a xyz87zyx Если переменная index имеет значение ▒14▓, то команда
set a xyz$x($index)zyx эквивалентна команде set a xyzmorezyx Более подробно о массивах  .

Вторая специальная форма для переменных имеет место тогда, когда после символа доллара следует открывающая фигурная скобка. В этом случае имя переменной состоит из всех символов, заключенных между фигурными скобками. Ссылки на массив в таком случае невозможны: предполагается, что такое имя есть имя скалярной переменной. Например, если переменная foo имеет значение ▒test▓, то команда

set abc${foo}bar эквивалентна команде set abctestbar В аргументе, заключенном в фигурные скобки, не выполняется подстановка переменных: символ доллара и имя переменной передаются аргументу без изменения.

Аббревиатура с символом доллара есть просто сокращенная форма: ▒$a▓ полностью эквивалентна ▒[set a]▓ и используется только для удобного сокращения количества печатаемых символов.

Разделение команд точкой с запятой

Обычно каждая команда занимает одну строчку (команда заканчивается символом новой строки). Символ точки с запятой также считается разделителем команд: можно поместить несколько команд в одной строке, разделив их точками с запятой. Точки с запятой не считаются разделителями команд, если они находятся внутри фигурных скобок или двойных кавычек.

Подстановки с обратным слешем

Обратный слеш можно использовать для ввода непечатаемых символов в поля команд и для вставки специальных символов (например, фигурных скобок или двойных кавычек) в поля без описанной выше специальной интерпретации этих символов. Ниже перечислены различаемые интерпретатором Tcl последовательности с обратным слешем. В каждом случае последовательность с обратным слешем замещается указанным символом:

второй аргумент команды setбудет ▒{x[\0yza▓.

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

Если аргумент заключен в фигурные скобки, то последовательности с обратным слешем внутри аргумента будут распознаны, но подстановки не будут выполнены (за исключением пары обратный слеш ≈ новая строка): последовательности с обратным слешем передаются в аргумент как есть, без какой-либо специальной интерпретации символов в последовательностях. В частности, в такой ситуации фигурные скобки не означают поиска соответствующей парной скобки, заканчивающей аргумент. Например, в команде второй аргумент команды set будет ▒\{abc▓.

Данный механизм обратного слеша недостаточен для создания аргумента абсолютно любой структуры; он только обеспечивает наиболее общие случаи. Для создания особенно сложного аргумента, возможно, самым простым вариантом будет использование команду format совместно с подстановкой команды.

Выражения

Вторая смысловая форма строк в Tcl ≈ это выражения. Несколько команд, таких как expr, for и if, считают один или несколько своих аргументов выражениями и для вычисления их значения вызывают процессоры выражений Tcl (Tcl_ExprLong, Tcl_ExprBoolean, и т.д.). Разрешенные в Tcl выражениях операторы составляют подмножество операторов, разрешенных в выражениях С, и они имеют такой же смысл и приоритет выполнения, как и соответствующие им операторы С. Почти всегда значением выражения является число (целое или с плавающей запятой). Например, выражение

8.2 + 6
дает результат 14,2. Выражения Tcl отличаются от выражений С способом описания операндов, а также тем, что поддерживают нечисловые операнды и сравнение строк.
Выражение Tcl состоит из комбинации операндов, операторов и скобок. Между ними всеми можно ставить пробелы, потому что при вычислении значения пробелы игнорируются. По возможности, все операнды интерпретируются как целые числа, если не задано иное. Целые числа могут иметь вид десятичного числа (обычно), восьмеричного (если первая цифра числа есть 0) или шестнадцатеричного (если первые два символа числа ≈ ). Если операнд не подпадает ни под один из названных форматов, он считается числом с плавающей запятой, если это возможно. Числа с плавающей запятой можно задавать любым из способов, воспринимаемым совместимым с ANSI компилятором С. Исключение составляет запрет в большинстве версий на суффиксы f, F, l, и L. Примеры правильных чисел с плавающей запятой: 2.1, 3., 6e4, 7.91e+16. Если числовая интерпретация невозможна, то операнд считается строковым и работать с ним может только ограниченный набор операторов.

Операнды могут быть заданы одним из следующих способов:

  • командой Tcl, заключенной в угловые скобки. Команда будет выполнена, и ее результат будет использован в качестве операнда.

  • Еще один способ задания операндов назван в разделе "Встроенные команды Tcl".

    Если в выражении имели место подстановки (например, внутри двойных кавычек), то они будут обработаны процессором выражения. Хотя анализатор команд тоже может выполнить свою часть подстановок (дополнительную серию подстановок) до вызова процессора выражения. Поэтому обычно, во избежание выполнения анализатором команд подстановок в содержимое выражения, лучше всего заключать выражение в фигурные скобки.

    В качестве примеров рассмотрим простые выражения, в которых переменная a имеет значение ▒3▓, а значение переменной b есть ▒6▓. Тогда выражение в левой части каждой строки даст значение в ее правой части:
    3.1 + $a 6.1

    2 + " $a.$b" 5.6

    4*[llength " 6 2" ] 8

    {word one} < " word $a" 0

    Списки

    Третьей основной смысловой формой строк в Tcl являются списки. Список ≈ это обычная строка с подобной списку структурой, состоящей из полей, разделенных промежутками. Например, строка ▒Al Sue Anne John▓ есть список, имеющий четыре элемента (поля). Основная структура списков аналогична структуре командных строк, за исключением того, что символ новой строки служит таким же разделителем, как и пробел с табуляцией. Для списков действуют такие же правила в отношении фигурных скобок, двойных кавычек и обратных слешей, как и для команд. Например, строка

    есть список из трех элементов: ▒a▓, ▒b c▓ и ▒d e {f g h}▓. Всегда, когда из списка извлекается элемент, действуют те же правила относительно фигурных скобок, двойных кавычек и обратных слешей, что и для команд. Таким образом, когда из списка в примере будет извлечен третий элемент, результат будет ▒d e {f g h}▓ (потому что при извлечении произошло только отбрасывание внешней пары фигурных скобок). В отношении списков никогда не выполняются подстановки команд и переменных (по крайней мере, командами обработки списков: список всегда может быть передан интерпретатору Tcl для обработки).

    Команды 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_OK Этот код нормального завершения, возвращается при успешном выполнении команды. Строка содержит возвращаемое командой значение. TCL_ERROR Указывает на имевшую место ошибку; строка содержит сообщение, описывающее ошибку. Дополнительно к этому, глобальная переменная errorInfo будет содержать словесную информацию о командах и процедурах, выполнявшихся при возникновении ошибки; глобальная переменная errorCode будет содержать машинно-читаемые данные об ошибке, если таковые доступны. Более подробно об этом рассказано в разделе ⌠4.18■. TCL_RETURN Указывает на то, что была вызвана команда return, и что текущая процедура (или команда верхнего уровня, или команда source) должна немедленно завершиться. Строка содержит возвращаемое значение для процедуры или команды. TCL_BREAK Указывает на то, что была вызвана команда break, и поэтому самый внутренний цикл должен немедленно прекратиться. Строка должна всегда оставаться пустой. TCL_CONTINUE Указывает на то, что была вызвана команда continue, и поэтому самый внутренний цикл должен приступить к следующей итерации. Строка должна всегда оставаться пустой.

    Обычно программистам на Tcl не нужно задумываться о кодах возврата, поскольку почти всегда возвращается TCL_OK. Если команда возвратила что-либо иное, то Интерпретатор Tcl немедленно останавливает обработку команд и возвращается к вызвавшему его событию. Если в некоторый момент имеется несколько вложенных вызовов интерпретатора Tcl, то обычно каждая из вложенных команд вернет ошибку вызывающему ее субъекту, и таким образом сообщение об ошибке достигнет самого верхнего уровня в приложении. После этого приложение выведет пользователю сообщение об ошибке.

    В некоторых случаях отдельные команды обрабатывают ошибочные ситуации сами и не сообщают о них наверх. Например, команда for проверяет наличие кода возврата TCL_BREAK и если находит его, то прекращает выполнение тела цикла и возвращает код TCL_OK вызвавшему субъекту. Также команда forобрабатывает коды TCL_CONTINUE, а Интерпретатор процедур обрабатывает коды TCL_RETURN. Команда catch позволяет программам Tcl перехватывать ошибки и обрабатывать их без последующего прекращения интерпретации команд.

    Процедуры

    Tcl позволяет расширить командный интерфейс за счет определения процедур. Процедуру Tcl можно вызвать для исполнения так же, как и любую другую команду Tcl (у нее есть имя и она получает один или более аргументов). Единственным отличием является то, что она не состоит из кода С, скомпонованного внутрь программы: это строка, содержащая одну или более команд Tcl. Подробнее об определении и вызове процедур рассказано в разделе "Встроенные комнды Tcl" (proc).

    Переменные: скалярные и массивы В Tcl можно определять переменные и использовать их значения при помощи подстановки переменных с символом ▒$▓, команды set, или нескольких иных механизмов. Нет необходимости специально определять переменные: новая переменная будет автоматически определена сразу же, как только будет использовано новое имя переменной. Tcl поддерживает переменные двух типов: скалярные и массивы (векторные). Скалярная переменная имеет только одно значение в каждый момент времени, тогда как переменная-массив может содержать любое количество элементов, имеющих имя (обычно называемое ⌠индексом⌠) и значение. Индексами массива могут быть произвольные строки, необязательно числового вида. Для ссылки на индексы в командах Tcl используются круглые скобки. Например, команда ▒set x(first) 44▓ изменит значение элемента массива x по имени first на новое: ▒44▓. Двумерные массивы можно имитировать использованием индексов, состоящих из нескольких составленных вместе частей. Например, команды

    set a(2,3) 1

    set a(3,6) 2

    задают элементы массива а с индексами ▒2,3▓ и ▒3,6▓. В общем, элементы массивов можно употреблять везде, где можно употреблять скалярные переменные. Недопустимо наличие скалярной переменной и массива с одним и тем же именем. Нельзя обращаться к скалярной переменной как к элементу массива. Для преобразования скалярной переменной в массив и наоборот следует удалить существующую переменную при помощи команды unset. Команда array предоставляет набор средств для работы с массивами, в том числе получение списка всех элементов массива и просмотр значений элементов по одному. Переменные могут быть локальными или глобальными. Если имя переменной используется тогда, когда не выполняется процедура, то оно автоматически относится к глобальной переменной. Имена переменных, используемых внутри процедуры, обычно ссылаются на локальные переменные, ассоциированные с данным выполнением этой процедуры. Локальные переменные удаляются по окончании работы процедуры. При выполнении процедуры для указания на то, что имя является именем глобальной переменной, может использоваться команда global (она в некотором смысле аналогична extern в С).

    Встроенные команды

    Библиотека Tcl предоставляет набор встроенных команд. Эти команды будут доступны в любом приложении, использующем Tcl. Дополнительно к этим командам приложения могут определять свои собственные команды, а также команды, определенные в виде процедур Tcl. Полный аннотированный список встроенных команд приведен в разделе "Встроенные команды Tcl".
    . В нем слова, выделенные полужирным шрифтом, представляют собой имена команд и прочие слова, которые следует передавать интерпретатору без изменения. Слова, выделенные курсивом, представляют собой метасимволы, они обозначают собой некоторое возможное значение, допустимое для ввода. Многоточие указывает на возможность подстановки произвольного количества дополнительных аргументов или групп аргументов, в том же формате, что и предшествующий аргумент или группа.

    Встроенные переменные

  • env
  • errorCode
  • errorInfo
  • Библиотека Tcl автоматически создает и управляет следующими глобальными переменными. Во всех случаях, кроме специально оговоренных, эти переменные должны использоваться приложениями и пользователями в режиме только для чтения.

    env

    errorCode

    errorInfo