Подскажите парсеры С++ строят абстрактно синтаксическое дерево зная имена всех типов или нет? то есть если написано int a; то при обработке парсером он знает что это тип?
Ну, обычно информация о типах в компиляторах появляется на этапе семантической проверки, позже парсинга. Можно, конечно, погуглить на эту тему, но после парсинга у тебя будут только идентификаторы, и в случае с int кейворды.
Из-за шаблонов в целом это нетривиально, например существует такой забавный факт, что парсинг программы на C++ алгоритмически неразрешим: https://blog.reverberate.org/2013/08/parsing-c-is-literally-undecidable.html Звучит весьма грозно и страшно, но на деле это означает, что можно состряпать из шаблонов зацикленную шнягу, которая на абстрактной машине Тьюринга зациклится/зависнет, а реальный компилятор выплюнет ошибку компиляции из-за превышения некой максимальной (заданной авторами компилятора) глубины вложенности шаблонов. Но в целом да, АСД делается и замуты с шаблонами решаются.
Современные компиляторы выводят все ошибки по парядку (а не сначало ошибки лексера, потом парсера, потом генерации кода) Что наводит на мысль что парсер как-то объединён с генератором кода.
Ну потому что. Смотрел хоть один компилятор в последние лет 15? Между лексером и кодогенератором там столько независимых друг от друга фаз может быть. Вообще, приведи пример, о какой конкретно ошибке ты говоришь. --- Сообщение объединено, 20 мар 2022 --- Образно, не обязательно прям такой порядок, но: Лексер -> Парсер -> Проверка семантики -> Оптимизация AST (много независимых фаз) -> Генерация IR (GIMPLE в GCC, LLVM IR в Clang) -> Тонна разных оптимизаций, независимых друг от друга -> Генератор кода. Фейлить у тебя обычно будут первые три этапа. Хотя не знаю, что можно написать, чтобы именно лексер прям зафейлил.
Проверил у себя на GCC и ничего подобного. Ошибка препроцессора, например, прерывает компиляцию и до ошибок компилятора даже не доходит.
Проверил - и да, действительно GCC выводит несколько ошибок, но как раз не по порядку. Сперва он ругается на незакрытую скобку, а потом на ошибку семантики и в моём случае еще одна ошибка под незакрытой скобкой. Т.е. сперва ругнулся лексер, но он всё-равно то что смог наскрести отправил в парсер и далее уже ругается еще и парсер.
Код (Text): #include <stdio.h> int main(int argc, char** argv) { int t = 0; int a = 0; char* s = NULL; a = t++t++a; s = " } Код (Text): test.c: В функции «main»: test.c:8:12: ошибка: expected «;» before «t» 8 | a = t++t++a; | ^ | ; test.c:10:9: предупреждение: отсутствует завершающий символ " 10 | s = " | ^ test.c:10:9: ошибка: отсутствует терминирующий символ " test.c:11:1: ошибка: expected expression before «}» token 11 | } | ^ Так а чего ему все ошибки не выводить и не делать это по порядку? Ворнинг исходит от препроцессора, так как тот тоже на токены пытается разбивать код. Остальные - ошибки парсера. Причем тут вообще семантика и тем более генератор кода? Просто в принципе нет узла AST для t++t++a, во что он должен был это распарсить по вашему, как это должно было дойти до проверки семантики и других этапов? Или вопрос в том, почему лексер не зафейлил? --- Сообщение объединено, 26 мар 2022 --- https://github.com/gcc-mirror/gcc/blob/16e2427f50c208dfe07d07f18009969502c25dc8/libcpp/lex.c#L2078 - хотя, может быть для C/C++ лексеров - это нормально, что нет закрывающей кавычки. CPP_DL_PEDWARN - по-умолчанию предупреждение, ошибка только при -pedantic-errors или -Werror: https://github.com/gcc-mirror/gcc/b...8009969502c25dc8/libcpp/include/cpplib.h#L574 (если он не видит терминирующую кавычку, то тип токена просто становится CPP_OTHER вместо строки или символа, и эту ситуацию, видимо, парсер должен разруливать). --- Сообщение объединено, 26 мар 2022 --- Код (Text): # gcc -pedantic-errors test.c test.c: В функции «main»: test.c:8:12: ошибка: expected «;» before «t» 8 | a = t++t++a; | ^ | ; test.c:10:9: ошибка: отсутствует завершающий символ " 10 | s = " | ^ test.c:10:9: ошибка: отсутствует терминирующий символ " test.c:11:1: ошибка: expected expression before «}» token 11 | } | ^ Предупреждение превратилось в ошибку, но все равно токен дошел до парсера и там же стал ошибкой второй раз.