Р.У. Себеста - Основные копцепции языков программирования (2001) (1160794), страница 34
Текст из файла (страница 34)
Первыми языками, имеющими лаконичное формальное описание, бьши языки А(.ОО(. 60 и А(.ОО(. 68; правда, в обоих с.бчаях описание было сложным лля понимания (отчасти из-за использования новой формы зашюи). В результате языки проиграли с точки зрения степени их восприятия.
С другой стороны. некоторые языки страдают от наличия большого количества диалектов, появивншхся вследствие доступного, но неформального и неточного описания. О.икзй из проблем, возникаюших прн описании языка, является несхожесть людей, лля конгрых это описание предназначено. Большинство новых языков программирования гшательно изучается потенциальными пользователями еше в ходе разработки. Успех з1~ й обратной связи напрямую зависит от ясности описания языка. 1'азраоотчики систем реализации языков программирования. очевидно, должны уметь онрслелязь способ образования выражений. операторов и программных единиц языка.
а тал.ье ожидаемый эффект от их выполнения. Сложность работы, связанной с реализацией я ~гака, также зависит от ясности и точности описания языка. Наконец, пользователи языка лолжны иметь возможность узнать по справочному рукояозсгву, как именно программировать системы программного обеспечения. Учебники и об) чающие курсы дают только обшее представление о языке, но единственным автори1с~ным печатным источником информации о языке обычно является именно справочнос р) коволство.
110 чение языков программирования, полобно изучению естественных языков, может бы сть разделено на исследование синтаксиса и семантики. Синтаксис языка программирования — это форма, а семантика — смысл его выражений, операторов и программных единиц. Например, оператор хЕ языка С имеет следующий синтаксис хЕ (<выражение>1 <опера=ар> 1 го семантика состоит в том. что если текущее значение выражения истинно, то булез выполнен указанный оператор. 11ссмотря на то что лля удобства обсуждения семантика и синтаксис часто разделян1тся. они тесно связаны друг с лругом. В хорошо разработанном языке программирова- Глава 3. Описание синтаксиса н семантики ния семантика непосредственно следует из синтаксиса; т.е. форма оператора может в значительной степени определять его смысл.
Описывать синтаксис намного легче, чем семантику, отчасти из-за существования краткой и общепринятой формы записи, тогда как для описания семантики полобной формы еше не созлано. 3.2. Общая задача описания синтаксиса Как естественные языки (например. английский), так и искусственные (напрнмер, 5ауа) представляют собой совокупности строк, состоящих из символов некоторого алфавита. Строки, состоящие нз символов языка, называются его предложениями (зепгепзез), или утверждениями (магещепгя). Синтаксические правила языка определяют, какие именно строки, состоящие из символов алфавита, существуют в языке. Английский язык, например, обладает большим и сложным набором правил для определения синтаксиса его предложений. По сравнению с ним языки программирования, даже самые объемные и сложные, очень просты с синтаксической точки зрения.
В формальные описания синтаксиса языков программирования лля простоты часто не включаются описания синтаксических единиц самого нижнего уровня. Эти элементарные елиницы называются лексемами (!ехешез). Описание лексем может даваться лексической спецификацией, обособленной от синтаксического описания языка. В число лексем языка программирования входят его идентификаторы, литеральные константы, операторы и специальные слова.
Можно считать, что программа представляет собой строки, состоящие не из символов, а из лексем. Грамматическая лексема (ю)геп) в некотором языке является разновидностью его лексем. Например, идентификатор представляет собой грамматическую лексему, которая может состоять из лексем, или экземпляров, таких как зцаз и соса1. В некоторых случаях грамматическая лексема состоит из одной-единственной возможной лексемы. Например, грамматическая лексема для символа арифметического оператора +, которая может называться оператор сложения, имеет только одну возможную лексему. Рассмотрим следующий пример оператора языка С: 1поех = 2 * соцпс + 17; Лексемы и грамматические лексемы этого оператора следующие: Лексемы 1поех Т~эамматжческже лексемы идентификатор знак равенства целочисленная константа оператор умножения идентификатор оператор сложения целочисленная константа точка с запятой соцпт 17 3.2.
Общая задача описания синтаксиса Приводимые в этой главе описания языков очень просты, и большинство из них содержит описание лексем. 3.2.1. Устройства распознавания языков В общем случае языки могут формально определяться двумя различными способами; путем распознавания (гесозп г(оп) и путем порождения (зепегайоп).
(Следует отметить, что ни один из этих способов не дает определения, улобного для людей, пытающихся нз)чать нли хотя бы использовать язык программирования.) Предположим, что у нас есть язык (.. использующий алфавит символов Е. Для формального определения языка Е посредством метода распознавания нам потребовалось бы созлать механизм К. называемый устройством распознавания и способный читать строки, состоящие из символов алфавита Е. Механизм К следует создать так, чтобы он показывал, приналлежит ли данная введенная строка языку Е. В действительности, механизм К должен был бы либо принимать. либо отклонять заданную строку. Такие устройства подобны фильтрам, отделяющим правильные предложения от неправильных, Если механизм К при введении строки символов алфавита Е принимает ее только в случае ее приналлежности к языку (., то механизм К является описанием языка Ь.
Поскольку самые полезные языки, прелназначенные лля практического испольювания. бесконечны, распознавание может показаться длительным и неэффективным пропессом. Впрочем, устройства распознавания не используются для перечисления всех прелложений языка.
Синтаксический анализатор, являющийся частью компилятора, представляет собой устройство распознавания языка, транслируемого компилятором. В таком качестве устройству распознавания не нужно проверять все возможные строки символов. принадлежащие некоторому множеству, лля того чтобы определить, принадлежит ли каждая из ннх ланному языку. Вместо этого ему всего лишь требуется опрелелить принадлежность ланной программы к языку. По сути, синтаксический анализатор просто определяет, является ли ланная программа синтаксически правильной.
3.2.2. Генераторы языков Генератор языка может использоваться в качестве устройства лля создания предложений языка. Представьте себе кнопку, нажатие которой порождает предложение на данном языке. Поскольку конкретное предложение, возникающее при нажатии кнопки этого устройства, предсказанию не поддается. то генератор кажется мало полезным лля описания языка. Тем не менее, люли предпочитают устройствам распознавания языка некоторые формы генераторов, поскольку их легче читать и понимать.
Часть компилятора, предназначенная лля проверки синтаксиса, наоборот, не так полезна лля программиста в качестве срелства описания языка, поскольку ее можно использовать только методом проб и ошибок. Например, лля опрелеления с помощью компилятора правильного синтаксиса отдельного оператора программист может только предложить компилятору предполагаемый вариант и посмотреть, примет ли его компилятор.
С другой стороны, часто макио опрелелить, верен ли синтаксис отдельного оператора, сравнив его со структурой генератора. Существует тесная связь между формальными устройствами порождения и распознавания одного языка. Открытие этого факта оказалось одним из самых плодотворных в компьютерных науках. Большая часть из того. что нам известно сейчас о формальных языках н теории разработки компиляторов, является следствием этого открытия. В следуюшем разделе мы еше вернемся к взаимосвязи между устройствами порождения и ) стройствами распознавания языков.
126 Глава 3. Описание синтаксиса и семантики 3.3. Формальные методы огтисания синтаксиса В ланном разделе обсуждаются механизмы порожления формазьных языков, широко используемые для описания синтаксиса языков программирования. Эти механизмы часто называются грамматиками. 3.3.1. Форма Бэкуса-Наура и контекстно-свободные грамматики Во второй половине 1950-х годов два человека — Джон Бэкус и Ноам Хамски (Ноаш Словаку) — независимо друг от лруга изобрели одну и ту же форму записи, которая впоследствии стала широко используемым методом формального описания синтаксиса языков программирования. З.З.1.1.