как понять стандартный синтаксис C99

Я не совсем понимаю, что означает синтаксис в C99. Здесь, говоря C99, я имею в виду ISO/IEC 9899:1999. Ну, я думаю, что синтаксическая часть грамматики не сильно изменилась со времен ANSI C, C89.

Возьмите пример из этого вопроса:

6.5.5 Multiplicative operators
  Syntax
    multiplicative-expression:
      cast-expression
      multiplicative-expression * cast-expression
      multiplicative-expression / cast-expression
      multiplicative-expression % cast-expression

  Constraints

Each of the operands shall have arithmetic type. The operands of the % operator
shall have integer type.

  Semantics

The usual arithmetic conversions are performed on the operands.
The result of the binary * operator is the product of the operands.
The result of the / operator is the quotient 

Интересно, почему в синтаксисе мультипликативных операторов у нас есть «приведение-выражение»? И какую грамматику может означать этот синтаксис? В этом вопросе @Avi сказал, что в

a*b*c

«c должен анализироваться как выражение приведения», я не совсем понимаю это.

Возьмите другой пример из c99 6.6.1, синтаксис константных выражений

Syntax
   constant-expression:
       conditional-expression

почему это условное выражение появилось здесь? Может кто-нибудь показать мне, как объяснить этот синтаксис? Спасибо всем заранее.


person Allan Ruin    schedule 25.04.2012    source источник


Ответы (2)


Интересно, почему в синтаксисе мультипликативных операторов у нас есть «приведение-выражение»?

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

Итак, как это будет работать:

  1. Группировка операторов с одинаковым приоритетом:

    1*2*3*4
    

    в этом случае возможны следующие возможности группировки (только верхний уровень):

    • 1*(2*3*4)
    • (1*2)*(3*4)
    • (1*2*3)*4

    Глядя на грамматику, мы знаем, что все, что стоит слева от *, должно быть cast-expression, то есть не должно содержать (без скобок) *. Следовательно, возможен только третий вариант

  2. Приоритет. Представьте себе выражение

    a*b+c
    

    Это может быть проанализировано как

    • (a*b)+c
    • a*(b+c)

    Однако мы знаем, что cast-expression в правой части не может содержать (без скобок) + (или мы можем понять это из грамматики, если проверим ее). Это оставляет первый вариант как единственно возможную альтернативу.

    Другое выражение

    a+b*c
    

    может быть, в свою очередь, проанализировано как

    • (a+b)*c
    • a+(b*c)

    Однако multiplicative-expression слева от * также не может содержать (без скобок) + (оставлено в качестве упражнения для читателя). Следовательно, возможен только второй вариант.

На ваш вопрос об условном выражении: правило грамматики просто запрещает анализировать любые эквивалентные или ниже операторов присваивания как constant-expressions. Следовательно, a=b, a,b, a+=b не могут быть константными выражениями, а a+b, a[b] и a(b) могут быть. Обратите внимание, что это не запрещает, например. (a=b); вы должны смотреть на фактическое предложение, определяющее, что такое константные выражения, что ограничивает область константных выражений больше, чем грамматика.

person jpalecek    schedule 25.04.2012
comment
Я вижу, что если мы просто возьмем cast-expression как некоторое выражение, которое не является multiplicative-expression, то мы сможем узнать ассоциативность мультипликативного выражения. Но само выражение cast имеет синтаксис в c99 6.5.4.1, нам не нужно гарантировать, что 'c' в выражении примера равно cast-expression? Не могли бы вы немного рассказать о части conditional-expression? - person Allan Ruin; 25.04.2012
comment
Это означает, что мы можем просто изменить cast-expression на conditional-expression? - person Allan Ruin; 25.04.2012
comment
Операторы приведения просто представляют собой серию операторов с приоритетом на один выше, чем у мультипликативных операторов. Вся глава стандарта о приоритетах операторов построена таким же образом. Да, это довольно неясно и запутанно, как и вся глава, посвященная выражениям в стандарте. - person Lundin; 25.04.2012
comment
@AllanRuin: Но у самого выражения cast есть синтаксис в c99 6.5.4.1, нам не нужно гарантировать, что «c» в выражении примера является выражением cast? Конечно нужен. Затем мы смотрим на стандарт и видим, что cast-expression -> unary-expression, unary-expression -> postfix-expression, postfix-expression -> primary-expression и primary-expression -> identifier (-> означает, что его можно переписать). c — это идентификатор, поэтому его можно проанализировать как cast-expression. - person jpalecek; 25.04.2012

Интересно, почему в синтаксисе мультипликативных операторов у нас есть «приведение-выражение»?

Начнем с гораздо более простой задачи и, соответственно, более простой грамматики. Мы определим грамматику для представления простого арифметического выражения (1 + 2, 3 * (4 - 2), 42 и т. д.). Поскольку мы хотим, чтобы обычная числовая константа была допустимым выражением, мы должны определить нашу грамматику так, чтобы был путь от корневого нетерминального выражения к простому числу:

expression:
    term  |
    term add-op expression

term:
    factor |
    factor mul-op term

factor:
    number |
    ( expression ) 

Нетерминалы, такие как number, add-op и mul-op, должны быть очевидны.

42 – это число, которое является произведением фактора, которое является произведением term, которое является произведением выражения< /эм>. Таким образом, 42 является допустимым арифметическим выражением в соответствии с нашей грамматикой; term и factor являются промежуточными продуктами на этом пути.

То же самое происходит и в грамматике Си. приведение-выражение — это промежуточный результат между выражением и некоторым терминалом, например идентификатором или числовой константой. Наша простая грамматика определяет 2 уровня приоритета; грамматика C определяет 16 различных уровней приоритета с большим количеством операторов, поэтому на этом пути гораздо больше промежуточных производств. И мы хотим, чтобы приведение-выражение имело более высокий уровень приоритета, чем мультипликативное-выражение, чтобы мы могли обрабатывать такие случаи, как

x = a * (int) b;

правильно.

person John Bode    schedule 25.04.2012