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

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

Рассмотрим синтаксис абстрактного императивного языка, 
где в ка\-чест\-ве комментариев (строки, начинающиеся с ''//'') даны пояснения смысла соответствующих конструкций.
 
\begin{alltt}
e.ASAIL      ::= /*empty*/ | t.Func e.ASAIL
t.Func       ::= (FUNC t.QualifName (e.param) 
                  (e.param) e.body)
\textit{// Определение  функции, где t.QualifName - имя функции, 
// e.param, соответственно, входные и выходные параметры, 
// e.body - тело функции.}
t.QualifName ::= (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.QualifName) 
             | (TVAR t.QualifName) | (VVAR t.QualifName) 
             | (EVAR t.QualifName) | (SVAR t.QualifName)
t.var-int    ::=   (STATIC (s.numb) ) | (VAR t.QualifName) 
             | (TVAR t.QualifName) | (VVAR t.QualifName) 
             | (EVAR t.QualifName) | (SVAR t.QualifName)
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 | t.obj
             | RETURN 
\textit{// Оператор успешного выхода из функции.}
             | FATAL 
\textit{// Оператор аварии, вырабатывающий исключение 
// вида Unexpected fail.}
             | RETFAIL
\textit{// Оператор неуспешного выхода из функции (fail).}
t.call       ::= (CALL t.QualifName (e.args) (e.args))
\textit{// Вызов функции, где t.QualifName - имя функции, 
// e.args, соответственно, входные и выходные фактические
// параметры, передаваемые по значению. }
e.args       :: = /*empty*/ | t.arg e.args
t.arg        ::= t.var | (e.expr-ref) | (e.expr-int)
t.tailcall   ::= (TAILCALL t.QualifName (e.args) (e.args))
\textit{// "Хвостовой" вызов функции, 
// где t.QualifName - имя функции, 
// 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-ref1 (e.expr-ref2) (e.pos)) 
\textit{// Проверка равенства подвыражений 
// выражений e.expr-ref1 и e.expr-ref2,  
// e.pos - начальная позиции сравниваемых подвыражений.  } 
             |(TERM-EQ e.expr-ref1 (e.expr-ref2)(e.pos))  
\textit{// Проверка равенства выражения e.expr-ref1 значению 
//терма, занимающего позицию e.pos в выражении e.expr-ref2. }  
             |(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.}
             |(CHECK-ITER e.expr-ref)
\textit{// Проверка успешности очередного шага итеративного отщепления. }                
             |(INFIX s.op-bool e.args-log)
             |(INFIX s.op-eq e.args-int)
e.args-log   ::= /*empty*/ | (e.expr-log) 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.cont-lab)(e.break-lab)(e.cond)(e.step)e.body) 
\textit{// Цикл  FOR, где e.cont-lab - empty или метка цикла 
// (для оператора CONTINUE), e.break-lab - empty или метка
// для оператора BREAK, e.cond - условие выполнения цикла, 
// e.step  - оператор итерации, e.body - тело цикла.}
e.cont-lab      ::= t.label | /*empty*/
e.break-lab  ::= t.label | /*empty*/
t.label      ::= t.QualifName 
e.step       ::= (INC-ITER e.expr-ref) | (DEC-ITER e.expr-ref) 
\textit{// Шаг цикла FOR - инкремент/декремент итератора 
// переменной e.expr-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.QualifName | (STATIC t.QualifName)
e.const-expr ::= e.comp-expr | e.const-subexpr
e.comp-expr  ::= [empty] | t.const-term e.const-expr
\textit{// Термы, входящие в e.compound-expr, соединяются операцией 
//конкатенации.}
t.const-term ::= s.symbol | (PAREN e.const-expr)
             | (REF t.QualifName)
             | (STATIC t.QualifName)
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.QualifName)
\textit{// Объявление константного объекта.}
t.decl-obj   ::= (DECL-OBJ s.linkage s.tag t.QualifName)
\textit{// Объявление произвольных объектов, s.tag - тип объекта.}
s.tag        ::= "Box" | "Vector" | "Channel" | "String"
t.obj        ::= (OBJ s.linkage s.tag t.name)
\textit{// Конструктор произвольного объекта.}
t.blok-label ::= (LABEL (e.maybe-empty) e.body)
\textit{// Блок, где e.body - тело блока, 
// e.maybe-empty - метка или empty.}
t.decl-func  ::= (DECL-FUNC  t.QualifName)
\textit{// Объявление функции с именем t.QualifName.}
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}
