Синтаксис Информа
Описание всех конструкций языка Inform 6, с дополнениями, касающихся русской версии.
Значения
Значения в Информе бывают следующих типов:
- Численные:
- Десятичные:
451 - Шестнадцатеричные:
$1C3 - Двоичные:
$$111000011
- Десятичные:
- Действие:
##Look - Символ:
'ъ' - Словарное слово:
'хлопушк/а'. Можно использовать как двойные, так и одинарные кавычки. - Строка, в двойных кавычках:
"Новогодняя хлопушка.". Есть набор специальных символов, в частности:^— перенос строки.~— типографские кавычки ("). Но в русском языке принято использовать кавычки-ёлочки: « и » (в Z-машине это@<<и@>>).@@64— «cобачка», @.@@92— обратный слеш, \.@@94— карет, ^.@@126— тильда, ~.
Имена
Имена есть у констант, переменных, массивов, классов, свойств, объектов, атрибутов, функций и меток.
Имена должны быть на латинице, могут содержать цифры и знак подчёркивания, не могут начинаться с цифры и должны быть длиной не более 32 символов.
Константы
Константа — это значение, которое не изменяется во время игры. По умолчанию константа равна 0.
Constant имя_константы;
Constant имя_константы = выражение;
Есть несколько стандартных констант: true (1), false (0), nothing (0), NULL (-1).
Переменные и массивы
Переменные и массивы могут изменяться в процессе игры, и по умолчанию равны 0.
Глобальные переменные:
Global имя_переменной;
Global имя_переменной = выражение;
Массив машинных слов (word). Слово в Glulx — 4 байта, в Z-машине — 2 байта. Элементы массива длиной N доступны через массив-->0, массив-->1, ... массив-->(N-1).
Array имя_массива ––> N;
Array имя_массива ––> выражение1 выражение2... выражениеN;
Array имя_массива ––> "строка";
Массив-таблица. Элементы таблицы длиной N доступны через массив-->1, массив-->2, ... массив-->N, при этом массив-->0 будет равно N.
Array имя_массива table N;
Array имя_массива table выражение1 выражение2... выражениеN;
Array имя_массива table "строка";
Байтовый массив. Элементы массива длиной N доступны через массив->0, массив->1, ... массив->(N-1).
Array имя_массива –> N;
Array имя_массива –> выражение1 выражение2... выражениеN;
Array имя_массива –> "строка";
Массив-строка. Элементы строки длиной N доступны через массив->1, массив->2, ... массив->N, при этом массив->0 будет равно N.
Array имя_массива string N;
Array имя_массива string выражение1 выражение2... выражениеN;
Array имя_массива string "строка";
Переменные также есть у объектов (как свойства) и у процедур (локальные переменные).
Выражения и операторы
Арифметические и логические операции:
p + qсложение,p - qвычитание,p * qумножение,p / qцелочисленное деление,p % qостаток от деления,p++прибавляет единицу к p и возвращает предыдущее значение,++pприбавляет единицу к p и возвращает новое значение,p--вычитает единицу от p и возвращает предыдущее значение,--pвычитает единицу от p и возвращает новое значение,p & qпобитовое И,p | qпобитовое ИЛИ,~pпобитовое НЕ.
Условные выражения возвращают true или false, в зависимости от того, выполняется ли условие. q может быть списком, например q1 or q2 or... qN.
-
p == qp равно q, -
p ~= qp не равно q, -
p > qp больше q, -
p < qp меньше q, -
p >= qp больше либо равно q, -
p <= qp меньше либо равно q, -
p ofclass qобъект p является объектом класса q, -
p in qобъект p является непосредственным дочерним для объекта q, -
p notin qобъект p не является непосредственным дочерним для объекта q, -
p provides qу объекта p есть свойство q, -
p has qу объекта p есть атрибут q, -
p hasnt qу объекта p нет атрибута q. -
p && qвозвращаетtrueесли оба значенияtrue(ненулевое), -
p || qвозвращаетtrueесли хотя бы одно из значенийtrue(ненулевое), -
~~pвозвращаетtrueесли p равноfalse(нулю).
Чтобы проверить, является ли объект q дочерним для объекта p с рекурсией (чтобы проверялись дети детей и т.д.), используйте IndirectlyContains(p,q).
Чтобы найти ближайшего родителя для двух объектов: CommonAncestor(p,q). Если его нет, вернётся nothing.
Генератор случайных чисел:
random(N)вернёт случайное число от 1 до N.random(значение, значение, значение...)вернёт одно из значений случайным образом.
Классы и объекты
Класс — это шаблон для объектов со схожими свойствами.
Class имя_класса(N)
class наследуемый_класс наследуемый_класс... наследуемый_класс
with свойство,
...
свойство,
has атрибут атрибут... атрибут;
N необходимо при динамическом создании объектов во время игры и указывает их максимальное количество.
Объект может быть самостоятельным, или наследован от класса или нескольких классов.
Object [->...] имя_объекта "текстовое имя" объект_родитель
class наследуемый_класс наследуемый_класс... наследуемый_класс
with свойство,
...
свойство,
has атрибут атрибут... атрибут;
Вместо Object можно сразу использовать имя класса. Имя объекта, текстовое имя, стрелки и родитель — необязательны. Нельзя использовать одновременно стрелки и объект_родитель.
Каждая из секций — class, with и has (а также редко используемая private) — опциональна, и они могут идти в любом порядке.
Чтобы определить класс объекта (Class, Object, Routine, String или nothing), используйте metaclass(объект).
Секция has
Каждый атрибут в списке:
- либо выставлен:
атрибут, - либо снят:
~атрибут.
Чтобы изменить атрибуты в процессе игры: give объект атрибут ... атрибут.
Секция with
Каждое свойство может включать выражение, строку или встроенную процедуру (или несколько).
свойство
свойство значение
свойство значение значение... значение
Доступ к свойству осуществляется через объект.свойство, либо изнутри самого объекта через self.свойство.
Несколько свойств образуют массив свойств (таким обычно является name). В этом случае объект.#свойство возвращает количество байт в массиве, а к записям можно обратиться через объект.&свойство-->0, объект.&свойство-->1 и т.д.
Через объект.класс::свойство можно обратиться к свойству, наследованному из класса. Это вернёт изначальное значение, до того как оно было изменено в объекте.
Работа с деревом объектов
move объект to новый_родитель— перемещает объект по дереву;remove объект— удаляет объект;parent(объект)— возвращает родителя объекта (илиnothing);child(объект)— возвращает первый дочерний объект (илиnothing);sibling(объект)— возвращает соседний дочерний объект родителя (илиnothing);children(объект)— возвращает количество непосредственных дочерних объектов.
Обмен сообщениями
класс.remaining()— сколько ещё можно создать объектов этого класса;класс.create()— создаёт и возвращает новый объект класса. Возвращаетnothing, если создать объект нельзя;класс.destroy(объект)— удаляет динамически созданный объект. Статически созданные объекты так удалить нельзя;класс.recreate(объект)— удаляет динамически созданный объект и создаёт его заново;класс.copy(объект1,объект2)— копирует свойства и атрибуты из первого объекта во второй;объект.property(арг1,aрг2, ... aрг7)— вызывает процедуру-свойство объекта с параметрами;процедура.call(арг1,aрг2, ... aрг7)— вызывает процедуру с параметрами. Это аналогичнопроцедура(арг1,aрг2, ... aрг7);строка.print()— выводит строку;строка.print_to_array(массив)— выводит строку в байтовый массив.
Инструкции
Каждая инструкция должна заканчиваться точкой с запятой: ;.
переменная = выражение;
Блок инструкций — это либо одна инструкция, либо несколько, окружённых фигурными скобками { и }.
Комментарии в коде начинаются с восклицательного знака !.
Множественное присваивание можно делать так:
переменная = переменная = ... = выражение;
переменная = выражение, переменная = выражение, ... ;
Процедуры
У процедуры может быть до 15 локальных переменных. По умолчанию на каждом вызове они изначально равны 0. Рекурсия работает.
Самостоятельная процедура
- имеет имя, по которому её нужно вызывать,
процедура(). Также можно вызвать её не напрямую черезindirect(процедура, арг1, арг2, ... арг 7); - может принимать аргументы,
процедура(арг1, арг2, ... арг 7), которые инициализируют локальные переменные; - возвращает
trueв самом конце при достижении];.
[ имя_процедуры
лок_переменная лок_переменная... лок_переменная;
инструкция;
инструкция;
...
инструкция;
];
Вложенная процедура
- не имеет имени, является свойством объекта. Её можно вызвать явно через
объект.свойство(); - принимает аргументы, только если её вызвать явно;
- возвращает
falseв самом конце при достижении];.
свойство [
лок_переменная лок_переменная... лок_переменная;
инструкция;
инструкция;
...
инструкция;
];
Процедуры возвращают одно значение, либо по достижении ];, либо явно:
return выражение;return;— возвращаетtrue;rtrue;— возвращаетtrue;rfalse;— возвращаетfalse.
Ветвление
Для проверки условий используются if (если условие выполнено) и else (если не выполнено):
if (выражение)
блок_инструкций
if (выражение)
блок_инструкций
else
блок_инструкций
Если нужно выполнить код в зависимости от значения выражения, используется switch:
switch (выражение) {
значение: инструкция;... инструкция;
значение: инструкция;... инструкция;
...
default: инструкция;... инструкция;
}
где каждое значение может быть:
- константой
- интервалом констант:
10 to 42; - перечислением констант через запятую.
Если очень нужно, есть возможность прыгать по меткам:
jump метка;
...
.метка; инструкция;
Циклы
Цикл с предусловием:
while (выражение)
блок_инструкций
Цикл с постусловием:
do
блок_инструкций
until (выражение)
Цикл со счётчиком:
for (установка_переменной : условие : изменение_переменной)
блок_инструкций
Выполнение кода для всех объектов в игре (объект помещается в переменную):
objectloop (переменная)
блок_инструкций
Выполнение кода для всех объектов, удовлетворяющих условию:
objectloop (условие)
блок_инструкций
Чтобы выйти из текущего цикла:
break;
Чтобы начать следующую итерацию цикла:
continue;
Вывод
Вывести список значений:
print значение, значение, ... значение;
Вывести список значений с переносом строки после каждого значения, после чего вернуть true:
print_ret значение, значение, ... значение;
Если первое (или единственное) значение это строка, то print_ret можно опустить:
"строка", значение, ... значение;
Каждое значение может быть выражением, строкой или «правилом».
Выражение выводится как целочисленное значение.
Строка выводится как текст.
Среди правил есть следующие:
(number) значение— вывести число словами.(char) значение— вывести сиивол с кодом числа.(string) адрес— вывести строку по адресу(name) объект— вывести имя объекта
Падежные формы со строчной и заглавной букв соответственно:
(cNom) объекти(CCNom) объект— именительный (Nominative).(cAcc) объекти(CCAcc) объект— винительный (Accusative).(cGen) объекти(CCGen) объект— родительный (Genitive).(cDat) объекти(CCDat) объект— дательный (Dative).(cIns) объекти(CCIns) объект— творительный (Instrumental).(cPre) объекти(CCPre) объект— предложный (Prepositive).
Вывести перевод строки:
new_line;
Несколько способов выделить текст:
style bold;
style underline;
style reverse;
...
style roman;
Глаголы и действия
Для создания нового глагола:
Verb 'глагол' 'глагол'... 'глагол'
* токен токен... токен –> действие
* токен токен... токен –> действие
...
* токен токен... токен –> действие;
где вместо Verb может быть Verb meta, вместо действие — действие reverse.
Токены опциональны и бывают следующих видов:
'слово'— конкретное слово;'слово1'/'слово2'/...— любое из перечисленных слов;атрибут— объект с указанным атрибутом;creature— объект с атрибутомanimate;cAcc_creat— объект с атрибутомanimate, в винительном падеже;cGen_creat— объект с атрибутомanimate, в родительном падеже;cDat_creat— объект с атрибутомanimate, в дательном падеже;cIns_held— объект в инвентаре игрока, в творительном падеже;cAcc_held— объект в инвентаре игрока, в винительном падеже;cGen_held— объект в инвентаре игрока, в родительном падеже;cNom_noun— объект в области видимости, в именительном падеже;cAcc_noun— объект в области видимости, в винительном падеже;cGen_noun— объект в области видимости, в родительном падеже;cDat_noun— объект в области видимости, в дательном падеже;cIns_noun— объект в области видимости, в творительном падеже;cPre_noun— объект в области видимости, в предложном падеже;noun=процедура— объект, для которого процедура вернётtrue;scope=процедура— объект, который попадёт в сформированную процедурой область видимости;multiheld— один или более объектов в инвентаре игрока;cAcc_multiheld— один или более объектов в инвентаре игрока, в винительном падеже;multi— один или более объектов в области видимости;cAcc_multi— один или более объектов в области видимости, в винительном падеже;multiexcept— то же, чтоmulti, но без указанного объекта;cAcc_multiexcept— то же, чтоmulti, но без указанного объекта, в винительном падеже;multiinside— то же, чтоmulti, но без объектов внутри указанного;cAcc_multiinside— то же, чтоmulti, но без объектов внутри указанного, в винительном падаже;topic— любые слова;number— любое число;функция— отдельная функция для парсинга.
Чтобы создать синоним для имеющегося глагола:
Verb 'глагол' 'глагол'... = 'существующий_глагол';
Чтобы изменить существующий глагол:
Extend 'существующий_глагол' last
* токен токен... токен –> действие
* токен токен... токен –> действие
...
* токен токен... токен –> действие;
где вместо Extend может быть Extend only, last можно опустить или указать first или replace.
Чтобы явно вызвать действие в коде (объекты опциональны):
<действие объект второй_объект>;
Чтобы явно вызвать действие и вернуть true:
<<действие объект второй_объект>>;
Полезные директивы
Можно переопределить параметры компиляции в начале файла:
!% список_параметров_компилятора;
Условная компиляция:
Ifdef имя;
Ifndef имя;
Iftrue выражение;
Iffalse выражение;
...
Ifnot;
...
Endif;
Вывести сообщение при компиляции:
Message "строка";
Импортировать исходный файл из пути библиотеки:
Include "исходный_файл";
Импортировать исходный файл из папки, в которой находится текущий файл:
Include ">исходный_файл";
Заменить библиотечную процедуру:
Replace имя_процедуры;
Указать номер релиза (по умолчанию 1), серийный номер (по умолчанию сегодняшний день в формате ГГММДД), формат статусной строки:
Release выражение;
Serial "ггммдд";
Statusline score;
Statusline time;
Создать новый атрибут:
Attribute имя_атрибута;
Создать новое свойство, которое будет у всех объектов:
Property имя_свойства;
Property имя_свойства выражение;