ANSI C - грамматика прямого декларатора. Почему грамматика C допускает синтаксически допустимые, но частично запрещенные объявления, такие как int func () ()? - PullRequest
0 голосов
/ 10 мая 2018

Грамматика ANSI C указывает:

declarator:
    pointer_opt direct-declarator

direct-declarator:
    identifier
    ( declarator )
    direct-declarator [ constant-expression_opt ]
    direct-declarator ( parameter-type-list )
    direct-declarator ( identifier-list_opt )

Согласно этой грамматике можно было бы получить

func()()

в качестве декларатора и

int func()()

как декларация, которая семантически незаконна. Почему грамматика C допускает такие синтаксически допустимые, но сентиментально незаконные объявления?

Ответы [ 3 ]

0 голосов
/ 10 мая 2018

Почему грамматика C допускает такие синтаксически допустимые, но сентиментально недопустимые объявления?

Почему вы считаете разумным ожидать, что синтаксис языка не сможет выразить какие-либо семантически неверные выражения?

Не все семантические проблемы могут быть обнаружены даже во время компиляции (пример: y = 1 / x;, который четко определен, за исключением случаев, когда x равен нулю).Даже формулировка правил синтаксиса, чтобы они не принимали никаких утверждений, объявлений или выражений, которые могут быть семантически неверны во время компиляции, не принесет большой пользы.Это чрезвычайно усложнит правила синтаксиса, что приведет к очень небольшому выигрышу, поскольку компиляторы должны выполнять семантический анализ в любом случае.

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

0 голосов
/ 10 мая 2018

Почему грамматика C допускает синтаксически допустимые, но семантически недопустимые объявления, такие как int func () ()?

Ваш вопрос в основном отвечает сам по себе: Проще говоря, это потому, что это целая работа грамматики * принимать синтаксически допустимые конструкции. Если что-то синтаксически допустимо, но семантически бессмысленно или незаконно, грамматика не должна отвергать ее - она ​​отклоняется позже, во время семантического анализа.

И если вопрос таков: «Почему грамматика не была написана по-другому, так что семантически незаконные конструкции также были синтаксически незаконны (так что грамматика могла их отвергать)?», Ответ заключается в том, что часто возникает вопрос: отвергать вещи во время разбора или во время семантического анализа. Синтаксис объявления C довольно сложный, и есть очевидное желание сделать грамматику, которая воспринимает ее настолько сложной, но не значительно более сложной, чем должна быть. Зачастую вы можете сохранить простоту грамматики, отложив определенные проверки до фазы семантического анализа.

0 голосов
/ 10 мая 2018

На такие вопросы обычно нельзя ответить наверняка, потому что вы запрашиваете информацию о коллективных мыслях и обсуждениях комитета C, в 1989 . Они никогда не занимались разработкой языка полностью публично, как, скажем, люди, ответственные за Python, а тридцать лет назад они делали это еще меньше. И если бы вы опросили их лично, они, вероятно, не помнят.

Мы можем взглянуть на документ C Обоснование (я ссылаюсь на издание, соответствующее C1999, но, насколько я знаю, оно не сильно изменилось с 1989 года) для подсказок, но на быстрое рассмотрение, я не вижу ничего подходящего для вашего вопроса.

Это заставляет меня делать догадки на основе общих принципов проектирования языка программирования. - это общий принцип, соответствующий вашему вопросу: особенно для более старых языков дизайнеры стараются сделать формальный синтаксис максимально свободным от контекста 1012 *. Это значительно облегчает написание эффективного синтаксического анализатора. Правила типа «у вас не может быть функции, которая возвращает функцию» требуют контекста, и поэтому они не входят в синтаксис. Вместо этого легко обрабатывать их как дополнительные ограничения, применяемые к дереву разбора, поэтому дизайнеры так и делают.

В грамматике Си есть целый ряд мест, где этот принцип, похоже, использовался, а не только тот, о котором вы спрашиваете. Например, правило «максимального мунка» для токенизации существует, потому что это означает, что токенизатору не нужно знать о полном контексте синтаксического анализатора, даже если это приводит к неудобным результатам, таким как a-----b интерпретируется как a -- -- - b вместо a -- - -- b, даже если парсер отклонит первое, но примет второе.

Этот принцип разработки для языков программирования часто удивляет начинающих, потому что он настолько отличается от того, как люди понимают естественные языки; мы сделаем все возможное, чтобы «исправить» какое-то контекстуально подходящее значение даже из самых бессмысленных предложений, и мы фактически полагаемся * на это в разговоре. Это может помочь рассмотреть мета-принцип, согласно которому чем хуже, тем лучше (упрощенно, потому что вы можете быстро выполнить первые 90% работы и выполнить ее, а затем повторить оставшиеся 90%) .

...