$ сс y.tab.c -о hoc1
$ hoc1
2/3
0.66666667
-3-4
hoc1: syntax error near line 1
$
Исследуйте структуру файла y.tab.c
hoc1 это составляет около 300 строк текста).Ранее мы утверждали, что, работая с yacc
hoc1 унарный минус, чтобы выражения типа-3-4
вычислялись, а не отвергались как синтаксические ошибки. Всего две строки нужно дополнительно включить в hoc.y
UNARYMINUS в ту часть грамматики, где задаются приоритеты, чтобы унарный минус имел наивысший приоритет:%left '+' '-'
%left '*' '/'
%left UNARYMINUS /* новая лексема */
Грамматика увеличивается на одно правило для expr
expr: NUMBER ($$= $1;}
| '-' expr %prec UNARYMINUS {$$=- $2} /* новое */
Определение %prec
"-" перед выражением) имеет тот же приоритет, что и UNARYMINUS (наивысший); действие заключается в изменении знака. Приоритет минуса между двумя выражениями устанавливается по умолчанию.Добавьте операции %
hoc1. Рекомендация: обратитесь к справочному руководству по frexp(3).makeОбидно, что приходится вводить две команды для компиляции hoc1
make читает описания взаимозависимости компонентов программы и позволяет создать ее действующую версию. Она проверяет время последней модификации каждого компонента, выясняет минимальный объем перекомпиляции, которую необходимо выполнить для получения новой действующей версии, и затем запускает процесс. Программа make разбирается в запутанных многошаговых процессах, в частности в yacc, поэтому ей можно давать задания, не уточняя отдельные шаги.Особенно полезно обращаться к make
hoc1. Ниже приведены описания команд для make, рассчитанные на hoc1, которые make предполагает найти в файле с именем makefile.$ cat makefile
hoc1: hoc.o
cc hoc.o -o hoc1
$
Здесь сообщается, что hoc1
hoc.o и что hoc1 создается из hoc.o с помощью команды сс, которая запускает компилятор Си, помещая выходной поток в файл hoc1. Программа make уже "знает", как преобразовать входной файл для yacc hoc.y в выходной файл hoc.o:$ make
yacc hoc.y
сс -с y.tab.c
rm y.tab.c
mv y.tab.o hoc.о
сс hoc.о -о hoc1
$ make
'hoc1' is up to date make понимает, что это не нужно
$
8.2 Этап 2: переменные и восстановление после ошибки
Следующий шаг переход от hoc1
hoc2, который сводится к расширению памяти (в памяти хранится 26 переменных с именами от а до z). Это довольно несложный и весьма полезный промежуточный этап. Мы также введем здесь процесс обработки ошибок. Если вы проверите hoc1, то убедитесь, что реакцией на синтаксические ошибки являются вывод сообщения и прекращение работы. Поведение же hoc1 в случае арифметических ошибок типа деления на нуль достойно всяческого порицания:$ hoc1
1/0
Floating exception - core dump
$
Для реализации новых возможностей требуются лишь небольшие изменения: приблизительно 35 строк текста. Лексический анализатор yylex
expr: VAR
| VAR '=' expr
Выражение может содержать операцию присваивания; разрешены также многократные присваивания типа
x = y = z = 0