Г. Шилдт - Полный справочник по C++ (1109478), страница 146
Текст из файла (страница 146)
Зги функции позволяют программе перелавать управление из одной функции в другую. слеловательно, с помощью функции 1опзмрО функция яеезщр() может выполнить передачу управления в безопасную точку программы, находящуюся за пределами синтаксического анализатора. Кроме того, в программе синтаксического анализа можно применить механизм обработки исключительных ситуаций, реализуемый' с помощью операторов еку„ севсЬ и еЬтом. Если оставить этот кол без изменения, на экран могут выдаваться многократные сообщения о синтаксических ошибках.
В одних ситуациях это может быть нежелательным, а в других желательным, поскольку так можно выявить сразу несколько ошибок. Однако, как правило, блок синтаксического контроля в коммерческих программах является более изощренным. чотй еча1 ехр5(Ртуре Ьгеви1С) чотй еча1 ехрб(ртуре агеви1с) чо)й агою(ртуре агеви1С)з чотй Пег Со)<еп(), рог)заск[)з чотй веггог(1пс еггог)з РТуре Етой чаг(с)заг *в); 1пс 1вйе11лз(спаг с)з роЬ11сз рагвег () з РТуре еча1 ехр(с)заг *ехр); // Конструктор класса рагвег. Сепр1аге <с1авв РТуре> рагвег<РТуре>з:рагвег() ( 1пг ).; ехр рог = МПЬЬы лог(1=0; 1<БПГЛЯВз 1++) чагв (з ) = [РТуре) Оз // Отгравная точка анализа.
Сезяр1аге <с1авв РТуре> РТуре рагвег<Ртуре>::еча1 акр[с)заг *ехр) ( РТуре гевп1С; ехр рог = ехр; цег Сокеп()з 11((>понед) веггог(2)з // Выражение пусто. гегпгп (РТуре) Оз ) еча1 ехр1(гевп1г)з тг(*говел) веггог(0); // Последняя лексема должна быть // нулевым символом. гегпгп геви1сз ) // Присваивание.
сеюр1асе <с1авв РТуре> чотй рагвег<ртуре>з:еча1 ехр1(ртуре агевп1С) ( тпс в1огз с)заг Спок Гурез с)заг гетр Говел[80)з ).1(сок Суре==ЧАВ1АВЬЕ) // Сохраняем старую лексему. всгсру(севзр сохеп, го)<еп)з ссон суре = со)< сурез // Вычисляем индекс переменной.
в1ос = Сопррег(*гонеп) — 'А'з дег со)геп()з 11(*секес )= '=') ( Часть ((. Приложения на языке С++ рисЬасК(); // Возвращаем текущую лексему. // Восстанавлнваем старую лексему // прмсваивание не выполняется. зггсру(гоКеп, Секр Сокеп); Гок Гуре = СгоК Суре; ) е1зе ( дег синел(); // Извлекаем следующую часть выражения ехр. еча1 ехр2(геви1С); чагз(в1ое) = геви1С; гесигп; еча1 ехр2(гези1с) ) // Складываем нлн вычмтаем два герма.
Сещр1аге <с1азз РТуре> чоЫ рагвег<РТуре>::еча1 ехр2(РТуре агеви1С) ( гедавсег сдаг ор; Ртуре Секр; еча1 ехрЗ(гези1С); мЬ11е([ор = >Сокеп) == 'ь' (( ор == ' †') вес сокеп(): еча1 ехрЗ(гещр); вмтссЬ(ор! ( сазе гези1Г = геви1С вЂ” Сещр; ЬгеаК: сазе '+': геяи1с = гази)г > гетр; ЬгеаК; ) ) ) // Умножение н пеленке двух факторов. Сещр1аее <с1азз РТуре> чей<) рагзег<РТуре>::еча1 ехрЗ(РТуре агеви1С) ( гед1згег айаг ор; РТуре Секр; еча1 ехра(гези1С); мЬ11е((ор = *гокеп) == '*' (( ор == '/' (( ор == 'ч') ( аес сокеп(); еча1 ехр4(секр); змассЬ(ор) ( саве '*': гези1г = гези1с * секр; Ьгеаи; саве '/': геви1с = геви1с / гещр; ЬгеаК; саяе 'Ъ': гези1г = (Зпг) гези1с Ъ (1пс) секр; Глааа 40.
Синтаксический анализ выражений ]отсах; ) ) // Возведение в свепеня. теыр1асе <с1аяв Ртуре> чоЫ ратвет<ртуре>::еча1 ехр4(ртуре йтеви1т) Ртуре титр, ех; тес1втет 1пт еча1 ехр5(теви1С); 1й(*тонеп== ' ') ( сея сохеп(); еча1 ехр4(теыр]; ех = теви1т; тб(петр==0.0) ( теви1т = (РТуре) 1; тетитп; ) Вот(т<(зпт) татар-1; с>О) б-В] теви10 = теви1т * ех; ) // Выполнение унарных операиий я или -.
Сетр1ате <с1аяв РТуре> чоЫ ратвет<РТуре>::еча1 ехр5(РТуре йтеви10) тер1всет с)тат ор) ар=0; 1й((то)< Суре == ВВЫМТТВВ) аа *Сокеп== + )) *Со]<еп == — ) ор = *сохеп; Вес сохеп!); еча1 ехрб(теви1с); 1й(ор==' †') теви1т =. -теви1т; // Вычисляет выражение, содержашеее схоохи. тепр1ате «с1азя Ртуре> чоЫ ратвет<ртуре>::еча1 ехрб!Ртуре йтеви1т) ( 1й( (*тохеп == ' (' ) ) ( дет тохеп(); еча1 ехр2(теяи1т); 1й(*сохеп != ')') ветт от. (1); Вет Сохеп(); ) е1ве атом(теяи10)т ) // Возвращает число или значение переменной. Сетр1ате <с1авв Ртуре> чоЫ ратяет<РТуре>::аоот(ртуре Ьтеви1С) ( ян1сс)т(сох туре) ( саве ч))кх)(ВВВ: теви1С = Й)пс( чат(тохеп]; Часть )/.
Прнясження на языке С++ сеС Сонеп(); гесигпз саве МПМВЕВз геви1с = (Ртуре) асос(секес) дег СоКеп()З геспгпз с)еГап1сз веггог(0)з // Возвращает лексему во входной поток. сещр1асе <с1авв Ртуре> ъоззб рагвег<Ртуре>з:риссаск() ( снег *Сз сокеп; 1ог(з *сз с++) ехр рсг †; ) // Выводит сообщение о синтаксической ошибке. Сещр1аге <с1авя Ртуре> чоЫ рагвег<РТуре>:зяеггог(1пС еггог) ( всасас с)заг *е[)= ( "Синтаксическая ошибка", "НарУшен баланс скобок', "Выражение пусто" ): сопя « е[еггог) « епз)1; // извлекает следующую лексему. Сешр1аге <с1аяв РТуре> ноЫ рагвег<РХуре>:здег СоКеп() гед1вгег сваг "Сещр; соК суре = Оз Сещр = СоКепз "сещр = ' 10 '; 11(!*ехр ргг) геглппз // В конце выражения.
нК11е(1вврасе(*ехр рсг)) ++ехр рсгз // пропуск разделителя. 1й (вггс)зг ( "з--*/(("= () ", *ехр рсг) ) ( СоК Суре = ОБ1.1М1ТЕНз // Переход к следующему символу. *сещр>+ =- "ехр рсг++з ) е1ве 11(1за1рЬа(*ехр ргг) ) нЬ11е((1я()е11щ(*ехр ргг)) *Сещр++ = *ехр рег++; Сон Суре = ЧАР1АВ(Ез ) е1ве 11(1вд1р(с(*ехр рсг)) ( нЬ11е((1вде11щ(*ехр ргг)) *Сещрз-з- = *ехр рег+тз Сон Суре = МПМВЕРз Глава 40. Синтаксический анализ выражений *секр = 10 ) // Если параметр с является разделителем, // возвращает значение стие.
хеыр1асе <с1аяв Ртуре> Тпх рахяет<ттуре>ззая((е1зхз(снах с) ( 18[яххспт[* +-/*Ъ =() ", с) 1 ) с==9 [ ( с.=='1т' [ [ с==0) техитп 1/ гехитп 0; ) // Возвраыает значение переменной. Геазр1аее <с1аяя РТуре> РТуре ратяет<Р>туре>ззбтпб чах(спат *в) ( Н ( [ з.ва1риа (*я) ) [ ветгог(1)з зетигп (РТуре) Оз гетигп чахя[тоиррет[*тонеп) †'А')з Тнзз данных, с которыми работает синтаксический анализатор, задается классом Ртуре. Применение обобшенного анализатора иллюстрируется следуюшей программой. зпх мази() ( снах ехряет[80) // Демонстрация анализатора выражений типа х1оат.
ратяет<((оиЬ1е> оЬз соих « "Анализатор выражений типа х1оас. соис « "Для окончания работы введите точку 1п"з Тох(зз) ( сова « "Введите выражение: сзп.пее11пе[ехряхх, 79)з 1Х("ехряхх=='.') Ьтеакз спит « "Ответ: " « оЬ.еча1 ехр(ехряхт) « "1п1п"з соне « епб1з // Демонстрация анализатора целочисленных выражений. рахяет<1пе> тоЬ; соит « "Анализатор целочисленных выражений. соит « "Для окончания работы введите точкутгз хох(зз) ( спит « "Введите выражение: с1п.пех1зпе(ехряст, 79); 1й(*ехряет=='.') Ьхеайз соих « "Ответ: " « тоЬ.еча1 ехр(ехрзхт) « "1п1п"з техихп 0) ) Часть )(.
Приложения на ж)ыке С++ рассмотрим несколько примеров. Анализатор выражений типа г1оае. Для окончания работы введите точку. Введите выражение: а.=10.1 Ответ: 10.1 Введите выражение: Ь=3.2 Ответ: 3.2 Введите выражение: а!Ь Ответ: 3.15625 Введите выражение: Анализатор целочисленных выражений. Для окончания работы введите точку. Введите выражение: а=10 Ответ: 10 Введите выражение: Ь=З Ответ: 3 Введите выражение: а)Ь Отве~: 3 Введите выражение: Как видим, анализатор выражений типа в1оас использует действительные значения, а анализатор целочисленных выражений — целые. Некоторые задачи Мы уже отмечали, что па~в синтаксический анализатор распознает ли~ль небольшое количество ошибок. Читатели могут сами усовершенствовать блок синтаксического контроля. Например, можно выделять ошибочный элемент выражения другим цветом. Это позволило бы пользователю легко обнаруживать и исправлять ошибки.
Кроме того, в нынешнем виде наш калькулятор может вычислять лишь числовые значения. Однако его можно модифицировать так, чтобы он вычислял выражения, содержащие строки, пространственные координаты или комплексные числа. Например, для вычисления строковых объектов в анализатор необходимо внести следующие изменения. 1.
Определить новый тип лексемы под названием втихата. 2, усовершенствовать функцию нее конев(1 так, чтобы она распознавала строки. 3. Предусмотреть вариант, в котором функция аеежа(1 обрабатывала бы строковые лексемы. После выполнения этих действий анализатор сможет вычислять строковые выражения, например: | а = "один" Ь = "два" с= а+В Глава 40. Синтаксический анализ выражений Результат„записанный в переменной е, должен представлять собой конкатенацию строк а и зз, т.е.
быть строкой "одинлва"'. Вспомним об еще одном полезном применении синтаксического анализатора: создании простого всплывающего калькулятора, вычисляющего выражения, введенные пользователем, и выводящего результат на экран. Этот калькулятор может украсить любое коммерческое приложение. Если вы программируете в среде Ъ1поозтз, это будет особенно просто.