Чтение лексем
Доставанием из исходного текста уже неделимых далее кусочков («атомов»-лексем), которые являются элементарными понятиями языка, занимается отдельная процедура транслятора с гордым названием лексический анализатор. Казалось бы, эта подпрограмма должна быть очень маленькой и простой. В действительности это довольно громоздкая часть транслятора, которая реализует некоторые свойства языка, например, свободный формат.
В данном трансляторе есть аж целых семь уровней чтения исходного текста. Давайте потратим немного времени и рассмотрим их, потому что это позволяет лучше понять правила записи в языке.
Самый нижний, первый уровень собственно и читает символы (байты) или из файла с программой или из файлов, указанных в директиве %INCLUDE. Никаких тонкостей здесь нет, именно этот уровень обнаруживает конец текста и выдает в этом случае специальный код 1A.
Следующий второй уровень, используя результат предыдущего, ищет в тексте строчные константы в кавычках, комментарии и, самое главное, директивы транслятору, начинающиеся с символа «%». На этом уровне просто выбрасываются однострочные комментарии, начинающиеся с «//». Однако ничего с обычными комментариями и строками этот уровень не делает. Его задача определить, что %INCLUDE и другие директивы транслятору стоят не внутри комментария и не внутри строки. Тогда этот уровень обрабатывает их.
Следующий третий уровень просто запоминает символы, если их приходится «подсматривать» для разбора присваивания и метки. Когда в обыкновенном разборе дойдет дело до уже «подсмотренных» символов, они берутся из «буфера» этого уровня, а не из файла. В других языках такого уровня может и не быть.
Следующий четвертый уровень обеспечивает разбивку исходного текста на строки. Если бы не требовалось выводить распечатку исходного текста или строку программы при обнаружении ошибки, то и этого уровня не потребовалось бы. Здесь подсчитывается номер строки, табуляция переводится в пробелы и происходит печать строки, если это нужно. По сути это уровень реализации свободного формата: исходные строки сохраняются и печатаются, но далее в самом языке они уже никак не используются.
Следующий пятый уровень тесно связан с предыдущим. Он заставляет сразу прочитать всю строку в свой «буфер», хотя вышестоящим уровням передает символы по одной штуке. Это как раз то место, где исходные строки исчезают, и остается только одна длинная цепочка байт.
Следующий шестой уровень и надо было бы назвать настоящим лексическим анализатором. Получая отдельные байты от пятого уровня, он составляет из них лексемы: числа, имена, строки, скобки и т.п. Именно этот уровень сообщает о неожиданном конце программы, если получает символ 1A посреди разбора лексемы. Здесь выполняются всякие перекодировки и коэффициенты повторения, а также выясняется, входит ли точка в состав числа или это отдельный символ-разделитель. Заодно все лексемы-имена проверяются в таблицах оператора %REPLACE.
Полный лексический анализатор реализован на последнем, седьмом уровне. Здесь определяются ключевые слова языка и составные действия типа «>=». Этот уровень интересен тем, что он разный для первой и второй частей транслятора (поиск описаний и собственно трансляция), потому что на этих этапах ищутся разные конструкции языка. Например, указанный оператор «>=» определяется как раз только на втором «проходе» транслятора, а при разборе описаний эти две отдельные лексемы просто пропускаются. Кстати, комментарии /* */ пропускаются только на этом последнем этапе.
Сложная семиуровневая структура позволяет производить на каждом уровне довольно простые и понятные действия. Обращаясь к лексическому анализатору транслятор каждый раз получает удобную готовую лексему, а если это имя — заодно и информацию не ключевое ли это слово языка. Как уже было рассказано выше, транслятор обращает внимание на эту дополнительную информацию при разборе начала каждого оператора языка и в нескольких других случаях. Последняя фраза определяет реализацию незарезервированных ключевых слов в ПЛ/1.
Автор: Д.Ю.Караваев.
Опубликовано: 2018.08.26, последняя правка: 2018.10.29 15:51
Отзывы
✅ 2018/10/30 18:13, Александр Коновалов aka Маздайщик #0
Если комментарии /* … */ удаляются на последнем проходе, то предыдущие проходы подставляют %REPLACE’ы детектируют метки/присваивания и т.д. ещё и внутри комментариев?✅ 2018/10/31 06:01, kt #1
Нет, конечно. Может быть невнятно фраза составлена. Комментарии приходится "тянуть" до 4 уровня, т.е. до возможной печати строки. Поскольку однострочный комментарий был добавлен после, он тоже запоминается, но в отдельном внутреннем буфере, а "родной" многострочный — в "родном" же буфере исходной строки. После возможной печати на 4 уровне и однострочный и многострочный просто выбрасываются. Добавить свой отзыв
Написать автору можно на электронную почту mail(аt)compiler.su
|