C++ обладает небольшим, но гибким набором различных видов операторов для контроля потока управления в программе и богатым выбором операций для
управления данными.
То есть программа представляет собой последовательность строк. Каждая строка включает в себя одно
или более выражений, разделенных запятой. Основными элементами выражения служат числа, имена
и операции *, -, +, – (унарный и бинарный) и =. Имена
не всегда описываются до использования.
Применяемый метод синтаксического анализа
обычно именуется рекурсивным спуском; это популярный и простой нисходящий метод. В таком языке, как
C++, в котором вызовы функций вполне дешевы, кроме
того, данный метод эффективен. Для любого правила
вывода грамматики существует функция, вызывающая
другие функции. Терминальные символы (например,
END, NUMBER, + и –) определяются лексическим анализатором get_token(), а нетерминальные символы
определяются функциями синтаксического анализа
expr(), term() и prim().
Программа разбора для обнаружения ввода применяет функцию get_token(). Значение вызова get_token()
определяется в переменной curr_tok; curr_tok принимает одно из значений перечисления token_value.
В любой функции разбора предполагается, что было
обращение к get_token() и в curr_tok располагается очередной символ, подлежащий анализу. Это дает возможность программе разбора заглядывать на один лексический символ вперед и вынуждает функцию разбора читать на одну лексему больше, чем применяется
правилом, для обработки которого она была вызвана. Каждая функция разбора определяет «свое» вы-
ражение и возвращает значение. Функ-ция expr() обрабатывает сложение и вычитание; она включает в себя
простой цикл, который обнаруживает термы для сложения или вычитания.
Сама функция делает мало. В манере, которая типична для функций более высокого уровня в громоздких программах, она вызывает для осуществления работы другие функции.
Обработка ошибок в программах С++ не составляет
большого труда. Функция обработки ошибок просто
определяет ошибки, пишет сообщение об ошибке и возвращает управление обратно: Возвращение производится потому, что ошибки
чаще всего встречаются в середине вычисления выражения, и поэтому следует или полностью прекращать
вычисление, или возвращать значение, которое не должно привести к последующим ошибкам. Для обычного калькулятора больше подходит последнее. Если бы
get_token() обнаруживала номера строк, то error() сообщала бы, где приблизительно обнаружена ошибка. Это
было бы полезно, если бы калькулятор применялся неинтерактивно.
Когда все части программы разделены, необходим
только драйвер для инициализации и того, что связано с запуском. Например:
Принято обычно, что main() возвращает ноль при
обычном завершении программы и не ноль в противном случае, поэтому это прекрасно осуществляет возвращение числа ошибок.