  Лирическое отступление. Это уже не исследование, это уже доработка до стадии
законченного продукта.

  Цель работы. Исправить основные ошибки в компиляторе и сделать продукт более
пригодным к использованию.

  Задачи.
  (1) Сделать компилятор переносимым под g++. Дело в том, что согласно Стандар-
ту C++ объявление функции вида void f(); или extern void f(); не может предва-
рять определение функции с модификатором static. Функции с модификатором static
должны объявляться как static void f();. Данное требование Стандарта не соблю-
дается компиляторами Microsoft Visual C++ и Borland C++ Builder -- они позволя-
ют не использовать модификатор static для объявления static-функций. Однако,
компилятор g++ это требование соблюдает.
  В данной версии Простого Рефала директива $EXTERN компилируется в объявление
extern-функции, хотя часто предваряет описание локальных функций.
  Решение проблемы. Ввводим в язык директиву $FORWARD, которая предназначена
для объявления локальных функций.

  (2) Исправить ошибку со сложными образцами. В случае образцов вида:

  Test {
    e.Begin (e.Inner) e.End (e.Left 'X' e.Inner) = ;
  }

  $ENTRY Go {
    = <Test ('er') ('super') ('super') ('abba' 'X' 'super')>;
  }

при переборе очередного варианта открытой e-переменной e.Begin состояние разбо-
ра внутри скобок справа (e.Left 'X' e.Inner) не откатывается до изначального --
разбор данного образца терпит неудачу.
  Решение проблемы. Более полно сохранять состояния.

  (3) Улучшить удобство использования: ввести возможность поиска файлов исход-
ного текста по заданному списку каталогов и возможность указывать компилятор
языка C++ в командной строке.

  (4) Добавить стандартные функции для умножения, деления и взятия остатка.


  Результаты.
  (1) Компилятор сделан переносимым: добавлена директива $FORWARD и добавлена
поддержка концов строки вида CrLf (необходимо для компиляции под UNIX исходни-
ков, написанных под Windows).

  (2) Ошибка исправлена.

  (3) Поддержка командной строки теперь имеет такой синтаксис:

  srefc [-c compiler_command_line] {-d directory} [--] file.sref file.cpp ...

  После опции -c следует начало командной строки для запуска компилятора, нап-
ример -c "g++ -I../SRLib -o file.exe". Если опция не указана, сишный компилятор
после конверсии sref -> cpp не запускается. После опции -d указывается путь к
каталогу поиска, например -d C:\SRLib. Если нужно указать несколько каталогов,
указывается несколько опций -d. Опция '--' используется для указания того, фак-
та, что далее следуют только имена файлов.
  В командной строке могут быть указаны как sref-файлы, так и cpp-файлы. Файлы
ищутся сначала в текущем каталоге, затем в каталогах, указанных при помощи
опции -d в порядке их следования в командной строке.
  Изменения затронули и стандартные функции. Стандартные функции Простого Рефа-
ла теперь находятся в файле Library.cpp; для компиляции необходимо в командной
строке указывать библиотеки Library и refalrts, компилятор их автоматически не
подключает.
  Изменилась утилита srmake -- теперь она имеет синтаксис командной строки,
сходный с синтаксисом компилятора:

  srmake [-c compiler_command_line] {-d directory} [--] file.sref | file.cpp

  Отличие здесь в том, что должен быть указан только один юнит.
  Утилита srmake по-прежнему ищет зависимые файлы по комментарию //FROM, причём
не делает различия между sref- и cpp-файлами, т.е. sref-файл может зависить от
cpp-файла, а cpp-файл -- от sref-файла.

  (4) Добавлены функции Mul, Div, Mod, работающие с целыми числами по модулю
2**32, а также функции запроса типа атома:

  // Новые перечисления

  //FROM Library
  $EXTERN TypeNumber, TypeCharacter, TypeFunction, TypeFile;

  //FROM LibraryEx
  $EXTERN TypeBracket;

  //FROM LibraryEx
  <Type t.Term> == s.TermType
  <Type-T /* пусто */> == '*'
  <Type-T e.Expr> == s.FirstTermType e.Expr

  <Trim e.Space-B e.Expr e.Space-E> == e.Expr

  //FROM LibraryEx
  <Compare t.Left t.Right> = '<' | '=' | '>'
  <Compare-T t.Left t.Right> = '<' | '=' | '>' t.Left t.Right

  Функция Type принимает на входе терм и возвращает одно из перечислений, начи-
нающихся на Type***, функция Type-T возвращает тип первого терма выражения на
входе, а также само выражение. В случае пустого аргумента возвращает '*'.
  Функция Trim удаляет символы пробела и табуляции из начала и конца выражения.
  Сравнение функциями Compare и Compare-T осуществляется в следующем порядке:
  () > Number > Character > Function > File
  При этом содержимое скобок сравнивается в лексиконографическом порядке; цифры
сравниваются естественным образом по их арифметическому значению; символы по их
ascii-кодам, функции и файлы в порядке, определённом реализацией. В данной реа-
лизации функции сначала сортируются по имени (т.к. имя функций хранится в самих
функциях), затем по указателю на функцию (вообще, это непереносимая в C++ опе-
рация), файлы сортируются как указатели FILE* (тоже операция не переносима).