Что делает синтаксический анализатор для C ++ до тех пор, пока он не сможет различить сравнения и создания шаблонов? - PullRequest
0 голосов
/ 26 октября 2018

После прочтения этого вопроса Мне остается только удивляться, что происходит (относительно AST), когда основные компиляторы C ++ анализируют код следующим образом:

struct foo 
{
  void method() { a<b>c; }

  // a b c may be declared here
};

Они справляются с этим, как с парсером GLR, или по-другому? Какие еще есть способы для анализа этого и подобных случаев?

Например, я думаю, что можно отложить синтаксический анализ тела метода, пока вся структура не будет проанализирована, но действительно ли это возможно и практично?

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

Хотя, безусловно, можно использовать методы GLR для разбора C ++ (см. Ряд ответов Ира Бакстер ), я считаю, что подход, обычно используемый в обычно используемых компиляторах, таких как gcc и clang,именно отсрочка разбора функциональных тел до полного определения класса.(Поскольку исходный код C ++ проходит через препроцессор перед анализом, синтаксический анализатор работает с потоками токенов, и это то, что должно быть сохранено для повторного анализа тела функции. Я не верю, что выполнимо повторный анализ исходного кода.)

Легко узнать, когда определение функции завершено, так как фигурные скобки ({}) должны быть сбалансированы, даже если неизвестно, как вкладываются угловые скобки.

C ++ - не единственный язык, на котором полезно отложить анализ до обработки объявлений.Например, язык, который позволяет пользователям определять новые операторы с различными приоритетами, потребовал бы (пере) анализа всех выражений, когда известны имена и приоритеты операторов.Более патологическим примером является COBOL, в котором приоритет OR в a = b OR c зависит от того, является ли c целым числом (a равно одному из b или c) или логическим (a равно b или c верно).Является ли проектирование языков таким способом хорошей идеей - это другой вопрос.

0 голосов
/ 26 октября 2018

Ответ, очевидно, будет зависеть от компилятора, но в статье Как Энг Бендерский объясняет, как Clang обрабатывает неоднозначность имени типа / переменной C / C ++ , объясняет, как это делает Clang. Я просто отмечу некоторые ключевые моменты из статьи:

  • Clang не нуждается во взломе лексера: информация передается в одном направлении от лексера до парсера

  • Clang знает, когда идентификатор является типом, используя таблицу символов

  • C ++ требует, чтобы объявления были видны во всем классе, даже в коде, который появляется перед ним

  • Clang справляется с этим, выполняя полный анализ / семантический анализ объявления, но оставляя определение на потом; другими словами, он лексируется, но анализируется после того, как все объявленные типы доступны

...