Главная  Терминология Хоора 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 [ 119 ] 120 121 122 123 124 125 126 127 128 129 130 131 132 133

ssym[.] := period; ssym[] :== neq;, ssym[<] := Iss; ssym[>] := gtr; ssym[<,] := leq; ssym[>] := geq; ssym[;] semicolon; pageiputput);

CO :== 0; := 0; ch := ; kk := al; getsym; block (0);

ilsym Ф periodiben error (9); 99: writeln end .

Программа 5.4. Грамматический разбор для ПЛ/0.

которых определен G. Соответственно это определяет, какие процедуры будут вызываться другими процедурами. Диаграмма зависимости для ПЛ/0 показана на рис. 5.5. Циклы на рис. 5.5 обозначают появление рекурсии. По-Ртому важно, чтобы в языке, на котором реализуется транслятор ПЛ/0, была разрешена рекурсия. Кроме того, диаграмма зависимости позволяет сделать выводы об иерархической организации программы грамматического разбора. Например, все процедуры могут содержаться (быть описаны как локальные) в процедуре, которая анализирует конструкцию (программа) (которая поэтому будет главной программой в программе грамматического разбора). Далее, все процедуры, изображенные на диаграмме ниже <блок), могут определяться как локальные в подпрограмме, представляющей цель разбора <блок>. Разумеется, все эти процедуры вызывают сканер getsym, который в свою очередь вызывает getch.

§.9. ВОССТАНОВЛЕНИЕ ПРИ СИНТАКСИЧЕСКИХ ОШИБКАХ

\ До сих пор программа грамматического разбора лишь анавливала, принадлежит ли входная последовательность Символов языку. В качестве побочного результата она также определяла структуру предложения. Но если встречалась неправильная конструкция, задача программы могла считаться Выполненной и она могла закончить работу. Разумеется, на йрактике такая схема неприемлема. Вместо этого транслятор

голжен выдавать соответствующую диагностику об ошибках продолжать процесс грамматического разбора, возможно Находя дальнейшие ошибки. Чтобы продолжать работу, нужно Либо сделать какие-то предположения о том, что на самом



деле имел в виду автор неправильной программы, либо ппо пустить некоторую часть входной последовательности, jjr сделать и то, и другое. Сделать достаточно разумные пред ? положения о действительных намерениях программиста - вольно сложно. До сих пор это не удавалось формализовать поскольку формальный подход к синтаксису и грамматическому разбору не учитывает многие факторы, сильно влияющие на человеческое сознание. Например, распространенной ошибкой является пропуск знаков пунктуации, таких, как точка с запятой (не только в программировании!), но весьма маловероятно, что кто-то пропустит знак + в арифметическом выражении. Для программы грамматического разбора и точка с запятой, и плюс -просто терминальные символы без какого-либо существенного различия; а для человека точка с затгятогг nowH нетшеештачеттия и в конце строки кажется избыточной, тогда как знак арифметической операции, бесспорно, осмыслен*). При разработке подходящей системы восстановления следует принимать во внимание многие подобные соображения, которые связаны с конкретным языком и не могут обобщаться для всех контекстно-свободных языков.

Все же существуют некоторые правила и рекомендации, действующие не только в рамках одного языка, такого, как ПЛ/0. Для них, пожалуй, характерно, что они в равной мере связаны как с исходной концепцией языка, так и с механизмом восстановления в программе грамматического разбора. Прежде всего совершенно ясно, что эффективное восстановление возможно или, во всяком случае, намного облегчается лишь в случае языка с простой структурой. В частности, если при обнаружении ошибки пропускается какая-то часть входной последовательности, то язык обязательно должен содержать служебные слова, неправильное употребление которых крайне маловероятно и которые поэтому могут использоваться для возобновления грамматического разбора. В ПЛ/0 это правило строго соблюдается: каждый оператор начинается с однозначного служебного слова, такого, как begin. If, while; то же относится к описаниям: они начинаются с var, const или procedure. Мы назовем это правилом слуоюеб-ных слов.

Второе правило более непосредственно связано с построением программы грамматического разбора. Для нисходящего

*) Может быть, эти соображения натолкнут читателя на мысль, что в современных языках программирования слишком уж много внимания было уделено формальной синтаксической проблематике. И это на этапе, когда мы ставим задачу общения с машиной на естебтвенном языке. Прим. ред. ..... .......



Иализа характерно, что цели разбиваются на подцели; при joM процедуры вызывают другие процедуры, соответствую-[цие этим подцелям. Второе правило определяет, что если процедура грамматического разбора обнаруживает ошибку, то ода не должна прекращать работу и сообщать о случившемся вызвавшей ее процедуре. Вместо этого она должна самостоятельно продолжать просмотр текста до того места, откуда можно возобновить анализ. Мы назовем это правилом не поднимай панику . Из него следует, что из процедуры грам-Ч|атического разбора не может быть другого выхода, кроме обычного завершения работы.

Правило не поднимай панику можно интерпретировать следующим образом: при появлении неправильной конструкции процедура должна пропустить входной текст, пока не встретится символ, который по правилам может следовать за той конструкцией языка, которую она пыталась обнаружить. Это-означает, что каждой процедуре грамматического разбора в момент текущей ее активации должно быть известно множество внешних символов.

Поэтому на первом этапе уточнения (или дополнения) мы снабдим каждую процедуру грамматического разбора явным параметром fsys, который задает возможные внешние символы. В конце каждой процедуры вставляется явная проверка: действительно ли следующий символ входного текста содержится среди этих внешних символов (если это уже не обусловлено логикой программы)?

Все же с нашей стороны было бы неразумно при всех обстоятельствах пропускать входной текст до следующего появления такого внешнего символа. В конце концов, программист мог по ошибке пропустить всего один символ (например, точку j запятой), а игнорирование текста до следующего внешнего (гамвола может иметь гибельные последствия. Поэтому ко множествам символов, которые прекращают пропуск текста, мы добавим служебные слова, отмечающие начало конструк-щи, которую не следует пропускать. Таким образом, сим-юлы, передаваемые в качестве параметров процедуре грам-1атического разбора, - это . символы возобновления, а не ipocTO внешние символы. Мы можем считать, что множества символов возобновления с самого начала содержат отдельные служебные слова и при проходе иерархии подцелей грам- этического разбора постепенно дополняются внешними символами этих подцелей. Для удобства вводится общая подпрограмма, называемая test, - она выполняет описан-ую выше проверку. Эта процедура (5.17) имеет три пара-Метра:

1. Множество si допустимых следующих символов; если теку-i щий символ к нему не принадлежит, то имеет место ошибка.




1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 [ 119 ] 120 121 122 123 124 125 126 127 128 129 130 131 132 133