Язык μLua

μLua — модельный императивный язык программирования, являющийся строгим подмножеством языка Lua.

Пример программы для вычисления факториала:

factorial.lua
n = input()
result = 1
while n > 0 do
    result = result * n
    n = n - 1
end
print(result)

Интерпретатор Lua

Вы можете использовать интерпретатор Lua для проверки вашей реализации языка:

lua -e 'function input() return io.read("*number") or error() end' program.lua

Мы здесь также определяем функцию input, поскольку ее нет в стандартной библиотеке Lua.

Синтаксис

Конкретный синтаксис языка определяется грамматикой, записанной в расширенной форме Бэкуса-Наура.

Лексические соглашения

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

Идентификаторы

Идентификаторы являются непустыми строками из букв латинского алфавита (A-Z, a-z), цифр и нижних подчеркиваний, не начинающимися с цифры.

Предполагается, что ключевые слова не могут использоваться в качестве идентификаторов.

Ключевые слова

nil, false, true, if, else, then, while, do, end, input, print.

Целочисленные литералы

Примеры: 0, 42, 1337.

Программа

Program ⩴
    | BlockStatement

Инструкции

BlockStatement ⩴
    | { Statement }
Statement ⩴
    | AssignmentStatement
    | IfStatement
    | WhileStatement
AssignmentStatement ⩴
    | Identifier AssignmentOperator Expression
AssignmentOperator ⩴
    | "="
IfStatement ⩴
    | "if" Expression "then" BlockStatement [ "else" BlockStatement ] "end"
WhileStatement ⩴
    | "while" Expression "do" BlockStatement "end"

Выражения

Expression ⩴
    | Identifier
    | Literal
    | ParenthesizedExpression
    | UnaryExpression
    | BinaryExpression
Literal ⩴
    | NilLiteral
    | BooleanLiteral
    | IntegerLiteral
NilLiteral ⩴
    | "nil"
BooleanLiteral ⩴
    | "false"
    | "true"
ParenthesizedExpression ⩴
    | "(" Expression ")"
UnaryExpression ⩴
    | UnaryOperator Expression
UnaryOperator  ⩴
    | "-"
BinaryExpression ⩴
    | Expression BinaryOperator Expression
BinaryOperator ⩴
    | "+" | "-" | "*" | "//"
    | "==" | "~="
    | "<" | "<=" | ">" | ">="

Приоритет операций

  1. ==, ~= (не равно), <, <=, >, >=.

  2. +, -.

  3. *, // (целочисленное деление).

Ввод-вывод

Добавим возможности ввода-вывода в данный язык следующим расширением:

Expression ⩴
    | …
    | InputExpression
Statement ⩴
    | …
    | PrintStatement
InputExpression ⩴
    | "input" "(" ")"
PrintStatement ⩴
    | "print" "(" Expression ")"

Семантика

Предполагается, что семантика этого языка очевидна, поэтому достаточно прокомментировать некоторые тонкости.

Значения

Как можно заметить по синтаксису, все значения относятся к одному из следующих типов:

  • Nilnil.

  • Boolean — либо true, либо false.

  • Integer — целое число.

Размер целочисленного типа не специфицируется, но должен быть достаточным, чтобы выполнять вычисления в интервале [-230; 230 - 1].

Выражения

Результат вычисления бинарных выражений с операторами <, <=, >, >=, +, -, *, // определен только в случае, когда оба операнда являются значениями типа Integer, причем целочисленное деление на ноль не определено. В противном случае интерпретатор языка сообщает об ошибке.

Переменные

Все переменные являются глобальными. По умолчанию значением всех переменных является nil.

Инструкции

Выражения в условном операторе if и цикле while считаются истинными, если результат их вычисления не равен false или nil.

Ввод-вывод

  • Выражение input() считывает очередное целое число со стандартного потока ввода.

  • Инструкция print(x) выводит значение x на стандартный поток вывода вместе с переводом строки.