\subsection {Абстрактный синтаксис императивного языка}

Набор конструкций абстрактного императивного языка
(ASIL) включает элементы императивных языков 
(цикл, условный оператор, операторы пе\-ре\-хо\-да и др.), 
а также набор базовых функций run-time--библио\-те\-ки, 
ориен\-ти\-ро\-ван\-ных на работу с Рефал-выражениями.

Рассмотрим синтаксис абстрактного императивного языка, 
где в ка\-чест\-ве комментариев (строки, начинающиеся с ''//'') даны пояснения смысла соответствующих конструкций.
 
\begin{alltt}
e.ASAIL         ::= /*empty*/ | t.Func e.ASAIL
t.Func          ::= (FUNC t.QualifiedName (e.param) 
                  (e.param) e.body)
\textit{// Определение  функции, где t.QualifiedName - имя функции, 
// e.param, соответственно, входные и выходные параметры, 
// e.body - тело функции.}
t.QualifiedName ::= (e.name)
e.name          ::= /*empty*/ | s.numb e.name | s.word e.name
e.param         ::= /*empty*/ | t.var-ref e.param
t.var           ::=  t.var-ref | t.var-int  
t.var-ref       ::=   (STATIC (s.numb) ) | (VAR t.QualifiedName) 
                | (TVAR t.QualifiedName) | (VVAR t.QualifiedName) 
                | (EVAR t.QualifiedName) | (SVAR t.QualifiedName)
t.var-int       ::=   (STATIC (s.numb) ) | (VAR t.QualifiedName) 
                | (TVAR t.QualifiedName) | (VVAR t.QualifiedName) 
                | (EVAR t.QualifiedName) | (SVAR t.QualifiedName)
e.body          ::= /*empty*/ | t.statement e.body
t.statement     ::= t.call | t.tailcall | t.assign | t.decl   
                |t.decl-int | t.if | t.for | t.continue | t.break 
                |t.lsplit | t.rsplit | t.catch | t.try 
                |t.drop | t.expr-obj | t.deref | t.subexpr 
                |t.constexpr | t.blok-label | t.decl-func 
                |t.error | t.decl-const | t.decl-obj
                | RETURN 
\textit{// Оператор успешного выхода из функции.}
                | FATAL 
\textit{// Оператор аварии, вырабатывающий исключение 
// вида Unexpected fail.}
                | RETFAIL
\textit{// Оператор неуспешного выхода из функции (fail).}
t.call          ::= (CALL t.QualifiedName (e.args) (e.args))
\textit{// Вызов функции, где t.QualifiedName - имя функции, 
// e.args, соответственно, входные и выходные фактические
// параметры, передаваемые по значению. }
e.args          :: = /*empty*/ | t.arg e.args
t.arg           ::= t.var | (e.expr-ref) | (e.expr-int)
t.tailcall      ::= (TAILCALL t.QualifiedName (e.args) (e.args))
\textit{// "Хвостовой" вызов функции, 
// где t.QualifiedName - имя функции, 
// e.args, соответственно, входные и выходные 
// фактические параметры, передаваемые по значению.}
t.assign        ::= (ASSIGN t.var e.expr)
\textit{// Оператор присваивания, где t.var - имя переменной, 
// e.expr - присваиваемое значение.}
e.expr          ::=  e.expr-ref | e.expr-int
t.decl          ::= (DECL s.type t.var)
\textit{// Объявление переменной t.var типа s.type.
// Предполагается поддержка двух базовых типов: 
// int (целые числа) и Expr (Рефал-выражения).}
s.type          ::= "Expr" | "int" 
t.decl-int      ::= (INT t.var e.expr-int)
\textit{// Объявление переменной t.var типа int
// и инициализация ее значением e.expr-int.}
t.if            ::= (IF (e.cond) e.body)
\textit{// Условный оператор, где e.cond - условие, 
// e.body - последовательность действий, выполняемых 
// в случае его истинности. }
e.cond          ::= /*empty*/ | t.cond-term e.cond   
\textit{// Операнды t.cond-term, входящие в условие e.cond, 
// соединяются "И" (AND).}
t.cond-term     ::= t.call 
                |(SYMBOL? e.expr-ref (e.pos))  
\textit{// Проверка структуры элемента, занимающего в 
// выражении e.expr-ref позицию e.pos; 
// условие истинно, если этот элемент - символ.}
                |(EQ (e.expr-ref) (e.pos) (e.len) 
                  (e.expr-ref) (e.pos) (e.len)) 
\textit{// Проверка равенства подвыражений 
// выражений e.expr-ref1 и e.expr-ref2; 
// e.pos1 и e.pos2 - начальные позиции сравниваемых 
// подвыражений; e.len1 и e.len2, соответственно, их длины.  } 
                |(FLAT-EQ (e.expr-ref) (e.pos) (e.expr-ref)
                  (e.pos) (e.len) )  
\textit{// "Быстрая" проверка равенства подвыражений выражений 
// e.expr-ref1 и e.expr-ref2; 
// e.pos1 и e.pos2 - начальные позиции сравниваемых 
// подвыражений; e.len - их длина; 
// известно, что подвыражения не содержат скобочных термов. }  
                |(FLAT-SUBEXPR? e.expr-ref (e.pos) (e.len)) 
\textit{// Проверка структуры выражения e.expr-ref;
// условие истинно, если в  выражении e.expr-ref   
// подвыражение, начинающееся в e.pos и имеющее длину e.len,   
// не содержит скобочных термов. }
                |(NOT e.cond) 
\textit{// Логическое отрицание условия e.cond.}
                |(INFIX s.op-bool e.args-log)
                |(INFIX s.op-eq e.args-int)
e.args-log      ::= /*empty*/ | (e.cond) e.args-log
e.pos           ::=e.expr-int
e.len           ::= e.expr-int
e.expr-log      ::= /*empty*/ 
                |t.cond-term e.expr-log 
                |t.int-term e.expr-log
s.op-bool       ::= "&&" | "||"   
s.op-eq         ::= "<" | ">" | "<=" | ">=" | "==" | "!="
t.for           ::= (FOR (e.maybe-empty)(e.cond)(e.step)e.body) 
\textit{// Цикл  FOR, где e.maybe-empty - empty или метка цикла 
// (для цикла с оператором CONTINUE), 
// e.cond - условие выполнения цикла, 
// e.step  - оператор итерации, 
// e.body - тело цикла.}
e.maybe-empty   ::= t.label | /*empty*/
t.label         ::= t.QualifiedName 
e.step          ::= (INC-ITER t.var-ref)
\textit{// Шаг цикла FOR - инкремент итератора 
// переменной t.var-ref, созданного ранее
// соответствующей функцией lsplit() или rsplit().}
t.continue      ::= (CONTINUE t.label)
\textit{// Оператор перехода к следующей итерации цикла FOR, 
// t.label - метка цикла.}
t.break         ::= (BREAK t.label)
\textit{// Оператор выхода из цикла FOR,  
// t.label - метка блока, содержащего цикл.}
t.lsplit        ::= (LSPLIT e.expr-ref (e.min) t.left t.right)
t.rsplit        ::= (RSPLIT e.expr-ref (e.min) t.left t.right)
\textit{// Функции отщепления фрагментов Рефал-выражения
// (соответственно, слева и справа);
// e.expr-ref - исходное выражение; 
// e.min - минимальная длина отщепляемого участка; 
// t.left и t.right, соответственно, левая и правая части, 
// на которые разделяется выражение. }
t.left          ::= t.var-ref
t.right         ::= t.var-ref
e.min           ::= e.expr-int
t.try           ::= (TRY e.body)
\textit{// try-блок, где e.body - тело блока. Исключения из него 
// перехватываются в соответствующем catch-блоке.}
t.error         ::= (ERROR e.expr-ref)
\textit{// Оператор генерации исключения, где e.expr-ref - исключение.}
t.catch         ::= (CATCH-ERROR e.body)
\textit{// Блок перехвата исключений, вырабатываемых соответствующим 
// try-блоком. Для любого try-блока существует только один 
// catch-блок, условие входа в который всегда  истинно 
// (вида Expr const& err), анализ  и обработка исключения 
// проводится в теле блока e.body.}
t.drop          ::= (DROP t.var-ref)
\textit{// Блок, сигнализирующий о возможности освобождения 
// памяти, занимаемой объектом  t.var-ref, 
// т.к. она далее не используется.}
t.expr-obj      ::= (EXPR t.var-ref e.expr-ref)
\textit{// Конструктор объекта t.var-ref класса Expr 
// со значением e.expr-ref.}
t.deref         ::= (DEREF t.var-expr e.expr-ref (e.pos))
\textit{// Конструктор объекта t.var-ref класса Expr, 
// значение которого - содержимое скобочного терма, 
// занимающего в выражении e.expr-ref позицию e.pos.}
t.subexpr       ::= (SUBEXPR t.var-ref e.expr-ref (e.pos)(e.len))
\textit{// Конструктор объекта t.var-ref класса Expr, 
// который выделяет в выражении e.expr-ref, 
// начиная с элемента e.pos, подвыражение длиной e.len.}
e.pos           ::= e.expr-int
e.len           ::= e.expr-int
t.constexpr     ::= (CONSTEXPR s.linkage t.const-name (e.comment) 
                     e.const-expr)
\textit{// Конструктор константного объекта класса Expr.}
s.linkage       ::= EXPORT | LOCAL
e.comment       ::= \emph{выражение (в смысле Рефал Плюс)}
\textit{// e.comment - выражение в том виде, в котором оно
// встретилось в Рефал-программе.}
t.const-name    ::= t.QualifiedName | (STATIC t.QualifiedName)
e.const-expr    ::= e.compound-expr | e.const-subexpr
e.compound-expr ::= [empty] | t.const-term e.const-expr
\textit{// Термы, входящие в e.compound-expr, соединяются операцией 
//конкатенации.}
t.const-term    ::= s.symbol | (PAREN e.const-expr)
                | (REF t.QualifiedName)
                | (STATIC t.QualifiedName)
e.const-subexpr ::=(SUBEXPR t.const-name s.const-pos s.const-len)
s.const-pos     ::= s.numb
s.const-len     ::= s.numb
t.decl-const    ::= (DECL-CONST t.QualifiedName)
\textit{// Объявление константного объекта.}
t.decl-obj      ::= (DECL-OBJ s.linkage s.tag t.QualifiedName)
\textit{// Объявление произвольных объектов, s.tag - тип объекта.}
s.tag           ::= "Box" | "Vector" | ...
t.blok-label    ::= (LABEL (e.maybe-empty) e.body)
\textit{// Блок, где e.body - тело блока, 
// e.maybe-empty - метка или empty.}
t.decl-func     ::= (DECL-FUNC  t.QualiiedName)
\textit{// Объявление функции с именем t.QualifiedName.}
e.expr-ref      ::= /*empty*/ | t.term-ref e.expr-ref
\textit{// Термы в Рефал-выражении объединяются конкатенацией.}
t.term-ref      :: = s.symbol | t.var-ref  
                |(PAREN e.expr-ref) 
\textit{// Оператор ''навешивания скобок'' для выражения e.expr-ref;
// результат типа Expr.}
                |(DEREF e.expr-ref (e.pos))  
\textit{// Извлечение содержимого скобочного терма, 
// находящегося в e.expr-ref в позиции e.pos, 
// результат типа Expr. }
                |(SUBEXPR e.expr-ref (e.pos)(e.len))  
\textit{// Выделение в выражении e.expr-ref подвыражения, 
// начинающегося в e.pos и имеющего длину e.len; 
// результат типа Expr.}
              	|(EXPR e.expr-value)  
\textit{// Формирование выражения (e.expr-ref);
// результат типа Expr. }
e.expr-value    ::= /*empty*/ | s.symbol e.expr-value
e.expr-int      ::= /* empty */ | t.int-term e.expr-int
\textit{// Термы в целочисленном выражении e.expr-int 
// соединяются "+" (операция сложения); результат типа int.}
t.int-term      ::= s.numb | t.var-int    
                |(LENGTH e.expr-ref) 
\textit{// Вычисление длины выражения e.expr-ref;
// результат типа int.  }
                |(MIN e.args-int) | (MAX e.args-int) 
\textit{// Вычисление минимума (максимума) среди аргументов типа int; 
// результат типа int.}
                |(INFIX s.op-int e.args-int) 
\textit{// Арифметические операции (левоассоциативные) для 
// аргументов типа int.}
e.args-int      ::= /*empty*/ | (e.expr-int) e.args-int
s.op-int        ::= "+" | "-" | "*" | "/" | "%" 
s.numb          ::= \emph{символ-число (в смысле Рефал Плюс)}
s.word          ::= \emph{символ-слово (в смысле Рефал Плюс)}
\end{alltt}
