Являются ли грамматики C# и Java LALR(x)?

Интересно, грамматики C# и Java LALR(x)? Если да, каково значение х?

Редактировать:

Приняв верный ответ, я думаю, что лучше изменить Q следующим образом:

Есть ли анализатор LALR (x), который мог бы анализировать текущие выпуски Java (версия 7) или C# (версия 4)? Если да, каково значение х?

3 ответа

Решение

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

Возможно, вы имеете в виду грамматику Java, опубликованную в последних спецификациях Java. Вы имеете в виду Java 7?

Я не уверен, что вы можете назначить конкретную грамматику для C#, по крайней мере, для Microsoft, особенно для C# 4.0; Я не верю, что они опубликовали грамматику.

Я могу сказать вам, что я не думаю, что C# может быть LALR(x), потому что он имеет некоторые элементы, которые выглядят как идентификаторы, но могут быть ключевыми словами в определенных контекстах. Это требует, чтобы лексер знал, что ожидает анализатор, чтобы решить, является ли идентифицирующий маркер токен ключевым словом или просто и идентификатором. Таким образом, должна быть обратная связь от парсера к лексеру, или лексер должен произвести оба токена и передать их парсеру, чтобы решить, какой он хочет. Парсеры LALR определяются в потоках токенов без обратной связи, и каждый входной токен имеет только одну интерпретацию.

Я не думаю, что Java, начиная с версии 1.5 и выше, когда enum был представлен как специальный тип со своим собственным ключевым словом. Это связано с тем, что для того, чтобы компиляторы Java 1.5 обрабатывали существующие программы Java 1.4, которые использовали enum в качестве имени переменной, enum должен рассматриваться как ключевое слово в некоторых контекстах и ​​как имя переменной в других. Так что синтаксический анализатор Java 1.5 имеет те же проблемы, что и C#.

С практической точки зрения, настоящие языки не являются LALR(1) [первое издание Java может быть исключением], и любой, кто создает реальный синтаксический анализатор (особенно LALR), должен сделать что-то вроде хака, чтобы обойти это. (GCC лихо анализировал C++ с помощью анализатора LALR с ужасным взломом таблицы символов в течение длительного времени, поэтому он мог определить разницу между идентификатором как переменной и идентификатором как экземпляром typedef. Теперь он имеет своего рода реализованный вручную парсер рекурсивного спуска, но я думаю, что ужасный взлом остается). Поэтому я не уверен, стоит ли отвечать на ваш вопрос.

Наши члены семейства языков C# 4.0 и Java 7 анализируют языки, используя синтаксический анализатор GLR, расширенный как возможностью обратной связи, так и возможностью обрабатывать две интерпретации одного и того же токена. РВО делает вопрос LALR (х) тоо, а обратная связь и множественные интерпретации позволяют нам обрабатывать множество языков, которые были бы вне возможности чистых РВ, тоже.

РЕДАКТИРОВАТЬ: После недолгого размышления может быть действительно уродливый способ заставить обе грамматики обрабатывать свои ключевые слова в контексте. Давайте использовать перечисление Java в качестве примера. Там реально должно быть грамматическое правило:

  type = 'enum' '{'  enum_members '}' ;

Но нам также нужно разрешить enum в качестве идентификатора. Мы можем сделать это, заменивидентификатор токена терминала на нетерминал:

  identifier = IDENTIFIER | 'enum' ;

и настаивать на том, что ИДЕНТИФИКАТОРЫ являются терминалами, произведенными лексером. Теперь, по крайней мере, лексеру не нужно решать, как лечить enum; парсер делает. Но ваша назначенная грамматика должна иметь такую ​​форму, чтобы даже иметь шанс стать LALR (x).

Наши парсеры делали это, чтобы позволить некоторым ключевым словам иногда использоваться в качестве идентификаторов. Мы изменили наш механизм синтаксического анализа, как описано ранее, и больше не делаем этого.

Известно, что грамматика Java (версия 1.0) - LALR(1); этот сайт предоставляет грамматику и начинается с уведомления о том, что

Грамматика была механически проверена, чтобы убедиться, что это LALR(1).

Я не уверен, является ли C# LALR(1), но есть синтаксический анализатор C#, написанный наbison доступно здесь, что говорит о том, что это, вероятно, LALR (1) (при условии, что вы разрешаете объявления приоритетов).

Что бы это ни стоило, обычно LALR (1) - единственный используемый анализатор LALR. Если вам нужно использовать что-то вроде LALR (2) для грамматики, обычно лучше использовать синтаксический анализатор LALR (1) с явным устранением неоднозначности приоритета или более мощный анализатор, такой как анализатор GLR.

Надеюсь это поможет!

По крайней мере, для Java (версия 1.0) это: http://java.sun.com/docs/books/jls/first_edition/html/19.doc.html

Другие вопросы по тегам