Введение
BPL (Bot programming language) - это встроенный язык выражений для конструктора ботов версии 3. Программа на этом языке размещается в блоках операций, условных блоках, триггерах и т.д. и представляет собой запись одного или нескольких выражений разделённых между собой символом новой строки или, опционально, точкой с запятой ";".
Каждое выражение языка представляет собой вычисляемую (или исполняемую) инструкцию (или инструкции) для бота. Любое выражение при этом имеет значение и может быть включено в качестве подвыражения в любое другое выражение по желанию программиста.
BPL не содержит каких-либо конструкций отвечающих за поток управления программой. За это отвечает графическая составляющая конструктора ботов.
Кодировка кода
Текст на BPL это Unicode текст в кодировке UTF-8. Строковые литералы могут содержать произвольные символы Unicode. Идентификаторы (см. ниже) могут включать в себя русские буквы.
Символы
Далее в описании грамматики языка будут использоваться следующие термы:
newline = /* символ Юникода U+000A */ . unicode_char = /* произвольный символ Юникода, за исключением newline */ . unicode_letter = /* символ Юникода обозначаемый букву */ . unicode_digit = /* символ Юникода обозначаемый цифру */ .
Буквы и цифры
Символ подчёркивания считается буквой в нижнем регистре:
letter = unicode_letter | "_" . decimal_digit = "0" … "9" . hex_digit = "0" … "9" | "A" … "F" | "a" … "f" .
Лексические элементы
Токены
Любое выражение состоит из одного или нескольких слов или лексических элементов которые также называются токенами. В BPL выделяется пять групп токенов:
- Пробельные символы
- Комментарии
- Идентификаторы
- Операторы и символы пунктуации
- Литералы
Пробельные символы
Пробельными считаются символы пробела (U+0020), новой строки ()U+000A), возврата каретки (U+000D), а также горизонтальной табуляции (U+0009). Обычно пробельные символы игнорируются кроме случаев когда они разделяют два токена с тем чтобы предотвратить их трактовку в качестве другого токена.
Комментарии
При записи выражений можно указывать комментарии – участки программы, которые не участвуют в вычислениях, а выполняют лишь информационную функцию. Есть два вида комментариев:
- Однострочные. Такие комментарии начинаются с символов "//" и заканчиваются окончанием строки.
- Многострочные. Начало многострочного комментария начинается с символов "/*" и заканчивается символами "*/".
// Это однострочный комментарий $x = time() /** * А это уже * многострочный * комментарий */ say("Time is " + $x)
Идентификаторы
Идентификаторами являются названия функций, типов и переменных. Идентификатор состоит из букв (letter) и цифр (unicode_digit). Первым символом идентификатора должна быть буква.
identifier = letter { letter | unicode_digit } .
Примеры идентификаторов:
xyz _x9 someBigIdentifier тоже_идентификатор
Некоторые идентификаторы являются предопределёнными.
Операторы и символы пунктуации
Следующие символы представляют собой операторы:
Математические и строковые | + | - | * | / | % | \ | ** | & | | | ^ | >> | << | <<< | >>> | :: | ~ | ! |
Комбинированные с присваиванием | += | -= | *= | /= | %= | \= | **= | &= | |= | ^= | >>= | <<= | <<<= | >>>= | ::= | ||
Сравнение | == | != | > | < | >= | <= | && | || | |||||||||
Преобразование и проверка типов | is | !is | as | ?as | to | ?to | |||||||||||
Обращение к переменным | $ | @ | # | ||||||||||||||
Безопасное выполнение | ? | ?? | |||||||||||||||
Инкремент и декремент | ++ | -- | |||||||||||||||
Присваивание | = | := | |||||||||||||||
Создание итератора | ... |
Пунктуационные знаки:
( | ) | [ | ] | { | } |
. | , | : | ; | ||
' | " | ||||
_ |
Точка с запятой
Символ ";" используется в качестве разделителя BPL выражений находящихся на одной строке. Его можно опустить, если последний токен выражения является одним из следующих:
- идентификатор;
- числовой, строковый, булев литерал или nil;
- знаки ")", "]" и "}".
Литералы
Литералы это значения разных типов данных встречающихся в тексте программы в качестве констант.
Пустой литерал
Специальный литерал обозначающий отсутствие значения. Представлен словом nil.
Булевы литералы
Булевы или логические литералы это значения двух видов: ИСТИНА и ЛОЖЬ. Представлены они соответственно двумя специальными словами: true и false.
Целочисленные литералы
Это последовательность цифр представляющая собой целое число. Целочисленный литерал может быть представлен в шестнадцатеричном формате, если имеет префикс "0x" или "0X".
Для улучшения читабельности можно использовать символ "_" для разделения последовательных цифр в числе или для отделения префикса от числа:
42 4_2 0xBadFace 0xBad_Face 0x_67_7a_2f_cc_40_c6 170141183460469231731687303715884105727 170_141183_460469_231731_687303_715884_105727 _42 // идентификатор, но не литерал 42_ // ошибка: _ должен разделять последовательные цифры 4__2 // ошибка: два подряд идущих _ 0_xBadFace // ошибка: _ должен разделять последовательные цифры
Дробно-числовые литералы
Дробно-числовые литералы состоят из целой части (десятичные цифры), десятичной точки (.), дробной части (десятичные цифры) и экспоненты (буква "e" или "E" за которой следует опциональный знак (+ или -) и далее десятичные цифры). Целая часть, либо дробная часть могут быть опущены. Десятичная точка, либо экспонента могут быть опущены. Значение экспоненты exp увеличивает мантиссу в 10^exp раз.
Как и в случае с целочисленными литералами можно использовать "_" для улучшения читабельности:
0. 72.40 2.71828 1.e+0 6.67428e-11 1E6 .25 .12345E+5 1_5. // == 15.0 0.15e+0_2 // == 15.0 1_.5 // ошибка: _ должен разделять последовательные цифры 1._5 // ошибка: _ должен разделять последовательные цифры 1.5_e1 // ошибка: _ должен разделять последовательные цифры 1.5e_1 // ошибка: _ должен разделять последовательные цифры 1.5e1_ // ошибка: _ должен разделять последовательные цифры
Строковые литералы
Строковый литерал представляет собой последовательность символов (unicde_char). Есть два вида строковых литеров: неинтерпретируемые и интерпретируемые.
Неинтерпретируемые строковые литералы представляют собой любую последовательность символов Юникода (unicode_char)? кроме newline, заключённую в одинарные кавычки. При этом символ одинарной кавычки и символ обратного слэша должны экранироваться.
Интерпретируемые строковые литералы создаются с помощью двойных кавычек и могут содержать любые символы Юникода (кроме newline), а также специальные последовательности символов. Экранированию подлежат символы двойной кавычки и обратный слэш.
Переменные
Для хранения данных в сценариях ботов применяются переменные. Переменная представляет собой именованный участок памяти бота. Она создаётся при первом своем использовании в каком-либо блоке операция. При этом значением по умолчанию для всех переменных является nil.
Существует три вида переменных, различающихся своей областью видимости:
- Переменные, видимые в пределах одного модуля в одном потоке.
Доступны для чтения и записи. Названия таких переменных начинаются с символа $. Такие переменные удобно использовать для хранения значений промежуточных операций и вычислений. - Переменные, видимые в пределах одного модуля в разных потоках.
Доступны для чтения и записи. Названия переменных уровня модуля начинаются с символа #. Поскольку такие переменные видны во всех потоках бота их удобно использовать для взаимодействия между потоками. - Глобальные переменные или переменные окружения.
Автоматически задаваемые переменные, которые видны во всех потоках всех модулей бота. Эти переменные доступны только для чтения и хранят информацию о глобальном контексте работы бота. Их имена начинаются с символа @.
// Переменные $p и $r доступны только в потоке, в котором они определены $p = 2 * 3.14 * $r // Эта переменная доступна во всех потоках в пределах текущего модуля // (модуля, в котором находится блок операций, в котором определена переменная). #count = queue.size() // @communicationType глобальная переменная только для чтения. Доступна везде. $isChat = @communicationType == "TEXT"
Имена переменных могут содержать только цифры, английские и русские буквы, а также символ подчёркивания. Т.е. вы не можете назвать переменную каким-то словом, содержащим пробел или символ отличный от символов русского и английского языков. Тем не менее, существует способ использовать любое название. Для этого необходимо заключить название переменной в круглые скобки.
$('日本') = 123 // Создали переменную c именем 日本 $x = $('日本') // $x теперь равна 123 $(math.rand(1, 2)) = 0 // Динамически создаём переменную с именем 1 или 2 и присваиваем ей значение 0