Анализаторы LR не могут обрабатывать неоднозначные правила грамматики, по дизайну. (Сделал теорию проще еще в 1970-х годах, когда идеи разрабатывались).
C и C++ и позволяют следующее заявление:
x * y ;
Он имеет два различных разборов:
- Это может быть декларация у, как указатель на тип х
- Он может быть умноженным на х и у, отбрасывая ответ.
Теперь вы можете подумать, что последнее глупо и его следует игнорировать. Большинство согласится с вами; однако бывают случаи, когда имеют побочный эффект (например, если умножение перегружено). но это не главное. Точка два разных анализа, поэтому программа может означать разные вещи в зависимости от того, как это должно быть разобрано.
Компилятор должен принять соответствующее в соответствующих обстоятельствах, а при отсутствии какой-либо другой информации (например, знание типа x) должен собираться как для того, чтобы позже решить, что делать. Таким образом, грамматика должна допускать это. И это делает грамматику неоднозначной.
Таким образом, чистый анализ LR не может справиться с этим. Также не могут использоваться многие другие широко доступные генераторы парсеров, такие как Antlr, JavaCC, YACC или традиционный Bison, или даже парсеры PEG, используемые «чистым» способом.
Есть много более сложных случаях (разбор синтаксиса шаблона требует произвольного предпросмотр, в то время как LALR (к) можно смотреть вперед более к лексем), но только он принимает только один контрпример, чтобы сбить чистый LR (или другие) синтаксический анализ.
Большинство реального C/C++ парсеров обрабатывать этот пример, используя некоторый вида детерминированной парсер с дополнительным хаком: они сплетаются разбор с таблицей символов коллекции ... так что к тому времени «х» встречаются, в анализатор знает, является ли x типом или нет, и поэтому выбирает между двумя возможными разборами. Но синтаксический анализатор , который делает это неконфликтным, и парсеров LR (чистые и т. Д.) Являются (в лучшем случае) контекстом бесплатно.
Можно обмануть и добавить семантические проверки временного сокращения в правилах для парсеров LR, чтобы сделать это неоднозначность. (Этот код часто не прост). Большинство других типов парсеров имеют некоторые средства для добавления семантических проверок в разных точках в разбор, которые могут быть использованы для этого.
И если вы достаточно обманываете, вы можете заставить LR-синтаксические анализаторы работать на C и C++. Парни GCC на некоторое время, но дали для ручного разбора, я думаю, потому что они хотели, чтобы улучшила диагностику ошибок.
Там другой подход, хотя, что это хорошее и чистый и разбирает C и C++ просто отлично без таблицы символов повозки, запряженных волов: GLR parsers. Это полные контекстно-свободные парсеры (эффективно бесконечные lookahead).Анализаторы GLR просто принимают как parses, , производя «дерево» (фактически ориентированный ациклический граф, который в основном похож на дерево) , который представляет собой двусмысленный синтаксический анализ. Последующий анализ может разрешить неоднозначность.
Мы используем эту технику в C и C++ фронт заканчивается для нашего DMS Программное обеспечение реинжиниринга Tookit (по состоянию на июнь 2017 года это обрабатывать полный C++ 17 в MS и GNU диалектов). Они были использованы для обработки миллионов строк больших систем C и C++ с полными точными разборами, в которых получают АСТ с полной информацией об исходном коде. (См the AST for C++'s most vexing parse.)
Точно так же: вам нужно понять рекурсию, чтобы узнать рекурсию ;-). – 2008-10-28 13:56:13
«Вы поймете парсеров, как только вы проанализируете эту фразу». – 2009-06-17 02:29:24