Что такое лексический и синтаксический анализ в процессе составления. Происходит ли предварительная обработка после лексического и синтаксического анализа?
Что такое лексический и синтаксический анализ в процессе компиляции в C Compiler?
Ответы (5)
Рассмотрим этот код:
int a = 10;
if (a < 4)
{
printf("%d", a);
}
На этапе Лексический анализ: вы определяете каждое слово/токен и присваиваете ему значение. В приведенном выше коде вы начинаете с определения, что i, за которым следует n, затем t, а затем пробел — это слово int< /strong>, и что это ключевое слово языка;1, за которым следует 0, а пробел — это число 10 и так далее.
На этапе Синтаксический анализ вы проверяете, соответствует ли код синтаксису языка (правилам грамматики). Например, вы проверяете, есть ли только одна переменная в левой части оператора (учитывая язык C), что каждое выражение завершается символом ;, что следует if с помощью условного/логического оператора и т. д.
Как уже упоминалось, обычно предварительная обработка происходит перед лексическим или синтаксическим анализом.
Лексический анализ выполняется ДО синтаксического анализа. Это логично, так как при вызове макроса необходимо сначала определить границы идентификатора. Это делается с помощью лексического анализа. После этого начинается синтаксический анализ. Обратите внимание, что компиляторы обычно не создают полностью предварительно обработанный исходный код перед началом синтаксического анализа. Они читают источник, выбирая по одной лексеме за раз, при необходимости выполняют предварительную обработку и передают результат синтаксическому анализу.
В одном случае лексический анализ происходит дважды. Это буферизация пасты. Посмотрите на код:
#define En(x) Abcd ## x ## x
enum En(5)
{
a, b = 20, c, d
};
Этот код определяет перечисление с именем Abcd55
. Когда ##
обрабатываются во время раскрытия макроса, данные помещаются во внутренний буфер. После этого этот буфер сканируется так же, как небольшой #include. Во время сканирования компилятор разобьёт содержимое буфера на лексемы. Может случиться так, что границы отсканированных лексем не совпадут с границами исходных лексем, помещенных в буфер. В приведенном выше примере в буфер помещаются 3 лексемы, но извлекается только одна.
Предварительная обработка происходит перед лексическим анализом Комментарии iirc отфильтровываются, #define, ... и после этого компилятор генерирует токены с помощью сканера/лексера (лексический анализ). После этого компиляторы генерируют деревья разбора, которые служат для синтаксического анализа.
Бывают исключения, но обычно это происходит так:
- Предварительная обработка - преобразование текста программы в текст программы
- Лексический анализ - преобразование текста программы в «токены», которые по сути представляют собой небольшие целые числа с прикрепленными атрибутами.
- Синтаксический анализ - преобразование текста программы в абстрактный синтаксис
Определение «абстрактного синтаксиса» может варьироваться. В однопроходных компиляторах абстрактный синтаксис равен целевому коду. Но в наши дни обычно это дерево или DAG, которые логически представляют структуру программы.
Когда мы говорим о языке программирования C, мы должны отметить, что для этого языка существует стандарт ISO (ANSI). Вот последний общедоступный проект C99 (ISO/IEC 9899:1999): www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf
Существует раздел «5.1.1.2 Фазы перевода», в котором говорится, как следует анализировать программу C. Есть этапы:
... некоторые шаги для многобайтовой обработки, триграфа и обратной косой черты...
3). Исходный файл разбивается на токены предварительной обработки и последовательности пробельных символов (включая комментарии).
Это лексический анализ для предварительной обработки. Здесь лексируются только директивы препроцессора, знаки препинания, строковые константы, идентификаторы, комментарии.
4). Выполняются директивы предварительной обработки, расширены вызовы макросов
Это сама предварительная обработка. На этом этапе также будут включены файлы из #include
, а затем будут удалены директивы предварительной обработки (например, #define
или #ifdef
и другие).
... обработка строковых литералов...
7). Пробелы, разделяющие токены, больше не имеют значения. Каждый токен предварительной обработки преобразуется в токен. Полученные токены синтаксически и семантически анализируются и переводятся как единица перевода.
Преобразование в токен означает обнаружение ключевых слов языка и обнаружение констант. Это этап окончательного лексического анализа; синтаксический и семантический анализ.
Итак, ваш вопрос был:
Происходит ли предварительная обработка после лексического и синтаксического анализа?
Для предварительной обработки необходим некоторый лексический анализ, поэтому порядок следующий: lexical_for_preprocessor, preprocessing, true_lexical, other_analysis.
PS: Настоящий компилятор C может быть организован немного по-другому, но он должен вести себя так же, как написано в стандарте.