Главная arrow Программирование С++ arrow Вычисление выражения

Вычисление выражения

Порождающие правила в интерпретаторе Mini С++ реализованы с помощью функций, имена которых начинаются со строки eval_exp, и функции atom(). Для того чтобы лучше понять, как анализатор вычисляет выражения, обработаем следующее выражение (предположим, что переменная prog указывает на начало этого выражения):
10 - 3 * 2.
Когда функция evai_exp () (точка входа в анализатор) вызывается, она получает первую лексему. Если эта лексема нулевой длины или пустая (null), генерируется исключение, указывающее на отсутствие выражения. Но в данном случае лексема содержит число 10. Следовательно, она не пустая, и вызывается функция evai_expO(), которая ищет операцию присваивания. Поскольку такой операции нет, вызывается функция evai_expio, вызывающая в свою очередь функцию eval_exp2 (). Далее eval_exp2 () вызывает функцию eval_exp3 (), а та — функцию eval_exp4 (). Функция eval_exp4 ()
обрабатывает унарные + и -, а также префиксные формы инкремента ++ и декремента —. Затем она вызывает функцию evai_exp5(). В этой точке функция evai_exp5() также рекурсивно вызывает функцию evai_expO() (если выражение заключено в круглые скобки) или функцию atom о для получения значения. Поскольку лексема не содержит открывающую круглую скобку, выполняется функция atom о и переменной value присваивается значение 10.
Затем извлекается следующая лексема, и начинаются возвраты из функций вверх по цепочке. Текущая лексема — знак операции - (минус), и возвраты
ИЗ фуНКЦИЙ ПрОДОЛЖаюТСЯ ДО фуНКЦИИ eval_exp2 ().
То, что происходит далее, очень важно. Поскольку лексема содержит -, он сохраняется в переменной ор. После этого анализатор получает следующую лексему — число 3, и снова начинается нисходящий спуск по цепочке функций. Как и раньше, вызывается функция atomo. Значение 3 возвращается в переменной value, и считывается знак операции * (умножение). Далее происходит возврат по цепочке в функцию eval_exp3 (), в которой читается заключительная лексема 2. Здесь выполняется первая арифметическая операция — умножение: 2*3. Результат передается в функцию evai_exp2 () и выполняется вычитание. Результат этой операции равен 4. Хотя на первый взгляд описанный процесс может показаться сложным, самостоятельный разбор еще нескольких примеров поможет лучше понять принцип действия анализатора.
Теперь подробнее рассмотрим функцию atomo. Она находит значение целочисленной константы или переменной, функции или символьной константы (она также обрабатывает постфиксную форму операций инкремента и декремента). В исходном коде могут быть представлены два вида функций: определенные пользователем и библиотечные. Если обнаружена функция, определенная пользователем, ее код выполняется интерпретатором для того, чтобы получить возвращаемое значение (как на самом деле Mini С++ добивается вызова функции, обсуждается в следующем разделе). Если же обнаружена библиотечная функция, сначала ее адрес ищется функцией intemal_func (), а затем выполняется обращение к ней с помощью интерфейсной функции (interface function) списка.
Как видите, интерпретатор Mini С++ знает лишь несколько библиотечных функций, но вы можете легко добавить другие функции, нужные вам (реальные интерфейсные функции содержатся в отдельном файле, который будет обсуждаться в разд. "Библиотечные функции Mini С++"). Заключительный взгляд на работу анализатора выражений: для того, чтобы правильно анализировать синтаксис языка С++, иногда требуется знать лексему, следующую за текущей. Рассмотрим следующий оператор: alpha = count();
Для того чтобы интерпретатор Mini С++ знал, что count — это функция, а не переменная, он должен прочитать count и следующую лексему. Если следующая лексема — круглая скобка, анализатор опознает count как функцию. Если же обрабатывается следующий оператор:
alpha = count * 10;
то за count следует знак умножения *. Поскольку это не круглая скобка, это означает, что count должна быть переменной. Без дополнительной, следующей лексемы анализатор не может сделать такой вывод. В обоих описанных случаях лексему, следующую за текущей, надо вернуть во входной поток для последующей обработки. Для этого в анализатор выражений включена функция putback (), возвращающая последнюю прочитанную лексему во входной поток.