В целях отладки мы сочли удобным, чтобы функция execerror
abort (см. справочное руководство по abort(3)), что приведет к распечатке содержимого памяти, которую затем смогут использовать программы adb и sdb. Когда разработка программы полностью завершится, обращение к abort будет заменено на longjmp.В программе hoc2
yyval является объединением, нужно выбрать подходящий элемент перед выходом из yylex. Ниже показаны измененные фрагменты:yylex() /* hoc2 */
{
...
if (с == '.' || isdigit(c)) { /* number */
ungetc(c, stdin);
scanf("%lf", &yylval.val);
return NUMBER;
}
if (islower(c)) {
yylval.index = с - 'a'; /* ASCII only */
return VAR;
}
...
Еще раз отметим, что тип лексемы (т.е. NUMBER
Продемонстрируем новые возможности hoc2
$ hoc2
x = 355
355
y = 113
113
p = x/z
hoc2: division by zero near line 4
x/y
3.1415929
1е30 * 1е30
hoc2: floating point exception near line 5
...
В самом деле, для PDP-11 требуются вполне конкретные меры, чтобы обнаружить переполнение вещественного, но на большинстве других машин hoc2
Обеспечьте возможность запоминания последнего вычисленного значения, чтобы его не приходилось вводить снова для последовательности связанных вычислений. Одним из решений может быть использование какой-либо переменной, например 'p'
Измените программу hoc
';' как разделитель выражений наравне с символом перевода строки.8.3 Этап 3: переменные с произвольными именами; встроенные функции
В версию hoc3
sin cos atan exp log log10 sqrt int abs
Введена также дополнительно операция возведения в степень '^'
Поскольку лексический анализатор должен справляться с встроенными именами длиной более чем в один символ, не так уж много усилий придется приложить, чтобы допустить переменные с именами произвольной длины. Для хранения информации об этих переменных нужна довольно сложная таблица имен, но если мы ее создаем, то можно заранее задать в ней вместе с именами значения некоторых полезных констант:
PI | 3.14159265358979323846 | Число π |
E | 2.71828182845904523536 | Основание натурального логарифма |
GAMMA | 0.57721566490153286060 | Константа Эйлера-Маскерони |
DEG | 57.2957795130823208768 | Отношение градуса к радиану |
PHI | 1.61803398874989484820 | Золотое сечение |
В результате получим полезный калькулятор:
$ hoc3
1.5^2.3
2.5410306
exp(2*3*log(1.5))
2.5410306
sin(PI/2)
1
atan(1)*DEG
45
Несколько улучшилась и работа распознавателя. В hoc2
x = expr не только вызывало присваивание, но и приводило к печати значения, поскольку все выражения печатаются:$ hoc2
x=2*3.14159
6.28318
В программе hoc3
$ hoc3
x=2*3.14159
x
6.28318
Получившаяся в результате всех этих изменений программа настолько велика (около 250 строк текста), что для простоты редактирования и ускорения компиляции лучше разбить ее на отдельные файлы. Итак, теперь мы имеем пять файлов вместо одного: