Синтаксис Информа
Описание всех конструкций языка 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 == q
p равно q, -
p ~= q
p не равно q, -
p > q
p больше q, -
p < q
p меньше q, -
p >= q
p больше либо равно q, -
p <= q
p меньше либо равно 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 имя_свойства выражение;