Лексический разбор слова - что это такое? Примеры

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

Определенное место среди них занимает лексический анализ слова и текста.

Лексический разбор слова - это всесторонний лексико-семантический и функциональный анализ слова как лексической единицы языка, как объекта его изучения в лексикологии.

Лексический разбор текста - это всесторонний лексико-семантический и функциональный анализ лексических единиц текста (преимущественно художественного), а также их роли в данном тексте.

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

Лексический анализ должен показать все знания студента о слове как лексической единице языка и речи в соответствии с вузовской программой. Поэтому он предложен как вторая (практическая) часть контрольной работы и (или) как вид практического задания на экзамене (в дополнение к теоретическому вопросу), т.к. позволяет проверить знания о предмете изучения всесторонне.

Лексический разбор включает в себя последовательно три этапа (части), соответствующих основным аспектам изучения слова в лексикологии: семантическому, системному и функционально-стилистическому (социолингвистическому) -

1) анализ семантической структуры слова,

2) анализ системных связей слова,

3) функционально-стилистический анализ слова.

Порядок лексического анализа слова

1.СЕМАНТИЧЕСКИЙ АНАЛИЗ

1) Истолковать лексическое значение слова в тексте одним из способов, с указанием способа толкования (описательный, синонимический и т.п.).

2) Выполнить компонентный анализ лексического значения (выделить архисему, дифференциальные и потенциальные семы).

3) Определить тип лексического значения (по разным параметрам: прямое/ переносное, номинативное/ характерологическое, мотивированное/ немотивированное, свободное/ связанное).

4) Определить наличие многозначности слова (в случае многозначности привести другие значения) и омонимии (разграничить полисемию и омонимию).

2. СИСТЕМНЫЙ АНАЛИЗ

5) Определить характер внутрисловных семантических связей слова (эпидигматику): топологический тип полисемии (элементарная, цепочечная, радиальная, смешанная), способы семантической деривации (сужение/ расширение, метафора/ метонимия).

6) Определить характер межсловных деривационных (словообразовательных) связей слова: привести однокоренные слова, определить тип лексической деривации (элементарная, цепочечная, гнездовая).

7) Определить характер парадигматических связей слова: наличие лексико-семантической группы (ЛСГ), гипонимов, синонимов, антонимов, их тип.

8) Определить характер синтагматических связей слова: тип сочетаемости (лексическая, грамматическая), валентность (свободные и контекстуально ограниченные типы связей слова), привести разные типы словосочетаний, в том числе устойчивые (фразеологические) сочетания.

3.ФУНКЦИОНАЛЬНО-СТИЛИСТИЧЕСКИЙ АНАЛИЗ

9) Определить происхождение слова, указать приметы и тип заимствований (освоенные, неосвоенные: экзотизмы, варваризмы).

10) Определить сферу употребления слова: общеупотребительое / необщеупотребительное (диалектное, жаргонное, специальное, просторечие).

11) Определить активность употребления слова: активного / пассивного запаса - устаревшее (архаизм / историзм) или новое (неологизм / окказионализм).

12) Определить стилистическую окраску слова: нейтральное (межстилевое) или стилистически окрашенное - высокое (книжное, поэтическое), сниженное (разговорное, просторечное).

Еще по теме ЛЕКСИЧЕСКИЙ АНАЛИЗ СЛОВА И ТЕКСТА (практика):

  1. А2. Лексические нормы (употребление слова в соответствии с точным лексическим значением и требованием лексической сочетаемости, паронимы).

Лексический анализ

Лексический анализ – это процесс сканирования потока входных символов и разделения его на строки, называемые лексемами. Большинство книг по компиляторам начинаются с этого и посвящают несколько глав обсуждению различных методов построения сканеров. Такой подход имеет свое место, но, как вы уже видели, существуют множество вещей, которые вы можете сделать даже никогда не обращавшись к этому вопросу, и, фактически, сканер, который мы здесь закончим, не очень будет напоминать то, что эти тексты описывают. Причина? Теория компиляторов и, следовательно, программы следующие из нее, должны работать с большинством общих правил синтаксического анализа. Мы же не делаем этого. В реальном мире возможно определить синтаксис языка таким образом, что будет достаточно довольно простого сканера. И как всегда KISS – наш девиз.

Как правило, лексический анализатор создается как отдельная часть компилятора, так что синтаксический анализатор по существу видит только поток входных лексем. Теоретически нет необходимости отделять эту функцию от остальной части синтаксического анализатора. Имеется только один набор синтаксических уравнений, который определяет весь язык, поэтому теоретически мы могли бы написать весь анализатор в одном модуле.

Зачем необходимо разделение? Ответ имеет и теоретическую и практическую основы.

В 1956 Ноам Хомский определил «Иерархию Хомского» для грамматик. Вот они:

Тип 0. Неограниченные (например Английский язык)

Тип 1. Контекстно-зависимые

Тип 2. Контекстно-свободные

Тип 3. Регулярные.

Некоторые характеристики типичных языков программирования (особенно старых, таких как Фортран) относят их к Типу 1, но большая часть всех современных языков программирования может быть описана с использованием только двух последних типов и с ними мы и будем здесь работать.

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

Аналогично грамматики Типа 2 (контекстно-свободные) всегда могут быть анализированы с использованием магазинного автомата (конечный автомат, дополненный стеком). Мы также реализовывали эти машины. Вместо реализации явного стека для выполнения работы мы положились на встроенный стек связанный с рекурсивным кодированием и это фактически является предочтительным способом для нисходящего синтаксического анализа.

Случается что в реальных, практических грамматиках части, которые квалифицируются как регулярные выражения, имеют склонность быть низкоуровневыми частями, как определение идентификатора:

::= [ | ]*

Так как требуется различные виды абстрактных машин для анализа этих двух типов грамматик, есть смысл отделить эти низкоуровневые функции в отдельный модуль, лексический анализатор, который строится на идее конечного автомата. Идея состоит в том, чтобы использовать самый простой метод синтаксического анализа, необходимый для работы.

Имеется другая, более практическая причина для отделения сканера от синтаксического анализатора. Мы хотим думать о входном исходном файле как потоке символов, которые мы обрабатываем справа налево без возвратов. На практике это невозможно. Почти каждый язык имеет некоторые ключевые слова типа IF, WHILE и END. Как я упомянул ранее, в действительности мы не можем знать является ли данная строка ключевым словом до тех пор пока мы не достигнем ее конца, что определено пробелом или другим разделителем. Так что мы должны хранить строку достаточно долго для того, чтобы выяснить имеем мы ключевое слово или нет. Это ограниченная форма перебора с возвратом.

Поэтому структура стандартного компилятора включает разбиение функций низкоуровневого и высокоуровневого синтаксического анализа. Лексический анализатор работает на символьном уровне собирая символы в строки и т.п., и передавая их синтаксическому анализатору как неделимые лексемы. Также считается нормальным позволить сканеру выполнять работу по идентификации ключевых слов.

Из книги Давайте создадим компилятор! автора Креншоу Джек

Лексический анализ Введение В последней главе я оставил вас с компилятором который должен почти работать, за исключением того, что мы все еще ограничены односимвольными токенами. Цель этого урока состоит в том, чтобы избавиться от этого ограничения раз и навсегда. Это

Из книги Модель зрелости процессов разработки программного обеспечения автора Паулк Марк

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

Из книги Интернет решения от доктора Боба автора Сворт Боб

Из книги Объектно-ориентированный анализ и проектирование с примерами приложений на С++ автора Буч Гради

7.2.4. Измерения и анализ Ключевые практики раздела «Измерения и анализ» описывают основные методы измерений, необходимых для определения статуса операций, относящихся к разделу «Выполняемые действия». Являясь неотъемлемой частью группы ключевых процессов, измерения

Из книги Технологии программирования автора Камаев В А

Измерения и анализ Измерение 1. Выполнение измерений и использование их результатов для определения состояния работ по управлению конфигурацией.Примеры измерений:количество запросов на изменение, обрабатываемое за единицу времени;выполнение этапов работ по

Из книги C++. Сборник рецептов автора Диггинс Кристофер

Измерения и анализ Измерение 1. Выполнение измерений и использование их результатов для определения статуса мероприятий по разработке и усовершенствованию производственного процесса организации.Примеры измерений:определение объема выполненных работ по оценке,

Из книги 1С: Бухгалтерия 8 с нуля. 100 уроков для начинающих автора Гладкий Алексей Анатольевич

Измерения и анализ Измерение 1. Выполнение измерений и использование их результатов для выяснения состояния работ по определению производственного процесса организации.Примеры измерений:статус выполнения этапов календарного плана разработки и сопровождения

Из книги автора

Из книги автора

8.1. Анализ Определение границ рассматриваемой задачи Врезка ознакомила вас с требованиями к системе мониторинга погоды. Это довольно простая задача, решение которой позволяет обойтись всего несколькими классами. Инженер, не вполне искушенный во всех особенностях

Из книги автора

9.1. Анализ Определение границ проблемной области На врезке представлены детально сформулированные требования к библиотеке базовых классов. К сожалению, эти требования навряд ли практически выполнимы: библиотека, содержащая абстракции, необходимые для всех возможных

Из книги автора

10.1. Анализ Определение границ задачи Требования к системе складского учета показаны на врезке. Это достаточно сложная программная система, затрагивающая все аспекты, связанные с движением товара на склад и со склада. Для хранения продукции служит, естественно, реальный

Из книги автора

11.1. Анализ Определение границ предметной области Как сказано во врезке, мы намерены заняться криптоанализом - процессом преобразования зашифрованного текста в обычный. В общем случае процесс дешифровки является чрезвычайно сложным и не поддается даже самым мощным

Из книги автора

12.1. Анализ Определение границ проблемной области Для большинства люден, живущих в США, поезда являются символом давно ушедшей эпохи. В Европе и странах Востока ситуация совершенно противоположная. В отличие от США, в Европе мало национальных и международных

Из книги автора

2.4. АНАЛИЗ ТРЕБОВАНИЙ К СИСТЕМЕ (СИСТЕМНЫЙ АНАЛИЗ) И ФОРМУЛИРОВКА ЦЕЛЕЙ Задача оптимизации разработки программ состоит в достижении целей при минимально возможной затрате ресурсов.Системный анализ в отличие от предварительного системного исследования - это

Из книги автора

3.5. Лексический анализ строки, содержащей число в экспоненциальной форме ПроблемаИмеется строка, содержащая число в экспоненциальной форме, и требуется сохранить значение числа в переменной типа double.РешениеНаиболее простым способом анализа числа в экспоненциальной

Из книги автора

Урок № 96. Анализ счета и анализ субконто Анализ счета также относится к числу популярных отчетов программы "1С". Чтобы сформировать этот отчет, нужно выполнить команду главного меню Отчеты | Анализ счета, затем в открывшемся окне указать отчетный период, счет и

ЛАБОРАТОРНАЯ РАБОТА 3. ИЗУЧЕНИЕ ЭТАПА ЛЕКСИЧЕСКОГО АНАЛИЗА ТРАНСЛЯТОРОВ ЯЗЫКОВ ПРОГРАММИРОВАНИЯ

Цель работы: Изучить методы построения лексических сканеров на основе конечных автоматов и формальных грамматик.

Архитектура компилятора

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

Препроцессирование;

Лексический анализ;

Синтаксический анализ;

Генерация кода;

Оптимизация программы.

Рассмотрим более подробно этап лексического анализа. Программа, которая выполняет этот этап называется лексический анализатор или сканер. Сканер переводит текст исходной программы из последовательности символов или строк в последовательность лексем. Лексема - минимальный элемент языка программирования. Для заданного языка программирования число типов лексем предполагается конечным.

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

Лексический анализ

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

После того как лексическая единица классифицирована как "возможный идентификатор", опрашивается таблица идентификаторов, если такого в таблице еще нет, то создается новый элемент. Остальная информация в таблицу заносится последующими фазами.

Числа, строки символов заключенные в кавычки и другие самоопределенные данные классифицируются как "литералы". Информация о них заносится в таблицу литералов. В отличие от идентификаторов литералы позволяют определить их атрибуты.

Рассмотрим пример построения описанных таблиц при компиляции следующей программы:

char * b=".dat";

Таблица терминальных символов(TRM). Таблица стандартных символов.

Символ Разделитель Другие Тип Индекс Строка программы
; TRM main
( TRM (
) TRM )
, TRM {
main TRM int
int IDN a
{ TRM ;
} TRM char
= TRM *
+ IDN b
* TRM =
char TRM "
" LTR .dat
TRM "
IDN a
TRM =
IDN a
TRM +
LTR
TRM ;
TRM }

Таблица идентификаторов (IDN). Таблица литералов (LTR).

Рассмотренные выше таблицы демонстрируют основные правила построения. Таблица терминальных символов уже заложена в компиляторе и в данном случае ее содержимое построено конкретно для примера.

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



Языки программирования высокого уровня имеют структуру вложенных блоков и процедур. Один и тот же идентификатор может быть описан и использован в разных блоках. Правило нахождения соответствующего идентификатору описания состоит в том, чтобы сначала просмотреть текущий блок (в котором идентификатор используется), затем объемлющий блок и т.д. пока не будет найдено описание данного идентификатора. Для этого используется список блоков.

Таблица блоков.

Лексический сканер должен учитывать области видимости и кодировать их по-разному.

Содержание задания: Разработать программу лексического сканирования и анализа для заданных языка программирования и типов лексем. Программа должна построить заданные таблицы и на их основе преобразовать анализируемую программу, заменив искомые лексемы на мнемонические имена. Мнемонические имена должны генерироваться так, чтобы любая лексема заменялась уникальным именем, а имя отражало ее тип (например, I1 - первая лексема целого типа).

Лексический анализ

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

Задачи и функционирование блока лексического анализа

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

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

Дескриптор -- это пара вида: (<тип лексемы>, <указатель>), где <тип лексемы> -- это, как правило, числовой код класса лексемы, который означает, что лексема принадлежит одному из конечного множества классов слов, выделенных в языке программирования;

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

Множество классов лексем (т.е. различных видов слов) в языках программирования может быть различным. Наиболее распространенными классами являются:идентификаторы;

служебные (ключевые) слова;

разделители;

константы.

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

С этих позиций коды образов лексем (дескрипторов) из конечных классов всегда одни и те же в различных программах для данного компилятора. Коды же образов лексем из бесконечных классов различны для разных программ и формируются каждый раз на этапе лексического анализа.

В ходе лексического анализа значения лексем из бесконечных классов помещаются в таблицы соответствующих классов. Конечность таблиц объясняет ограничения, существующие в языках программирования на длины (и, соответственно, число) используемых в программе идентификаторов и констант. Необходимо отметить, что числовые константы перед помещением их в таблицу могут переводиться из внешнего символьного во внутреннее машинное представление. Содержимое таблиц, в особенности таблицы идентификаторов, в дальнейшем пополняется на этапе семантического анализа исходной программы и используется на этапе генерации объектной программы.

Рассмотрим основные идеи, которые лежат в основе построения лексического анализатора, проблемы, возникающие при его работе, и подходы к их устранению.

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

После этого (или параллельно с этим) проводится идентификация лексемы. Она заключается в сборке лексемы из символов, начиная с выделенного на предыдущем этапе, и проверки правильности записи лексемы данного класса.

Идентификация лексемы из конечного класса выполняется путем сравнения ее с эталонным значением. Основная проблема здесь -- минимизация времени поиска эталона. В общем случае может понадобиться полный перебор слов данного класса, в особенности для случая, когда выделенное для опознания слово содержит ошибку. Уменьшить время поиска можно, используя различные методы ускоренного поиска:

метод линейного списка;

метод упорядоченного списка;

метод расстановки и другие.

Для идентификации лексем из бесконечных (очень больших) классов используются специальные методы сборки лексем с одновременной проверкой правильности написания лексемы. При построении этих алгоритмов широко применяется формальный математический аппарат -- теория регулярных языков, грамматик и конечных распознавателей.

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

Для проведения успешной идентификации лексемы формируется ее дескриптор, он помещается в выходной поток лексического анализатора, в случае неуспешной идентификации формируются сообщения об ошибке.

На этапе лексического анализа могут выполняться и другие виды лексического юнтроля, в частности, проверяется парность скобок и других парных конструкций. Выходной поток с лексического анализатора в дальнейшем поступает на вход синтаксического анализатора. Имеется две возможности их связи: раздельная связь, при которой выход лексического анализатора формируется полностью и затем передается синтаксическому анализатору; нераздельная связь, когда синтаксическому анализатору требуется очередной образ лексемы, он вызывает лексический анализатор, который генерирует требуемый дескриптор и возвращает управление синтаксическому анализатору.

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

10 --- ключевое слово; 20 -- разделитель; 30 -- идентификатор; 40 -- константа.

Вход лексического анализатора имеет вид:

var x,y,z: real;

Внутренние таблицы лексического анализатора имеют вид:

Таблица ключевых слов

Таблица идентификаторов

Таблица констант

Константа

Выходом лексического анализатора является следующий дескрипторный текст:

(10.1)(30,1) (20,1)

(10,6) (30,2) (20,2) (30,3) (20,2) (30,4) (20,7) (10,5) (20,1) (10,2)

(20,7) (20,8) (40,1) (20,1)

(20,7) (20,8) (40,1) (20,1)

(20,7) (20,8) (30,2) (20,3) (30,3) (20,1)

Однако, основной задачей ЛА является не порождение лексических единиц, а их распознавание. Математической моделью процесса распознавания регулярного языка является вычислительное устройство, которое называется конечным автоматом (КА). Термин «конечный» подчеркивает то, что вычислительное устройство имеет фиксированный и конечный объем памяти и обрабатывает последовательность входных символов, принадлежащих некоторому конечному множеству. Существуют различные типы КА, если функцией выхода КА (результатом работы) является лишь указание на то, допустима или нет входная последовательность символов, такой КА называют конечным распознавателем. Именно этот тип КА в дальнейшем мы и будем рассматривать.

Конечный автомат описывается следующим образом:

А = ,

где V = {а 1 , а 2 ,..., а m } -- входной алфавит (конечное множество символов);

Q = { q 0 , q 1 ,..., q n-1 } -- алфавит состояний (конечное множество символов);

8: Q х V -> Q -- функция переходов;

q 0 Q -- начальное состояние конечного автомата;

F Q -- множество заключительных состояний.

Имеется бесконечная лента, разбитая на ячейки, в каждой из которых может находиться один символ из V. На ленте записана цепочка а V*. Ячейки слева и справа от цепочки не заполнены. Имеется конечное устройство управления (УУ) с читающей головкой, которое может последовательно считывать символы с ленты, передвигаясь вдоль ленты слева направо. При этом УУ может находиться в каком-либо одном состоянии из Q. Начинает свою работу УУ всегда в начальном состоянии q o Q, а завершает в одном из заключительных состояний F. Каждый раз, переходя к новой ячейке на ленте, УУ переходит в соответствии с функцией переходов. Функцию переходов КА можно представить различными способами. Основные из них: совокупность команд; диаграмма состояний; матрица переходов.

Для КС-языков устройствами распознавания языка являются магазинные автоматы (или, иначе, автоматы с магазинной памятью, МП-автоматы).

Автомат имеет конечное множество состояний, конечное множество входных символов и неограниченную снизу вспомогательную ленту (называемую лентой магазинной памяти или магазинной памятью). «Дно» магазина (самый нижний символ) отмечается специальным символом, называемым маркером дна. Магазинная память определяется свойством «первым введен -- последним выведен». При записи символа в магазин, его содержимое сдвигается на одну ячейку «вниз», а на освободившееся место записывается требуемый символ. Обработку входной цепочки МП-автомат начинает в некотором выделенном состоянии при определенном содержимом магазина. Затем автомат выполняет операции, задаваемые его управляющим устройством. При этом выполняется либо завершение обработки, либо переход в новое состояние. Если синтаксический анализатор выполняется переход, то он дает новый верхний символ магазина, новый текущий символ, автомат переходит в новое состояние и цикл работы автомата повторяется. Итогом работы МП-автомата при обработке лексемы является ответ на вопрос: «принадлежит данная лексема данному языку или нет?». В общем виде может быть предложен следующий порядок конструирования ЛА:

Выделить во входном языке множество классов лексем.

Построить для каждого класса лексем грамматику.

Построить модель распознавателя.

Выбрать формат кодов лексем-дескрипторов.

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

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

Как правило, лексический анализатор создается как отдельная часть компилятора, так что синтаксический анализатор по существу видит только поток входных лексем. Теоретически нет необходимости отделять эту функцию от остальной части синтаксического анализатора. Имеется только один набор синтаксических уравнений, который определяет весь язык, поэтому теоретически мы могли бы написать весь анализатор в одном модуле.

Зачем необходимо разделение? Ответ имеет и теоретическую и практическую основы.

В 1956 Ноам Хомский определил «Иерархию Хомского» для грамматик. Вот они:

Тип 0. Неограниченные (например Английский язык)

Тип 1. Контекстно-зависимые

Тип 2. Контекстно-свободные

Тип 3. Регулярные.

Некоторые характеристики типичных языков программирования (особенно старых, таких как Фортран) относят их к Типу 1, но большая часть всех современных языков программирования может быть описана с использованием только двух последних типов и с ними мы и будем здесь работать.

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

Аналогично грамматики Типа 2 (контекстно-свободные) всегда могут быть анализированы с использованием магазинного автомата (конечный автомат, дополненный стеком). Мы также реализовывали эти машины. Вместо реализации явного стека для выполнения работы мы положились на встроенный стек связанный с рекурсивным кодированием и это фактически является предочтительным способом для нисходящего синтаксического анализа.

Случается что в реальных, практических грамматиках части, которые квалифицируются как регулярные выражения, имеют склонность быть низкоуровневыми частями, как определение идентификатора:

Так как требуется различные виды абстрактных машин для анализа этих двух типов грамматик, есть смысл отделить эти низкоуровневые функции в отдельный модуль, лексический анализатор, который строится на идее конечного автомата. Идея состоит в том, чтобы использовать самый простой метод синтаксического анализа, необходимый для работы.

Имеется другая, более практическая причина для отделения сканера от синтаксического анализатора. Мы хотим думать о входном исходном файле как потоке символов, которые мы обрабатываем справа налево без возвратов. На практике это невозможно. Почти каждый язык имеет некоторые ключевые слова типа IF, WHILE и END. Как я упомянул ранее, в действительности мы не можем знать является ли данная строка ключевым словом до тех пор пока мы не достигнем ее конца, что определено пробелом или другим разделителем. Так что мы должны хранить строку достаточно долго для того, чтобы выяснить имеем мы ключевое слово или нет. Это ограниченная форма перебора с возвратом.

Поэтому структура стандартного компилятора включает разбиение функций низкоуровневого и высокоуровневого синтаксического анализа. Лексический анализатор работает на символьном уровне собирая символы в строки и т.п., и передавая их синтаксическому анализатору как неделимые лексемы. Также считается нормальным позволить сканеру выполнять работу по идентификации ключевых слов.