12

N1570をベースにしたC11用のlex/yacc文法を書き込もうとしています。私の文法のほとんどは、有益な構文の要約から逐語的にコピーされていますが、いくつかのyaccの競合が発生しました。1つを除いて、すべてを解決できました。「_ Atomic」を型指定子として使用する場合と、型修飾子として使用する場合との間には、あいまいさがあります。

指定子の形式では、_Atomicの直後に括弧が続くので、宣言子を括弧で囲むことができるCのあまり使用されていない構文と関係があると思います。これにより、括弧が修飾子の直後に続くようになります。しかし、私の文法は、typedef名を他の識別子と区別する方法をすでに知っているので、yaccはその違いを知っているはずですよね?

私の人生では、それが実際に曖昧になるケースを考えることはできません。

それが役立つとは思えませんが、yaccの-vフラグを使用したときに得られる関連する状態出力は次のとおりです。「ATOMIC」は明らかに「_Atomic」の私のトークン名です

state 23

  152 atomic_type_specifier: ATOMIC . '(' type_name ')'
  156 type_qualifier: ATOMIC .

    '('  shift, and go to state 49

    '('       [reduce using rule 156 (type_qualifier)]
    $default  reduce using rule 156 (type_qualifier)
4

2 に答える 2

9

さて、文法的に曖昧なケースを思い付くことができるかどうかは関係ありません。N1570のセクション6.7.2.4パラグラフ4は、次のように述べています。

_Atomicキーワードの直後に左括弧が続く場合、それは型修飾子としてではなく、型指定子(型名付き)として解釈されます。

これを強制するために、lexルールで_Atomicを指定子として、_Atomicを修飾子として個別のトークンにしただけです。

"_Atomic"/{WHITESPACE}*"(" {return ATOMIC_SPECIFIER;}
"_Atomic"                  {return ATOMIC_QUALIFIER;}

私は一般的にlex/yaccとパーサージェネレーターに比較的慣れていませんが、私の直感はこれは一種のハックだと言っています。同時に、lexの末尾のコンテキスト構文は他に何のためにありますか?

于 2012-05-20T13:20:28.037 に答える
8

はい、仕様にはあいまいさがあると思います。取った

_Atomic int (*f)(int);

ここで、_Atomicは型修飾子です。(関数の戻り型としてはあまり意味がありませんが、有効だと思います)。今、この代替形式を取ります

int _Atomic (*f)(int);

通常、型修飾子はの後に来ることができint、これは他の宣言と同等である必要があります。ただし、現在_Atomicは括弧が後に続くため、型指定子として解釈する必要があり、これは構文エラーになります。*f有効なに置き換えることができる例を作成することさえ可能だと思いますtypedef

6.7.2.4p4の最初のフレーズを見てください

アトミックタイプに関連付けられたプロパティは、左辺値である式に対してのみ意味があります。

_Atomicこれは、戻り型の関数が修飾されることを期待していないことを明確に示しています。

編集:

同じあいまいさが発生します

_Atomic int (*A)[3];

これは完全に理にかなっており(3つのアトミック整数の配列へのポインター)、次のように書き直すことができるはずです。

int _Atomic (*A)[3];

編集2:括弧内に型があるという基準が曖昧さを解消していないことを確認するには、次の有効なC99コードを使用します。

typedef int toto;

int main(void) {
  const int toto(void);
  int const toto(void);
  const int (toto)(void);
  int const (toto)(void);
  return toto();
}

これは、関数としてtoto内部を再宣言mainします。そして、4行すべてが同じ関数の有効なプロトタイプです。_Atomicを修飾子として使用します

typedef int toto;

int main(void) {
  int _Atomic (toto)(void);
  return toto();
}

これは、が付いたバージョンとして有効である必要がありますconst。ここで、_Atomic内部に型が付いた括弧が後に続く場合がありますが、それでも型指定子ではありません。

于 2012-05-19T22:34:03.987 に答える